1479 lines
46 KiB
C++
1479 lines
46 KiB
C++
|
/******************************************************************************
|
||
|
|
||
|
Copyright (C) Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
Handle.CPP
|
||
|
|
||
|
Abstract:
|
||
|
This module deals with Query functionality of OpenFiles.exe
|
||
|
NT command line utility. This module will specifically query open files
|
||
|
for local system.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Akhil Gokhale (akhil.gokhale@wipro.com) 25-APRIL-2000
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
Akhil Gokhale (akhil.gokhale@wipro.com) 25-APRIL-2000 : Created It.
|
||
|
|
||
|
|
||
|
*****************************************************************************/
|
||
|
#include "pch.h"
|
||
|
#include "OpenFiles.h"
|
||
|
#define MAX_POSSIBLE_DRIVES 26 // maximum possible drives are A,B....Y,Z
|
||
|
#define RTL_NEW( p ) RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *p ) )
|
||
|
#define RTL_FREE(p) \
|
||
|
if(p!=NULL)\
|
||
|
{\
|
||
|
RtlFreeHeap( RtlProcessHeap(), 0, p);\
|
||
|
p = NULL;\
|
||
|
}\
|
||
|
1
|
||
|
|
||
|
#define MAX_TYPE_NAMES 128
|
||
|
struct DriveTypeInfo
|
||
|
{
|
||
|
TCHAR szDrive[4];
|
||
|
UINT uiDriveType;
|
||
|
BOOL bDrivePresent;
|
||
|
};
|
||
|
|
||
|
BOOLEAN fAnonymousToo;
|
||
|
HANDLE ProcessId;
|
||
|
WCHAR TypeName[ MAX_TYPE_NAMES ];
|
||
|
WCHAR SearchName[ 512 ];
|
||
|
CHAR OutputFileName[ MAX_PATH ];
|
||
|
HANDLE OutputFile;
|
||
|
HKEY hKey;
|
||
|
CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
|
||
|
HANDLE hStdHandle;
|
||
|
|
||
|
typedef struct _PROCESS_INFO
|
||
|
{
|
||
|
LIST_ENTRY Entry;
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
||
|
PSYSTEM_THREAD_INFORMATION ThreadInfo[ 1 ];
|
||
|
} PROCESS_INFO, *PPROCESS_INFO;
|
||
|
|
||
|
LIST_ENTRY ProcessListHead;
|
||
|
|
||
|
PSYSTEM_OBJECTTYPE_INFORMATION ObjectInformation;
|
||
|
PSYSTEM_HANDLE_INFORMATION_EX HandleInformation;
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInformation;
|
||
|
|
||
|
typedef struct _TYPE_COUNT
|
||
|
{
|
||
|
UNICODE_STRING TypeName ;
|
||
|
ULONG HandleCount ;
|
||
|
} TYPE_COUNT, * PTYPE_COUNT ;
|
||
|
|
||
|
|
||
|
TYPE_COUNT TypeCounts[ MAX_TYPE_NAMES + 1 ] ;
|
||
|
|
||
|
UNICODE_STRING UnknownTypeIndex;
|
||
|
|
||
|
// Local function decleration
|
||
|
PRTL_DEBUG_INFORMATION RtlQuerySystemDebugInformation(void);
|
||
|
BOOLEAN LoadSystemModules(PRTL_DEBUG_INFORMATION Buffer);
|
||
|
BOOLEAN LoadSystemObjects(PRTL_DEBUG_INFORMATION Buffer);
|
||
|
BOOLEAN LoadSystemHandles(PRTL_DEBUG_INFORMATION Buffer);
|
||
|
BOOLEAN LoadSystemProcesses(PRTL_DEBUG_INFORMATION Buffer);
|
||
|
PSYSTEM_PROCESS_INFORMATION FindProcessInfoForCid(IN HANDLE UniqueProcessId);
|
||
|
|
||
|
VOID DumpHandles( DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose);
|
||
|
BOOL GetCompleteFileName(LPCTSTR pszSourceFile,LPTSTR pszFinalPath,struct DriveTypeInfo *pdrvInfo,DWORD dwTotalDrives,LPCTSTR pszCurrentDirectory,LPCTSTR pszSystemDirectory,PBOOL pAppendToCache) ;
|
||
|
void FormatFileName(LPTSTR pFileName,DWORD dwFormat,LONG dwColWidth);
|
||
|
void PrintProgressMsg(HANDLE hOutput,LPCWSTR pwszMsg,const CONSOLE_SCREEN_BUFFER_INFO& csbi);
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This function will change an ansi string to UNICODE string
|
||
|
|
||
|
Arguments:
|
||
|
[in] Source : Source string
|
||
|
[out] Destination : Destination string
|
||
|
[in] NumberOfChars : No of character in source string
|
||
|
Return Value:
|
||
|
BOOL TRUE : Successfully conversion
|
||
|
FALSE: Unsuccessful
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOLEAN
|
||
|
AnsiToUnicode(
|
||
|
LPCSTR Source,
|
||
|
PWSTR Destination,
|
||
|
ULONG NumberOfChars
|
||
|
)
|
||
|
{
|
||
|
if (NumberOfChars == 0)
|
||
|
{
|
||
|
NumberOfChars = strlen( Source );
|
||
|
}
|
||
|
if (MultiByteToWideChar( CP_ACP,
|
||
|
MB_PRECOMPOSED,
|
||
|
Source,
|
||
|
NumberOfChars,
|
||
|
Destination,
|
||
|
NumberOfChars
|
||
|
) != (LONG)NumberOfChars)
|
||
|
{
|
||
|
SetLastError( ERROR_NO_UNICODE_TRANSLATION );
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Destination[ NumberOfChars ] = UNICODE_NULL;
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Functin gets system registry key.
|
||
|
|
||
|
Arguments:
|
||
|
none
|
||
|
|
||
|
Return Value:
|
||
|
DWORD : Registry key value
|
||
|
******************************************************************************/
|
||
|
|
||
|
DWORD
|
||
|
GetSystemRegistryFlags( VOID )
|
||
|
{
|
||
|
DWORD cbKey;
|
||
|
DWORD GFlags;
|
||
|
DWORD type;
|
||
|
|
||
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
|
||
|
_T("SYSTEM\\CurrentControlSet\\Control\\Session Manager"),
|
||
|
0,
|
||
|
KEY_READ | KEY_WRITE,
|
||
|
&hKey
|
||
|
) != ERROR_SUCCESS)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
cbKey = sizeof( GFlags );
|
||
|
if (RegQueryValueEx( hKey,
|
||
|
_T("GlobalFlag"),
|
||
|
0,
|
||
|
&type,
|
||
|
(LPBYTE)&GFlags,
|
||
|
&cbKey
|
||
|
) != ERROR_SUCCESS ||type != REG_DWORD)
|
||
|
{
|
||
|
RegCloseKey( hKey );
|
||
|
return 0;
|
||
|
}
|
||
|
return GFlags;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Sets system registry Global Flag with given value.
|
||
|
|
||
|
Arguments:
|
||
|
[in] GFlags : Key value
|
||
|
|
||
|
Return Value:
|
||
|
BOOLEAN TRUE: success
|
||
|
FALSE: FAIL
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOLEAN
|
||
|
SetSystemRegistryFlags(
|
||
|
DWORD GFlags
|
||
|
)
|
||
|
{
|
||
|
if (RegSetValueEx( hKey,
|
||
|
_T("GlobalFlag"),
|
||
|
0,
|
||
|
REG_DWORD,
|
||
|
(LPBYTE)&GFlags,
|
||
|
sizeof( GFlags )
|
||
|
) != ERROR_SUCCESS)
|
||
|
{
|
||
|
RegCloseKey( hKey );
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This function will show all locally opened open files.
|
||
|
Arguments:
|
||
|
[in] dwFormat : Format value for output e.g LIST, CSV or TABLE
|
||
|
[in] bShowNoHeader : Whether to show header or not.
|
||
|
[in] bVerbose : Verbose ouput or not.
|
||
|
[in] bDisableObjectTypeList : To disable object type list;
|
||
|
Return Value:
|
||
|
BOOL
|
||
|
******************************************************************************/
|
||
|
BOOL DoLocalOpenFiles(DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose,LPCTSTR pszLocalValue)
|
||
|
{
|
||
|
char *s;
|
||
|
NTSTATUS Status;
|
||
|
PRTL_DEBUG_INFORMATION p;
|
||
|
DWORD dwRegistryFlags = 0;
|
||
|
dwRegistryFlags = GetSystemRegistryFlags();
|
||
|
if(lstrcmpi(pszLocalValue,GetResString(IDS_LOCAL_OFF)) == 0) // disabling the object typelist
|
||
|
{
|
||
|
dwRegistryFlags &= ~FLG_MAINTAIN_OBJECT_TYPELIST;
|
||
|
if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
|
||
|
{
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_RESET));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetSystemRegistryFlags(dwRegistryFlags);
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_RESET));
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
return TRUE;
|
||
|
}
|
||
|
else if(lstrcmpi(pszLocalValue,GetResString(IDS_LOCAL_ON)) == 0)
|
||
|
{
|
||
|
if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
|
||
|
{
|
||
|
// SUNIL: Enabling the OS to maintain the objects list flag
|
||
|
// The user help text calls this global flag 'maintain objects list'
|
||
|
// and enables it with "/local" switch.
|
||
|
SetSystemRegistryFlags( dwRegistryFlags | FLG_MAINTAIN_OBJECT_TYPELIST );
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_SET));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_SET));
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
return TRUE;
|
||
|
}
|
||
|
else if(lstrcmpi(pszLocalValue,L"SHOW_STATUS") == 0)
|
||
|
{
|
||
|
dwRegistryFlags &= ~FLG_MAINTAIN_OBJECT_TYPELIST;
|
||
|
if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
|
||
|
{
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_RESET));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_SET));
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
return TRUE;
|
||
|
}
|
||
|
else // just check for FLG_MAINTAIN_OBJECT_TYPELIST
|
||
|
{
|
||
|
if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
|
||
|
{
|
||
|
RegCloseKey( hKey );
|
||
|
ShowMessage(stderr,GetResString(IDS_LOCAL_NEEDS_TO_SET));
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
// Not required Reg. key so close it
|
||
|
RegCloseKey( hKey );
|
||
|
hStdHandle = GetStdHandle(STD_ERROR_HANDLE);
|
||
|
if(hStdHandle!=NULL)
|
||
|
{
|
||
|
GetConsoleScreenBufferInfo(hStdHandle,&screenBufferInfo);
|
||
|
}
|
||
|
PrintProgressMsg(hStdHandle,GetResString(IDS_WAIT),screenBufferInfo);
|
||
|
|
||
|
OutputFileName[0]='\0';
|
||
|
OutputFile = INVALID_HANDLE_VALUE;
|
||
|
ProcessId = NULL;
|
||
|
fAnonymousToo = FALSE;
|
||
|
|
||
|
AnsiToUnicode(
|
||
|
"File",
|
||
|
TypeName,
|
||
|
4
|
||
|
);
|
||
|
p = RtlQuerySystemDebugInformation();
|
||
|
if (p == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
if (NT_SUCCESS( Status ))
|
||
|
{
|
||
|
DumpHandles(dwFormat,bShowNoHeader,bVerbose);
|
||
|
}
|
||
|
|
||
|
if (OutputFile != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
CloseHandle( OutputFile );
|
||
|
}
|
||
|
RtlDestroyQueryDebugBuffer( p );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Query system for System object, System handles and system process
|
||
|
|
||
|
Arguments:
|
||
|
none
|
||
|
|
||
|
result.
|
||
|
|
||
|
Return Value:
|
||
|
PRTL_DEBUG_INFORMATION
|
||
|
******************************************************************************/
|
||
|
|
||
|
PRTL_DEBUG_INFORMATION
|
||
|
RtlQuerySystemDebugInformation( void)
|
||
|
{
|
||
|
PRTL_DEBUG_INFORMATION Buffer;
|
||
|
|
||
|
Buffer = (PRTL_DEBUG_INFORMATION)RTL_NEW( Buffer );
|
||
|
if (Buffer == NULL)
|
||
|
{
|
||
|
RTL_FREE(Buffer);
|
||
|
return NULL;
|
||
|
}
|
||
|
if (!LoadSystemObjects( Buffer ))
|
||
|
{
|
||
|
RTL_FREE(Buffer);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (!LoadSystemHandles( Buffer ))
|
||
|
{
|
||
|
RTL_FREE(Buffer);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (!LoadSystemProcesses( Buffer ))
|
||
|
{
|
||
|
RTL_FREE(Buffer);
|
||
|
return NULL;
|
||
|
}
|
||
|
return Buffer;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This routine will reserves or commits a region of pages in the virtual .
|
||
|
address space of given size.
|
||
|
Arguments:
|
||
|
[in] Lenght : Size of memory required
|
||
|
|
||
|
result.
|
||
|
|
||
|
Return Value:
|
||
|
PVOID
|
||
|
******************************************************************************/
|
||
|
|
||
|
PVOID
|
||
|
BufferAlloc(
|
||
|
IN OUT SIZE_T *Length
|
||
|
)
|
||
|
{
|
||
|
PVOID Buffer;
|
||
|
MEMORY_BASIC_INFORMATION MemoryInformation;
|
||
|
|
||
|
Buffer = VirtualAlloc( NULL,
|
||
|
*Length,
|
||
|
MEM_COMMIT,
|
||
|
PAGE_READWRITE
|
||
|
);
|
||
|
|
||
|
if(Buffer == NULL)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (Buffer != NULL && VirtualQuery( Buffer, &MemoryInformation, sizeof( MemoryInformation ) ) )
|
||
|
{
|
||
|
*Length = MemoryInformation.RegionSize;
|
||
|
}
|
||
|
return Buffer;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This routine will free buffer.
|
||
|
|
||
|
Arguments:
|
||
|
[in] Buffer : Buffer which is to be freed.
|
||
|
|
||
|
Return Value:
|
||
|
none
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID
|
||
|
BufferFree(
|
||
|
IN PVOID Buffer
|
||
|
)
|
||
|
{
|
||
|
VirtualFree (Buffer,0, MEM_DECOMMIT) ;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Loads the system objects
|
||
|
|
||
|
Arguments:
|
||
|
[out] Buffer: returns system objects
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOLEAN
|
||
|
LoadSystemObjects(
|
||
|
PRTL_DEBUG_INFORMATION Buffer
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
SYSTEM_OBJECTTYPE_INFORMATION ObjectInfoBuffer;
|
||
|
SIZE_T RequiredLength, NewLength=0;
|
||
|
ULONG i;
|
||
|
PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
|
||
|
DWORD length;
|
||
|
|
||
|
ObjectInformation = &ObjectInfoBuffer;
|
||
|
RequiredLength = sizeof( *ObjectInformation );
|
||
|
while (TRUE)
|
||
|
{
|
||
|
Status = NtQuerySystemInformation( SystemObjectInformation,
|
||
|
ObjectInformation,
|
||
|
(ULONG)RequiredLength,
|
||
|
(ULONG *)&NewLength
|
||
|
);
|
||
|
if (Status == STATUS_INFO_LENGTH_MISMATCH && NewLength > RequiredLength)
|
||
|
{
|
||
|
if (ObjectInformation != &ObjectInfoBuffer)
|
||
|
{
|
||
|
BufferFree (ObjectInformation);
|
||
|
}
|
||
|
RequiredLength = NewLength + 4096;
|
||
|
ObjectInformation = (PSYSTEM_OBJECTTYPE_INFORMATION)BufferAlloc (&RequiredLength);
|
||
|
if (ObjectInformation == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (!NT_SUCCESS( Status ))
|
||
|
{
|
||
|
if (ObjectInformation != &ObjectInfoBuffer)
|
||
|
{
|
||
|
|
||
|
BufferFree (ObjectInformation);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
TypeInfo = ObjectInformation;
|
||
|
while (TRUE)
|
||
|
{
|
||
|
if (TypeInfo->TypeIndex < MAX_TYPE_NAMES)
|
||
|
{
|
||
|
TypeCounts[ TypeInfo->TypeIndex ].TypeName = TypeInfo->TypeName;
|
||
|
}
|
||
|
|
||
|
if (TypeInfo->NextEntryOffset == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
|
||
|
((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
|
||
|
}
|
||
|
|
||
|
RtlInitUnicodeString( &UnknownTypeIndex, L"UnknownTypeIdx" );
|
||
|
for (i=0; i<=MAX_TYPE_NAMES; i++)
|
||
|
{
|
||
|
if (TypeCounts[ i ].TypeName.Length == 0 )
|
||
|
{
|
||
|
TypeCounts[ i ].TypeName = UnknownTypeIndex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Loads the system handles
|
||
|
|
||
|
Arguments:
|
||
|
[out] Buffer: returns system handles
|
||
|
|
||
|
Return Value:
|
||
|
BOOLEAN
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
BOOLEAN
|
||
|
LoadSystemHandles(
|
||
|
PRTL_DEBUG_INFORMATION Buffer
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
SYSTEM_HANDLE_INFORMATION_EX HandleInfoBuffer;
|
||
|
SIZE_T RequiredLength, NewLength=0;
|
||
|
PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
|
||
|
PSYSTEM_OBJECT_INFORMATION ObjectInfo;
|
||
|
|
||
|
HandleInformation = &HandleInfoBuffer;
|
||
|
RequiredLength = sizeof( *HandleInformation );
|
||
|
while (TRUE)
|
||
|
{
|
||
|
Status = NtQuerySystemInformation( SystemExtendedHandleInformation,
|
||
|
HandleInformation,
|
||
|
(ULONG)RequiredLength,
|
||
|
(ULONG *)&NewLength
|
||
|
);
|
||
|
|
||
|
if (Status == STATUS_INFO_LENGTH_MISMATCH && NewLength > RequiredLength)
|
||
|
{
|
||
|
if (HandleInformation != &HandleInfoBuffer)
|
||
|
{
|
||
|
BufferFree (HandleInformation);
|
||
|
}
|
||
|
|
||
|
RequiredLength = NewLength + 4096; // slop, since we may trigger more handle creations.
|
||
|
HandleInformation = (PSYSTEM_HANDLE_INFORMATION_EX)BufferAlloc( &RequiredLength );
|
||
|
if (HandleInformation == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (!NT_SUCCESS( Status ))
|
||
|
{
|
||
|
if (HandleInformation != &HandleInfoBuffer)
|
||
|
{
|
||
|
BufferFree (HandleInformation);
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TypeInfo = ObjectInformation;
|
||
|
while (TRUE)
|
||
|
{
|
||
|
ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
|
||
|
((PCHAR)TypeInfo->TypeName.Buffer + TypeInfo->TypeName.MaximumLength);
|
||
|
while (TRUE)
|
||
|
{
|
||
|
if (ObjectInfo->HandleCount != 0)
|
||
|
{
|
||
|
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
|
||
|
ULONG HandleNumber;
|
||
|
|
||
|
HandleEntry = &HandleInformation->Handles[ 0 ];
|
||
|
HandleNumber = 0;
|
||
|
while (HandleNumber++ < HandleInformation->NumberOfHandles)
|
||
|
{
|
||
|
if (!(HandleEntry->HandleAttributes & 0x80) &&
|
||
|
HandleEntry->Object == ObjectInfo->Object)
|
||
|
{
|
||
|
HandleEntry->Object = ObjectInfo;
|
||
|
HandleEntry->HandleAttributes |= 0x80;
|
||
|
}
|
||
|
HandleEntry++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ObjectInfo->NextEntryOffset == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
|
||
|
((PCHAR)ObjectInformation + ObjectInfo->NextEntryOffset);
|
||
|
}
|
||
|
|
||
|
if (TypeInfo->NextEntryOffset == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
|
||
|
((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
|
||
|
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Loads the system process .
|
||
|
|
||
|
Arguments:
|
||
|
[out] Buffer: returns sysem process
|
||
|
|
||
|
Return Value:
|
||
|
BOOLEAN
|
||
|
******************************************************************************/
|
||
|
|
||
|
|
||
|
BOOLEAN
|
||
|
LoadSystemProcesses(
|
||
|
PRTL_DEBUG_INFORMATION Buffer
|
||
|
)
|
||
|
{
|
||
|
NTSTATUS Status;
|
||
|
SIZE_T RequiredLength;
|
||
|
ULONG i, TotalOffset;
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
||
|
PSYSTEM_THREAD_INFORMATION ThreadInfo;
|
||
|
PPROCESS_INFO ProcessEntry;
|
||
|
CHAR NameBuffer[ MAX_PATH ];
|
||
|
ANSI_STRING AnsiString;
|
||
|
|
||
|
//
|
||
|
// Always initialize the list head, so that a failed
|
||
|
// NtQuerySystemInformation call won't cause an AV later on.
|
||
|
//
|
||
|
InitializeListHead( &ProcessListHead );
|
||
|
|
||
|
RequiredLength = 64 * 1024;
|
||
|
ProcessInformation = (PSYSTEM_PROCESS_INFORMATION)BufferAlloc( &RequiredLength );
|
||
|
if (ProcessInformation == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
Status = NtQuerySystemInformation( SystemProcessInformation,
|
||
|
ProcessInformation,
|
||
|
(ULONG)RequiredLength,
|
||
|
NULL
|
||
|
);
|
||
|
if (Status == STATUS_INFO_LENGTH_MISMATCH)
|
||
|
{
|
||
|
if (!VirtualFree( ProcessInformation,
|
||
|
RequiredLength,
|
||
|
MEM_DECOMMIT
|
||
|
))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (RequiredLength * 2 < RequiredLength)
|
||
|
{
|
||
|
// Very rare loop case, but I want to handle it anyways
|
||
|
return FALSE;
|
||
|
}
|
||
|
RequiredLength = RequiredLength * 2;
|
||
|
ProcessInformation = (PSYSTEM_PROCESS_INFORMATION)BufferAlloc( &RequiredLength );
|
||
|
if (ProcessInformation == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else if (!NT_SUCCESS( Status ))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ProcessInfo = ProcessInformation;
|
||
|
TotalOffset = 0;
|
||
|
while (TRUE)
|
||
|
{
|
||
|
if (ProcessInfo->ImageName.Buffer == NULL)
|
||
|
{
|
||
|
sprintf( NameBuffer, "System Process (%p)", ProcessInfo->UniqueProcessId );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
sprintf( NameBuffer, "%wZ",
|
||
|
&ProcessInfo->ImageName);
|
||
|
}
|
||
|
RtlInitAnsiString( &AnsiString, NameBuffer );
|
||
|
RtlAnsiStringToUnicodeString( &ProcessInfo->ImageName, &AnsiString, TRUE );
|
||
|
|
||
|
ProcessEntry =(PPROCESS_INFO) RtlAllocateHeap( RtlProcessHeap(),
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
sizeof( *ProcessEntry ) +
|
||
|
(sizeof( ThreadInfo ) * ProcessInfo->NumberOfThreads));
|
||
|
if (ProcessEntry == NULL)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
InitializeListHead( &ProcessEntry->Entry );
|
||
|
ProcessEntry->ProcessInfo = ProcessInfo;
|
||
|
ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
|
||
|
for (i = 0; i < ProcessInfo->NumberOfThreads; i++)
|
||
|
{
|
||
|
ProcessEntry->ThreadInfo[ i ] = ThreadInfo++;
|
||
|
}
|
||
|
|
||
|
InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
|
||
|
|
||
|
if (ProcessInfo->NextEntryOffset == 0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
TotalOffset += ProcessInfo->NextEntryOffset;
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
|
||
|
((PCHAR)ProcessInformation + TotalOffset);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This routine will get Process information.
|
||
|
Arguments:
|
||
|
[in] UniqueProcessId = Process ID.
|
||
|
|
||
|
Return Value:
|
||
|
PSYSTEM_PROCESS_INFORMATION, Structure which hold information about process
|
||
|
******************************************************************************/
|
||
|
|
||
|
PSYSTEM_PROCESS_INFORMATION
|
||
|
FindProcessInfoForCid(
|
||
|
IN HANDLE UniqueProcessId
|
||
|
)
|
||
|
{
|
||
|
PLIST_ENTRY Next, Head;
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
||
|
PPROCESS_INFO ProcessEntry;
|
||
|
CHAR NameBuffer[ 64 ];
|
||
|
ANSI_STRING AnsiString;
|
||
|
|
||
|
Head = &ProcessListHead;
|
||
|
Next = Head->Flink;
|
||
|
while (Next != Head)
|
||
|
{
|
||
|
ProcessEntry = CONTAINING_RECORD( Next,
|
||
|
PROCESS_INFO,
|
||
|
Entry
|
||
|
);
|
||
|
|
||
|
ProcessInfo = ProcessEntry->ProcessInfo;
|
||
|
if (ProcessInfo->UniqueProcessId == UniqueProcessId)
|
||
|
{
|
||
|
return ProcessInfo;
|
||
|
}
|
||
|
|
||
|
Next = Next->Flink;
|
||
|
}
|
||
|
|
||
|
ProcessEntry =(PPROCESS_INFO) RtlAllocateHeap( RtlProcessHeap(),
|
||
|
HEAP_ZERO_MEMORY,
|
||
|
sizeof( *ProcessEntry ) +
|
||
|
sizeof( *ProcessInfo )
|
||
|
);
|
||
|
if (ProcessEntry == NULL)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessEntry+1);
|
||
|
|
||
|
ProcessEntry->ProcessInfo = ProcessInfo;
|
||
|
sprintf( NameBuffer, "Unknown Process");
|
||
|
RtlInitAnsiString( &AnsiString, NameBuffer );
|
||
|
RtlAnsiStringToUnicodeString( (PUNICODE_STRING)&ProcessInfo->ImageName, &AnsiString, TRUE );
|
||
|
ProcessInfo->UniqueProcessId = UniqueProcessId;
|
||
|
|
||
|
InitializeListHead( &ProcessEntry->Entry );
|
||
|
InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
|
||
|
return ProcessInfo;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This function will show result.
|
||
|
|
||
|
Arguments:
|
||
|
[in] dwFormat : Format value for output e.g LIST, CSV or TABLE
|
||
|
[in] bShowNoHeader : Whether to show header or not.
|
||
|
[in] bVerbose : Verbose ouput or not.
|
||
|
|
||
|
Return Value:
|
||
|
void
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
VOID
|
||
|
DumpHandles( DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose)
|
||
|
{
|
||
|
HANDLE PreviousUniqueProcessId;
|
||
|
PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
|
||
|
ULONG HandleNumber;
|
||
|
PSYSTEM_PROCESS_INFORMATION ProcessInfo;
|
||
|
PSYSTEM_OBJECT_INFORMATION ObjectInfo;
|
||
|
PUNICODE_STRING ObjectTypeName;
|
||
|
WCHAR ObjectName[ MAX_RES_STRING ];
|
||
|
PVOID Object;
|
||
|
CHAR OutputLine[ MAX_RES_STRING];
|
||
|
CHString szFileType;
|
||
|
PWSTR s;
|
||
|
ULONG n;
|
||
|
DWORD dwRow = 0; // no of rows
|
||
|
DWORD dwAvailableLogivalDrives = 0; // Stores avalable logical drives info.
|
||
|
TCHAR szWorkingDirectory[MAX_PATH+1] = NULL_STRING; // stores working directory.
|
||
|
TCHAR szSystemDirectory[MAX_PATH+1] = NULL_STRING; // Stores the System (Active OS) directory
|
||
|
struct DriveTypeInfo drvInfo[MAX_POSSIBLE_DRIVES];
|
||
|
DWORD dwNoOfAvailableDrives = 0; // Stores no. of available drives
|
||
|
TCHAR cDriveLater = 65; // "A" is First available driveDrive
|
||
|
DWORD dwDriveMaskPattern = 1; // "A" is First available driveDrive
|
||
|
// so mask pattern is
|
||
|
// 0xFFF1
|
||
|
// variable used for _splitpath function...
|
||
|
TCHAR szDrive[_MAX_DRIVE] = NULL_STRING;
|
||
|
TCHAR szDir[_MAX_DIR]= NULL_STRING;
|
||
|
TCHAR szFname[_MAX_FNAME]= NULL_STRING;
|
||
|
TCHAR szExt[_MAX_EXT]= NULL_STRING;
|
||
|
|
||
|
TCHAR szTemp[MAX_RES_STRING*2]=NULL_STRING;
|
||
|
TCHAR szCompleteFileName[MAX_PATH] = NULL_STRING;
|
||
|
DWORD dwHandle = 0;
|
||
|
BOOL bAtLeastOne = FALSE;
|
||
|
DWORD dwIndx = 0; // variable used for indexing
|
||
|
|
||
|
TCHAR szFileSystemNameBuffer[MAX_PATH+1] = NULL_STRING;
|
||
|
TCHAR szVolName[MAX_PATH+1] = NULL_STRING;
|
||
|
DWORD dwVolumeSerialNumber = 0;
|
||
|
DWORD dwSerialNumber = 0;
|
||
|
DWORD dwFileSystemFlags = 0;
|
||
|
DWORD dwMaximumCompenentLength = 0;
|
||
|
BOOL bReturn = FALSE;
|
||
|
DWORD dwNoOfElements = 0;
|
||
|
|
||
|
DWORD dwIteration = 0;
|
||
|
BY_HANDLE_FILE_INFORMATION byHandleFileInfo;
|
||
|
DWORD dwFileAttributes;
|
||
|
|
||
|
BOOL bAppendToCache = FALSE;
|
||
|
//Some column required to hide in non verbose mode query
|
||
|
DWORD dwMask = bVerbose?SR_TYPE_STRING:SR_HIDECOLUMN|SR_TYPE_STRING;
|
||
|
|
||
|
TCOLUMNS pMainCols[]=
|
||
|
{
|
||
|
{NULL_STRING,COL_L_ID,SR_TYPE_STRING,NULL_STRING,NULL,NULL},
|
||
|
{NULL_STRING,COL_L_TYPE,SR_HIDECOLUMN,NULL_STRING,NULL,NULL},
|
||
|
{NULL_STRING,COL_L_ACCESSED_BY,dwMask,NULL_STRING,NULL,NULL},
|
||
|
{NULL_STRING,COL_L_PROCESS_NAME,SR_TYPE_STRING,NULL_STRING,NULL,NULL},
|
||
|
{NULL_STRING,COL_L_OPEN_FILENAME,SR_TYPE_STRING|(SR_NO_TRUNCATION&~(SR_WORDWRAP)),NULL_STRING,NULL,NULL}
|
||
|
};
|
||
|
|
||
|
LPTSTR pszAccessedby = new TCHAR[MAX_RES_STRING*2];
|
||
|
if(pszAccessedby==NULL)
|
||
|
{
|
||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
|
||
|
ShowLastError(stderr);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TARRAY pColData = CreateDynamicArray();//array to stores
|
||
|
//result
|
||
|
if((pColData == NULL))
|
||
|
{
|
||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
|
||
|
ShowLastError(stderr);
|
||
|
SAFEDELETE(pszAccessedby);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TARRAY pCacheData = CreateDynamicArray();//array to stores
|
||
|
|
||
|
if(pCacheData == NULL)
|
||
|
{
|
||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
|
||
|
ShowLastError(stderr);
|
||
|
SAFERELDYNARRAY(pColData);
|
||
|
SAFERELDYNARRAY(pCacheData);
|
||
|
SAFEDELETE(pszAccessedby);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
lstrcpy(pMainCols[LOF_ID].szColumn,GetResString(IDS_STRING_ID));
|
||
|
lstrcpy(pMainCols[LOF_TYPE].szColumn,GetResString(IDS_FILE_TYPE));
|
||
|
lstrcpy(pMainCols[LOF_ACCESSED_BY].szColumn,GetResString(IDS_STRING_ACCESSED_BY) );
|
||
|
lstrcpy(pMainCols[LOF_PROCESS_NAME].szColumn,GetResString(IDS_STRING_PROCESS_NAME));
|
||
|
lstrcpy(pMainCols[LOF_OPEN_FILENAME].szColumn,GetResString(IDS_STRING_OPEN_FILE) );
|
||
|
|
||
|
dwAvailableLogivalDrives = GetLogicalDrives(); // Get logical drives.
|
||
|
// Store current working direcory.
|
||
|
_wgetcwd(szWorkingDirectory,MAX_PATH);
|
||
|
|
||
|
// Get System Active (OS) directory
|
||
|
if(GetSystemDirectory(szSystemDirectory,MAX_PATH)==NULL)
|
||
|
{
|
||
|
DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
|
||
|
ShowLastError(stderr); // Shows the error string set by API function.
|
||
|
SAFERELDYNARRAY(pColData);
|
||
|
SAFERELDYNARRAY(pCacheData);
|
||
|
SAFEDELETE(pszAccessedby);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
// Check each drive and set its info.
|
||
|
for(dwIndx=0;dwIndx<MAX_POSSIBLE_DRIVES;dwIndx++,cDriveLater++)
|
||
|
{
|
||
|
// dwAvailableLogivalDrives contains drive information in bit wise
|
||
|
// 0000 0000 0000 0000 0000 01101 means A C and D drives are
|
||
|
// logical drives.
|
||
|
if(dwAvailableLogivalDrives & dwDriveMaskPattern)
|
||
|
{
|
||
|
// means we catch a drive latter.
|
||
|
// copy drive latter (line c:\ or a: for example).
|
||
|
wsprintf(drvInfo[dwNoOfAvailableDrives].szDrive,_T("%c:"),cDriveLater);
|
||
|
// Check type of the drive .
|
||
|
drvInfo[dwNoOfAvailableDrives].uiDriveType = GetDriveType(drvInfo[dwNoOfAvailableDrives].szDrive);
|
||
|
// Check if drive is ready or not.
|
||
|
wsprintf(szTemp,_T("%s\\"),drvInfo[dwNoOfAvailableDrives].szDrive);
|
||
|
bReturn = GetVolumeInformation((LPCWSTR)szTemp,
|
||
|
szVolName,
|
||
|
MAX_PATH,
|
||
|
&dwVolumeSerialNumber,
|
||
|
&dwMaximumCompenentLength,
|
||
|
&dwFileSystemFlags,
|
||
|
szFileSystemNameBuffer,
|
||
|
MAX_PATH);
|
||
|
drvInfo[dwNoOfAvailableDrives].bDrivePresent = bReturn;
|
||
|
dwNoOfAvailableDrives++;
|
||
|
}
|
||
|
dwDriveMaskPattern = dwDriveMaskPattern << 1; // Left shift 1
|
||
|
}
|
||
|
HandleEntry = &HandleInformation->Handles[ 0 ];
|
||
|
HandleNumber = 0;
|
||
|
PreviousUniqueProcessId = INVALID_HANDLE_VALUE;
|
||
|
for (HandleNumber = 0;HandleNumber < HandleInformation->NumberOfHandles;HandleNumber++, HandleEntry++)
|
||
|
{
|
||
|
if (PreviousUniqueProcessId != (HANDLE)HandleEntry->UniqueProcessId)
|
||
|
{
|
||
|
PreviousUniqueProcessId = (HANDLE)HandleEntry->UniqueProcessId;
|
||
|
ProcessInfo = FindProcessInfoForCid( PreviousUniqueProcessId );
|
||
|
|
||
|
}
|
||
|
|
||
|
ObjectName[ 0 ] = UNICODE_NULL;
|
||
|
if (HandleEntry->HandleAttributes & 0x80)
|
||
|
{
|
||
|
ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)HandleEntry->Object;
|
||
|
Object = ObjectInfo->Object;
|
||
|
if (ObjectInfo->NameInfo.Name.Length != 0 &&
|
||
|
*(ObjectInfo->NameInfo.Name.Buffer) == UNICODE_NULL)
|
||
|
{
|
||
|
ObjectInfo->NameInfo.Name.Length = 0;
|
||
|
|
||
|
}
|
||
|
n = ObjectInfo->NameInfo.Name.Length / sizeof( WCHAR );
|
||
|
if(ObjectInfo->NameInfo.Name.Buffer != NULL)
|
||
|
{
|
||
|
wcsncpy( ObjectName,
|
||
|
ObjectInfo->NameInfo.Name.Buffer,
|
||
|
n
|
||
|
);
|
||
|
ObjectName[ n ] = UNICODE_NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ObjectName[ 0 ] = UNICODE_NULL;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ObjectInfo = NULL;
|
||
|
Object = HandleEntry->Object;
|
||
|
}
|
||
|
|
||
|
if (ProcessId != 0 && ProcessInfo->UniqueProcessId != ProcessId)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
ObjectTypeName = &TypeCounts[ HandleEntry->ObjectTypeIndex < MAX_TYPE_NAMES ?
|
||
|
HandleEntry->ObjectTypeIndex : MAX_TYPE_NAMES ].TypeName ;
|
||
|
|
||
|
TypeCounts[ HandleEntry->ObjectTypeIndex < MAX_TYPE_NAMES ?
|
||
|
HandleEntry->ObjectTypeIndex : MAX_TYPE_NAMES ].HandleCount++ ;
|
||
|
|
||
|
if (TypeName[0])
|
||
|
{
|
||
|
if (_wcsicmp( TypeName, ObjectTypeName->Buffer ))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!*ObjectName)
|
||
|
{
|
||
|
if (!fAnonymousToo)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
else if (SearchName[0])
|
||
|
{
|
||
|
if (!wcsstr( ObjectName, SearchName ))
|
||
|
{
|
||
|
s = ObjectName;
|
||
|
n = wcslen( SearchName );
|
||
|
while (*s)
|
||
|
{
|
||
|
if (!_wcsnicmp( s, SearchName, n ))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
s += 1;
|
||
|
}
|
||
|
if (!*s)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
dwHandle = PtrToUlong( ProcessInfo->UniqueProcessId ); //HandleEntry->HandleValue;
|
||
|
|
||
|
// SUNIL: Blocking the display of files that were opened by system accounts ( NT AUTHORITY )
|
||
|
// if( bVerbose == TRUE )
|
||
|
// {
|
||
|
if ( GetProcessOwner( pszAccessedby, dwHandle ) == FALSE )
|
||
|
continue;// As user is "SYSTEM" related....
|
||
|
// }
|
||
|
|
||
|
// Get File name ..
|
||
|
wsprintf(szTemp,_T("%ws"),*ObjectName ? ObjectName : L"");
|
||
|
// Search this file in cache, if it is there skip this file
|
||
|
// for further processing. As this is already processed and
|
||
|
// was found invalid.
|
||
|
if(IsValidArray(pCacheData) == TRUE)
|
||
|
{
|
||
|
if ( DynArrayFindString( pCacheData, szTemp, TRUE, 0 ) != -1 )
|
||
|
continue;
|
||
|
}
|
||
|
lstrcpy( szCompleteFileName, _T( "" ) );
|
||
|
if(GetCompleteFileName(szTemp,szCompleteFileName,&drvInfo[0],dwNoOfAvailableDrives,szWorkingDirectory,szSystemDirectory,&bAppendToCache) == FALSE)
|
||
|
{
|
||
|
if(bAppendToCache == TRUE) // szTemp contains a directory which is not physicaly exist
|
||
|
// so add this to cache to skip it in future for checking
|
||
|
// of its existance
|
||
|
{
|
||
|
|
||
|
if(IsValidArray(pCacheData) == TRUE)
|
||
|
{
|
||
|
// dwNoOfElements = DynArrayGetCount( pCacheData );
|
||
|
DynArrayAppendString(pCacheData, (LPCWSTR)szTemp,0);
|
||
|
}
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
// Now fill the result to dynamic array "pColData"
|
||
|
DynArrayAppendRow( pColData, 0 );
|
||
|
// File id
|
||
|
wsprintf(szTemp,_T("%ld"),HandleEntry->HandleValue);
|
||
|
DynArrayAppendString2(pColData ,dwRow,szTemp,0);
|
||
|
// Type
|
||
|
DynArrayAppendString2(pColData ,dwRow,(LPCWSTR)szFileType,0);
|
||
|
// Accessed by
|
||
|
DynArrayAppendString2(pColData,dwRow,pszAccessedby,0);
|
||
|
// Process Name
|
||
|
sprintf(OutputLine,"%wZ",&ProcessInfo->ImageName);
|
||
|
GetCompatibleStringFromMultiByte(OutputLine,szTemp,MAX_RES_STRING);
|
||
|
DynArrayAppendString2(pColData ,dwRow,szTemp,0);
|
||
|
|
||
|
if(bVerbose == FALSE) // Formate file name only in non verbose mode.
|
||
|
{
|
||
|
FormatFileName(szCompleteFileName,dwFormat,COL_L_OPEN_FILENAME);
|
||
|
}
|
||
|
// Open File name
|
||
|
DynArrayAppendString2(pColData ,dwRow,szCompleteFileName,0);
|
||
|
dwRow++;
|
||
|
bAtLeastOne = TRUE;
|
||
|
|
||
|
}
|
||
|
// Display output result.
|
||
|
//Output should start after one blank line
|
||
|
PrintProgressMsg(hStdHandle,NULL_STRING,screenBufferInfo);
|
||
|
if(bShowNoHeader==TRUE)
|
||
|
{
|
||
|
dwFormat |=SR_NOHEADER;
|
||
|
}
|
||
|
if(bVerbose == TRUE)
|
||
|
{
|
||
|
pMainCols[LOF_OPEN_FILENAME].dwWidth = 80;
|
||
|
}
|
||
|
if(bAtLeastOne==FALSE)// if not a single open file found, show info
|
||
|
// as - INFO: No open file found.
|
||
|
{
|
||
|
ShowMessage(stdout,GetResString(IDS_NO_OPENFILES));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ShowMessage(stdout,GetResString(IDS_LOCAL_OPEN_FILES));
|
||
|
ShowMessage(stdout,GetResString(IDS_LOCAL_OPEN_FILES_SP1));
|
||
|
ShowResults(NO_OF_COL_LOCAL_OPENFILE,pMainCols,dwFormat,pColData);
|
||
|
}
|
||
|
SAFERELDYNARRAY(pColData);
|
||
|
SAFERELDYNARRAY(pCacheData);
|
||
|
SAFEDELETE(pszAccessedby);
|
||
|
return;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
Prints the message on console.
|
||
|
Arguments:
|
||
|
[in] hOutput = Handle value for console.
|
||
|
[in] pwszMsg = Message to be printed.
|
||
|
[in] csbi = Coordinates of console from where message will print.
|
||
|
|
||
|
Return Value:
|
||
|
none
|
||
|
|
||
|
******************************************************************************/
|
||
|
|
||
|
void PrintProgressMsg(HANDLE hOutput,LPCWSTR pwszMsg,const CONSOLE_SCREEN_BUFFER_INFO& csbi)
|
||
|
{
|
||
|
COORD coord;
|
||
|
DWORD dwSize = 0;
|
||
|
WCHAR wszSpaces[80] = L"";
|
||
|
|
||
|
if(hOutput == NULL)
|
||
|
return;
|
||
|
|
||
|
coord.X = 0;
|
||
|
coord.Y = csbi.dwCursorPosition.Y;
|
||
|
|
||
|
ZeroMemory(wszSpaces,80);
|
||
|
SetConsoleCursorPosition(hOutput,coord);
|
||
|
WriteConsoleW(hOutput,Replicate(wszSpaces,L"",79),79,&dwSize,NULL);
|
||
|
|
||
|
SetConsoleCursorPosition(hOutput,coord);
|
||
|
|
||
|
if(pwszMsg!=NULL)
|
||
|
WriteConsoleW(hOutput,pwszMsg,lstrlen(pwszMsg),&dwSize,NULL);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This function will accept a path (with out drive letter), and returns
|
||
|
the path with drive letter.
|
||
|
Arguments:
|
||
|
[in] pszSourceFile = Source path
|
||
|
[out] pszFinalPath = Final path
|
||
|
[in] DriveTypeInfo = Logical drive information structure pointer
|
||
|
[in] pszCurrentDirectory = Current woking directory path
|
||
|
[in] pszSystemDirectory = Current Active (OS) System directory
|
||
|
[out] pAppendToCache = whether to pszSourceFile to cache
|
||
|
|
||
|
Return Value:
|
||
|
BOOL: TRUE: if fuction successfuly returns pszFinalPath
|
||
|
FALSE: otherwise
|
||
|
******************************************************************************/
|
||
|
BOOL GetCompleteFileName(LPCTSTR pszSourceFile,LPTSTR pszFinalPath,struct DriveTypeInfo *pdrvInfo,DWORD dwTotalDrives,LPCTSTR pszCurrentDirectory,LPCTSTR pszSystemDirectory,PBOOL pAppendToCache)
|
||
|
{
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// ALGORITHM USED
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// Following is the procedure for getting full path name ..
|
||
|
// 1. First check if the first character in pszSourceFile is '\' .
|
||
|
// 2. If first character of pszSourceFile is '\' then check for the second character...
|
||
|
// 3. If second character is ';' then than take 3 rd character as drive letter and
|
||
|
// find rest of string for 3rd "\" (Or 4th from first). String after 3rd character
|
||
|
// will be final path. for example let the source string is
|
||
|
// \;Z:00000000000774c8\sanny\c$\nt\base\fs\utils\OpenFiles\Changed\obj\i386
|
||
|
// then final path is z:\nt\base\fs\utils\OpenFiles\Changed\obj\i386
|
||
|
// 4. If second character is not ';' then try to find pszSourceFile for its existance
|
||
|
// by first prefixing the available drive letter one by one. The first occurence
|
||
|
// of file existance will be the final valid path. Appending of file letter has
|
||
|
// a rule. First append FIXED DRIVES then try to append MOVABLE DRIVES.
|
||
|
//
|
||
|
// Here there is a known limitation. Let there exists two files with same name like...
|
||
|
// c:\document\abc.doc and d:\documet\abc.doc and actual file opened is d:\documet\abc.doc
|
||
|
// then this will show final path as c:\documet\abc.doc as it starts with A:....Z:(also preference
|
||
|
// will be given to FIXED TYPE DRIVE).
|
||
|
// 5. If first character is not '\' then prefix Current working directory path to file name.
|
||
|
// and check it for its existance. IF this not exits then search this path by prefixing
|
||
|
// logical drive letter to it.
|
||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
CHString szTemp(pszSourceFile); // Temp string
|
||
|
DWORD dwTemp = 0;// Temp variable
|
||
|
LONG lTemp = 0;
|
||
|
LONG lCount = 0;
|
||
|
TCHAR szTempStr[MAX_PATH+1] = NULL_STRING;
|
||
|
HANDLE hHandle = NULL;
|
||
|
DWORD dwFoundCount = 0;
|
||
|
WIN32_FIND_DATA win32FindData; // data buffer for FindFirstFile function.
|
||
|
DriveTypeInfo *pHeadPosition = pdrvInfo; // Hold the head position.
|
||
|
*pAppendToCache = FALSE; // Make it false by default.
|
||
|
// check if first character is '\'
|
||
|
TCHAR szSystemDrive[5] = NULL_STRING;
|
||
|
lstrcpyn(szSystemDrive,pszSystemDirectory,3); // First two character will be system drive (a:).
|
||
|
if(pszSourceFile[0] == _T('\\'))
|
||
|
{
|
||
|
// Check if second character if it is ';'
|
||
|
if(pszSourceFile[1] == ';')
|
||
|
{
|
||
|
pszFinalPath[0] = pszSourceFile[2]; // make 3rd character as drive letter
|
||
|
pszFinalPath[1] = ':'; // make 2nd character ':'
|
||
|
pszFinalPath[2] = '\0'; // make 3nd character NULL
|
||
|
dwFoundCount = 0;
|
||
|
for (lTemp = 0;lTemp <5;lTemp++) // search for 3rd '\'
|
||
|
{
|
||
|
lCount = szTemp.Find(_T("\\"));
|
||
|
if(lCount!=-1)
|
||
|
{
|
||
|
dwFoundCount++;
|
||
|
if(dwFoundCount == 4 )// this should always (if any)after 4rd character from start
|
||
|
{
|
||
|
lstrcat(pszFinalPath,(LPCWSTR)szTemp.Mid(lCount));
|
||
|
return TRUE;
|
||
|
}
|
||
|
szTemp = szTemp.Mid(lCount+1);
|
||
|
continue;
|
||
|
}
|
||
|
*pAppendToCache = TRUE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
|
||
|
// check first of all for system drive
|
||
|
szTemp = szSystemDrive;
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
// check file for each FIXED drive
|
||
|
for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
|
||
|
{
|
||
|
if(lstrcmpi(szSystemDrive,pdrvInfo->szDrive) == 0)
|
||
|
continue; // as system drive is already checked
|
||
|
if(pdrvInfo->uiDriveType == DRIVE_FIXED)
|
||
|
{
|
||
|
szTemp = pdrvInfo->szDrive;
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
} // end if
|
||
|
} // End for loop
|
||
|
pdrvInfo = pHeadPosition ; // retore original position.
|
||
|
// check file for other drive which is present...
|
||
|
for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
|
||
|
{
|
||
|
// Check for NON_FIXED drive only if it is physicaly present
|
||
|
if((pdrvInfo->uiDriveType != DRIVE_FIXED) && (pdrvInfo->bDrivePresent == TRUE))
|
||
|
{
|
||
|
szTemp = pdrvInfo->szDrive;
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
} // end if
|
||
|
} // End for loop
|
||
|
|
||
|
// Now try if file is opend on remote system without
|
||
|
// having drive map. in this we are assuming that file name
|
||
|
// is containing atleast 3 '\' characters.
|
||
|
szTemp = pszSourceFile;
|
||
|
pszFinalPath[0] = '\\'; // make 3rd character '\'
|
||
|
pszFinalPath[1] = '\0'; // make 2nd character '\o'
|
||
|
dwFoundCount = 0;
|
||
|
for (lTemp = 0;lTemp <4;lTemp++) // search for 3rd '\'
|
||
|
{
|
||
|
lCount = szTemp.Find(_T("\\"));
|
||
|
if(lCount!=-1)
|
||
|
{
|
||
|
szTemp = szTemp.Mid(lCount+1);
|
||
|
dwFoundCount++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
if (dwFoundCount == 3)
|
||
|
{
|
||
|
lstrcat(pszFinalPath,pszSourceFile);
|
||
|
// Now try to check its physical existance
|
||
|
hHandle = FindFirstFile(pszFinalPath,&win32FindData);
|
||
|
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
// Now try to append \* to it...(this will check if
|
||
|
// if pszFinalPath is a directory or not)
|
||
|
lstrcpy(szTempStr,pszFinalPath);
|
||
|
lstrcat(szTempStr,L"\\*");
|
||
|
hHandle = FindFirstFile(szTempStr,&win32FindData);
|
||
|
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
// now its sure this is not a valid directory or file
|
||
|
// so append it to chache
|
||
|
*pAppendToCache = TRUE;
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
FindClose(hHandle);
|
||
|
return TRUE;
|
||
|
}
|
||
|
FindClose(hHandle);
|
||
|
return TRUE;
|
||
|
}
|
||
|
} // End for
|
||
|
}// End else
|
||
|
} // end if
|
||
|
else // means string not started with '\'
|
||
|
{
|
||
|
|
||
|
lstrcpy(pszFinalPath,pszCurrentDirectory);
|
||
|
lstrcat(pszFinalPath,L"\\");
|
||
|
lstrcat(pszFinalPath,pszSourceFile);
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
// check first of all for system drive
|
||
|
szTemp = szSystemDrive;
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle != INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
// restores the head position for the pointer.
|
||
|
pdrvInfo = pHeadPosition ;
|
||
|
// check file for each FIXED drive
|
||
|
for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
|
||
|
{
|
||
|
if(lstrcmpi(szSystemDrive,pdrvInfo->szDrive) == 0)
|
||
|
continue; // as system drive is already checked
|
||
|
|
||
|
if(pdrvInfo->uiDriveType == DRIVE_FIXED)
|
||
|
{
|
||
|
szTemp = pdrvInfo->szDrive;
|
||
|
szTemp += L"\\"; // append \
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
} // end if
|
||
|
} // End for loop
|
||
|
pdrvInfo = pHeadPosition ; // retore original position.
|
||
|
|
||
|
// check file for other drive (Like Floppy or CD-ROM etc. ) which is present...
|
||
|
for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
|
||
|
{
|
||
|
if((pdrvInfo->uiDriveType != DRIVE_FIXED) && (pdrvInfo->bDrivePresent == TRUE))
|
||
|
{
|
||
|
szTemp = pdrvInfo->szDrive;
|
||
|
szTemp += L"\\"; // append '\'
|
||
|
szTemp+=pszSourceFile;
|
||
|
// now check for its existance....
|
||
|
hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
|
||
|
if(hHandle == INVALID_HANDLE_VALUE)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FindClose(hHandle); // closed opened find handle
|
||
|
lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
|
||
|
return TRUE;
|
||
|
}
|
||
|
} // end if
|
||
|
} // End for loop
|
||
|
}
|
||
|
*pAppendToCache = TRUE;
|
||
|
return FALSE;
|
||
|
}
|
||
|
/*****************************************************************************
|
||
|
Routine Description:
|
||
|
This routine will format the pFileName according to column width
|
||
|
|
||
|
Arguments:
|
||
|
[in/out] pFileName : path to be formatted
|
||
|
[in] dwFormat : Format given
|
||
|
[in] dwColWidth : Column width
|
||
|
Return Value:
|
||
|
none
|
||
|
******************************************************************************/
|
||
|
|
||
|
void FormatFileName(LPTSTR pFileName,DWORD dwFormat,LONG dwColWidth)
|
||
|
{
|
||
|
CHString szCHString(pFileName);
|
||
|
if((szCHString.GetLength()>(dwColWidth))&&
|
||
|
(dwFormat == SR_FORMAT_TABLE))
|
||
|
{
|
||
|
// If file path is too big to fit in column width
|
||
|
// then it is cut like..
|
||
|
// c:\..\rest_of_the_path.
|
||
|
CHString szTemp = szCHString.Right(dwColWidth-6);;
|
||
|
DWORD dwTemp = szTemp.GetLength();
|
||
|
szTemp = szTemp.Mid(szTemp.Find(SINGLE_SLASH),
|
||
|
dwTemp);
|
||
|
szCHString.Format(L"%s%s%s",szCHString.Mid(0,3),
|
||
|
DOT_DOT,
|
||
|
szTemp);
|
||
|
}
|
||
|
lstrcpy(pFileName,(LPCWSTR)szCHString);
|
||
|
return;
|
||
|
}
|