Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1478 lines
46 KiB

  1. /******************************************************************************
  2. Copyright (C) Microsoft Corporation
  3. Module Name:
  4. Handle.CPP
  5. Abstract:
  6. This module deals with Query functionality of OpenFiles.exe
  7. NT command line utility. This module will specifically query open files
  8. for local system.
  9. Author:
  10. Akhil Gokhale (akhil.gokhale@wipro.com) 25-APRIL-2000
  11. Revision History:
  12. Akhil Gokhale (akhil.gokhale@wipro.com) 25-APRIL-2000 : Created It.
  13. *****************************************************************************/
  14. #include "pch.h"
  15. #include "OpenFiles.h"
  16. #define MAX_POSSIBLE_DRIVES 26 // maximum possible drives are A,B....Y,Z
  17. #define RTL_NEW( p ) RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *p ) )
  18. #define RTL_FREE(p) \
  19. if(p!=NULL)\
  20. {\
  21. RtlFreeHeap( RtlProcessHeap(), 0, p);\
  22. p = NULL;\
  23. }\
  24. 1
  25. #define MAX_TYPE_NAMES 128
  26. struct DriveTypeInfo
  27. {
  28. TCHAR szDrive[4];
  29. UINT uiDriveType;
  30. BOOL bDrivePresent;
  31. };
  32. BOOLEAN fAnonymousToo;
  33. HANDLE ProcessId;
  34. WCHAR TypeName[ MAX_TYPE_NAMES ];
  35. WCHAR SearchName[ 512 ];
  36. CHAR OutputFileName[ MAX_PATH ];
  37. HANDLE OutputFile;
  38. HKEY hKey;
  39. CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo;
  40. HANDLE hStdHandle;
  41. typedef struct _PROCESS_INFO
  42. {
  43. LIST_ENTRY Entry;
  44. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  45. PSYSTEM_THREAD_INFORMATION ThreadInfo[ 1 ];
  46. } PROCESS_INFO, *PPROCESS_INFO;
  47. LIST_ENTRY ProcessListHead;
  48. PSYSTEM_OBJECTTYPE_INFORMATION ObjectInformation;
  49. PSYSTEM_HANDLE_INFORMATION_EX HandleInformation;
  50. PSYSTEM_PROCESS_INFORMATION ProcessInformation;
  51. typedef struct _TYPE_COUNT
  52. {
  53. UNICODE_STRING TypeName ;
  54. ULONG HandleCount ;
  55. } TYPE_COUNT, * PTYPE_COUNT ;
  56. TYPE_COUNT TypeCounts[ MAX_TYPE_NAMES + 1 ] ;
  57. UNICODE_STRING UnknownTypeIndex;
  58. // Local function decleration
  59. PRTL_DEBUG_INFORMATION RtlQuerySystemDebugInformation(void);
  60. BOOLEAN LoadSystemModules(PRTL_DEBUG_INFORMATION Buffer);
  61. BOOLEAN LoadSystemObjects(PRTL_DEBUG_INFORMATION Buffer);
  62. BOOLEAN LoadSystemHandles(PRTL_DEBUG_INFORMATION Buffer);
  63. BOOLEAN LoadSystemProcesses(PRTL_DEBUG_INFORMATION Buffer);
  64. PSYSTEM_PROCESS_INFORMATION FindProcessInfoForCid(IN HANDLE UniqueProcessId);
  65. VOID DumpHandles( DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose);
  66. BOOL GetCompleteFileName(LPCTSTR pszSourceFile,LPTSTR pszFinalPath,struct DriveTypeInfo *pdrvInfo,DWORD dwTotalDrives,LPCTSTR pszCurrentDirectory,LPCTSTR pszSystemDirectory,PBOOL pAppendToCache) ;
  67. void FormatFileName(LPTSTR pFileName,DWORD dwFormat,LONG dwColWidth);
  68. void PrintProgressMsg(HANDLE hOutput,LPCWSTR pwszMsg,const CONSOLE_SCREEN_BUFFER_INFO& csbi);
  69. /*****************************************************************************
  70. Routine Description:
  71. This function will change an ansi string to UNICODE string
  72. Arguments:
  73. [in] Source : Source string
  74. [out] Destination : Destination string
  75. [in] NumberOfChars : No of character in source string
  76. Return Value:
  77. BOOL TRUE : Successfully conversion
  78. FALSE: Unsuccessful
  79. ******************************************************************************/
  80. BOOLEAN
  81. AnsiToUnicode(
  82. LPCSTR Source,
  83. PWSTR Destination,
  84. ULONG NumberOfChars
  85. )
  86. {
  87. if (NumberOfChars == 0)
  88. {
  89. NumberOfChars = strlen( Source );
  90. }
  91. if (MultiByteToWideChar( CP_ACP,
  92. MB_PRECOMPOSED,
  93. Source,
  94. NumberOfChars,
  95. Destination,
  96. NumberOfChars
  97. ) != (LONG)NumberOfChars)
  98. {
  99. SetLastError( ERROR_NO_UNICODE_TRANSLATION );
  100. return FALSE;
  101. }
  102. else
  103. {
  104. Destination[ NumberOfChars ] = UNICODE_NULL;
  105. return TRUE;
  106. }
  107. }
  108. /*****************************************************************************
  109. Routine Description:
  110. Functin gets system registry key.
  111. Arguments:
  112. none
  113. Return Value:
  114. DWORD : Registry key value
  115. ******************************************************************************/
  116. DWORD
  117. GetSystemRegistryFlags( VOID )
  118. {
  119. DWORD cbKey;
  120. DWORD GFlags;
  121. DWORD type;
  122. if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  123. _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager"),
  124. 0,
  125. KEY_READ | KEY_WRITE,
  126. &hKey
  127. ) != ERROR_SUCCESS)
  128. {
  129. return 0;
  130. }
  131. cbKey = sizeof( GFlags );
  132. if (RegQueryValueEx( hKey,
  133. _T("GlobalFlag"),
  134. 0,
  135. &type,
  136. (LPBYTE)&GFlags,
  137. &cbKey
  138. ) != ERROR_SUCCESS ||type != REG_DWORD)
  139. {
  140. RegCloseKey( hKey );
  141. return 0;
  142. }
  143. return GFlags;
  144. }
  145. /*****************************************************************************
  146. Routine Description:
  147. Sets system registry Global Flag with given value.
  148. Arguments:
  149. [in] GFlags : Key value
  150. Return Value:
  151. BOOLEAN TRUE: success
  152. FALSE: FAIL
  153. ******************************************************************************/
  154. BOOLEAN
  155. SetSystemRegistryFlags(
  156. DWORD GFlags
  157. )
  158. {
  159. if (RegSetValueEx( hKey,
  160. _T("GlobalFlag"),
  161. 0,
  162. REG_DWORD,
  163. (LPBYTE)&GFlags,
  164. sizeof( GFlags )
  165. ) != ERROR_SUCCESS)
  166. {
  167. RegCloseKey( hKey );
  168. return FALSE;
  169. }
  170. return TRUE;
  171. }
  172. /*****************************************************************************
  173. Routine Description:
  174. This function will show all locally opened open files.
  175. Arguments:
  176. [in] dwFormat : Format value for output e.g LIST, CSV or TABLE
  177. [in] bShowNoHeader : Whether to show header or not.
  178. [in] bVerbose : Verbose ouput or not.
  179. [in] bDisableObjectTypeList : To disable object type list;
  180. Return Value:
  181. BOOL
  182. ******************************************************************************/
  183. BOOL DoLocalOpenFiles(DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose,LPCTSTR pszLocalValue)
  184. {
  185. char *s;
  186. NTSTATUS Status;
  187. PRTL_DEBUG_INFORMATION p;
  188. DWORD dwRegistryFlags = 0;
  189. dwRegistryFlags = GetSystemRegistryFlags();
  190. if(lstrcmpi(pszLocalValue,GetResString(IDS_LOCAL_OFF)) == 0) // disabling the object typelist
  191. {
  192. dwRegistryFlags &= ~FLG_MAINTAIN_OBJECT_TYPELIST;
  193. if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
  194. {
  195. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_RESET));
  196. }
  197. else
  198. {
  199. SetSystemRegistryFlags(dwRegistryFlags);
  200. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_RESET));
  201. }
  202. RegCloseKey( hKey );
  203. return TRUE;
  204. }
  205. else if(lstrcmpi(pszLocalValue,GetResString(IDS_LOCAL_ON)) == 0)
  206. {
  207. if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
  208. {
  209. // SUNIL: Enabling the OS to maintain the objects list flag
  210. // The user help text calls this global flag 'maintain objects list'
  211. // and enables it with "/local" switch.
  212. SetSystemRegistryFlags( dwRegistryFlags | FLG_MAINTAIN_OBJECT_TYPELIST );
  213. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_SET));
  214. }
  215. else
  216. {
  217. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_SET));
  218. }
  219. RegCloseKey( hKey );
  220. return TRUE;
  221. }
  222. else if(lstrcmpi(pszLocalValue,L"SHOW_STATUS") == 0)
  223. {
  224. dwRegistryFlags &= ~FLG_MAINTAIN_OBJECT_TYPELIST;
  225. if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
  226. {
  227. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_RESET));
  228. }
  229. else
  230. {
  231. ShowMessage(stderr,GetResString(IDS_LOCAL_FLG_ALREADY_SET));
  232. }
  233. RegCloseKey( hKey );
  234. return TRUE;
  235. }
  236. else // just check for FLG_MAINTAIN_OBJECT_TYPELIST
  237. {
  238. if (!(NtCurrentPeb()->NtGlobalFlag & FLG_MAINTAIN_OBJECT_TYPELIST))
  239. {
  240. RegCloseKey( hKey );
  241. ShowMessage(stderr,GetResString(IDS_LOCAL_NEEDS_TO_SET));
  242. return TRUE;
  243. }
  244. }
  245. // Not required Reg. key so close it
  246. RegCloseKey( hKey );
  247. hStdHandle = GetStdHandle(STD_ERROR_HANDLE);
  248. if(hStdHandle!=NULL)
  249. {
  250. GetConsoleScreenBufferInfo(hStdHandle,&screenBufferInfo);
  251. }
  252. PrintProgressMsg(hStdHandle,GetResString(IDS_WAIT),screenBufferInfo);
  253. OutputFileName[0]='\0';
  254. OutputFile = INVALID_HANDLE_VALUE;
  255. ProcessId = NULL;
  256. fAnonymousToo = FALSE;
  257. AnsiToUnicode(
  258. "File",
  259. TypeName,
  260. 4
  261. );
  262. p = RtlQuerySystemDebugInformation();
  263. if (p == NULL)
  264. {
  265. return FALSE;
  266. }
  267. Status = STATUS_SUCCESS;
  268. if (NT_SUCCESS( Status ))
  269. {
  270. DumpHandles(dwFormat,bShowNoHeader,bVerbose);
  271. }
  272. if (OutputFile != INVALID_HANDLE_VALUE)
  273. {
  274. CloseHandle( OutputFile );
  275. }
  276. RtlDestroyQueryDebugBuffer( p );
  277. return TRUE;
  278. }
  279. /*****************************************************************************
  280. Routine Description:
  281. Query system for System object, System handles and system process
  282. Arguments:
  283. none
  284. result.
  285. Return Value:
  286. PRTL_DEBUG_INFORMATION
  287. ******************************************************************************/
  288. PRTL_DEBUG_INFORMATION
  289. RtlQuerySystemDebugInformation( void)
  290. {
  291. PRTL_DEBUG_INFORMATION Buffer;
  292. Buffer = (PRTL_DEBUG_INFORMATION)RTL_NEW( Buffer );
  293. if (Buffer == NULL)
  294. {
  295. RTL_FREE(Buffer);
  296. return NULL;
  297. }
  298. if (!LoadSystemObjects( Buffer ))
  299. {
  300. RTL_FREE(Buffer);
  301. return NULL;
  302. }
  303. if (!LoadSystemHandles( Buffer ))
  304. {
  305. RTL_FREE(Buffer);
  306. return NULL;
  307. }
  308. if (!LoadSystemProcesses( Buffer ))
  309. {
  310. RTL_FREE(Buffer);
  311. return NULL;
  312. }
  313. return Buffer;
  314. }
  315. /*****************************************************************************
  316. Routine Description:
  317. This routine will reserves or commits a region of pages in the virtual .
  318. address space of given size.
  319. Arguments:
  320. [in] Lenght : Size of memory required
  321. result.
  322. Return Value:
  323. PVOID
  324. ******************************************************************************/
  325. PVOID
  326. BufferAlloc(
  327. IN OUT SIZE_T *Length
  328. )
  329. {
  330. PVOID Buffer;
  331. MEMORY_BASIC_INFORMATION MemoryInformation;
  332. Buffer = VirtualAlloc( NULL,
  333. *Length,
  334. MEM_COMMIT,
  335. PAGE_READWRITE
  336. );
  337. if(Buffer == NULL)
  338. {
  339. return NULL;
  340. }
  341. if (Buffer != NULL && VirtualQuery( Buffer, &MemoryInformation, sizeof( MemoryInformation ) ) )
  342. {
  343. *Length = MemoryInformation.RegionSize;
  344. }
  345. return Buffer;
  346. }
  347. /*****************************************************************************
  348. Routine Description:
  349. This routine will free buffer.
  350. Arguments:
  351. [in] Buffer : Buffer which is to be freed.
  352. Return Value:
  353. none
  354. ******************************************************************************/
  355. VOID
  356. BufferFree(
  357. IN PVOID Buffer
  358. )
  359. {
  360. VirtualFree (Buffer,0, MEM_DECOMMIT) ;
  361. return;
  362. }
  363. /*****************************************************************************
  364. Routine Description:
  365. Loads the system objects
  366. Arguments:
  367. [out] Buffer: returns system objects
  368. Return Value:
  369. ******************************************************************************/
  370. BOOLEAN
  371. LoadSystemObjects(
  372. PRTL_DEBUG_INFORMATION Buffer
  373. )
  374. {
  375. NTSTATUS Status;
  376. SYSTEM_OBJECTTYPE_INFORMATION ObjectInfoBuffer;
  377. SIZE_T RequiredLength, NewLength=0;
  378. ULONG i;
  379. PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
  380. DWORD length;
  381. ObjectInformation = &ObjectInfoBuffer;
  382. RequiredLength = sizeof( *ObjectInformation );
  383. while (TRUE)
  384. {
  385. Status = NtQuerySystemInformation( SystemObjectInformation,
  386. ObjectInformation,
  387. (ULONG)RequiredLength,
  388. (ULONG *)&NewLength
  389. );
  390. if (Status == STATUS_INFO_LENGTH_MISMATCH && NewLength > RequiredLength)
  391. {
  392. if (ObjectInformation != &ObjectInfoBuffer)
  393. {
  394. BufferFree (ObjectInformation);
  395. }
  396. RequiredLength = NewLength + 4096;
  397. ObjectInformation = (PSYSTEM_OBJECTTYPE_INFORMATION)BufferAlloc (&RequiredLength);
  398. if (ObjectInformation == NULL)
  399. {
  400. return FALSE;
  401. }
  402. }
  403. else if (!NT_SUCCESS( Status ))
  404. {
  405. if (ObjectInformation != &ObjectInfoBuffer)
  406. {
  407. BufferFree (ObjectInformation);
  408. }
  409. return FALSE;
  410. }
  411. else
  412. {
  413. break;
  414. }
  415. }
  416. TypeInfo = ObjectInformation;
  417. while (TRUE)
  418. {
  419. if (TypeInfo->TypeIndex < MAX_TYPE_NAMES)
  420. {
  421. TypeCounts[ TypeInfo->TypeIndex ].TypeName = TypeInfo->TypeName;
  422. }
  423. if (TypeInfo->NextEntryOffset == 0) {
  424. break;
  425. }
  426. TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
  427. ((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
  428. }
  429. RtlInitUnicodeString( &UnknownTypeIndex, L"UnknownTypeIdx" );
  430. for (i=0; i<=MAX_TYPE_NAMES; i++)
  431. {
  432. if (TypeCounts[ i ].TypeName.Length == 0 )
  433. {
  434. TypeCounts[ i ].TypeName = UnknownTypeIndex;
  435. }
  436. }
  437. return TRUE;
  438. }
  439. /*****************************************************************************
  440. Routine Description:
  441. Loads the system handles
  442. Arguments:
  443. [out] Buffer: returns system handles
  444. Return Value:
  445. BOOLEAN
  446. ******************************************************************************/
  447. BOOLEAN
  448. LoadSystemHandles(
  449. PRTL_DEBUG_INFORMATION Buffer
  450. )
  451. {
  452. NTSTATUS Status;
  453. SYSTEM_HANDLE_INFORMATION_EX HandleInfoBuffer;
  454. SIZE_T RequiredLength, NewLength=0;
  455. PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
  456. PSYSTEM_OBJECT_INFORMATION ObjectInfo;
  457. HandleInformation = &HandleInfoBuffer;
  458. RequiredLength = sizeof( *HandleInformation );
  459. while (TRUE)
  460. {
  461. Status = NtQuerySystemInformation( SystemExtendedHandleInformation,
  462. HandleInformation,
  463. (ULONG)RequiredLength,
  464. (ULONG *)&NewLength
  465. );
  466. if (Status == STATUS_INFO_LENGTH_MISMATCH && NewLength > RequiredLength)
  467. {
  468. if (HandleInformation != &HandleInfoBuffer)
  469. {
  470. BufferFree (HandleInformation);
  471. }
  472. RequiredLength = NewLength + 4096; // slop, since we may trigger more handle creations.
  473. HandleInformation = (PSYSTEM_HANDLE_INFORMATION_EX)BufferAlloc( &RequiredLength );
  474. if (HandleInformation == NULL)
  475. {
  476. return FALSE;
  477. }
  478. }
  479. else if (!NT_SUCCESS( Status ))
  480. {
  481. if (HandleInformation != &HandleInfoBuffer)
  482. {
  483. BufferFree (HandleInformation);
  484. }
  485. return FALSE;
  486. }
  487. else
  488. {
  489. break;
  490. }
  491. }
  492. TypeInfo = ObjectInformation;
  493. while (TRUE)
  494. {
  495. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  496. ((PCHAR)TypeInfo->TypeName.Buffer + TypeInfo->TypeName.MaximumLength);
  497. while (TRUE)
  498. {
  499. if (ObjectInfo->HandleCount != 0)
  500. {
  501. PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
  502. ULONG HandleNumber;
  503. HandleEntry = &HandleInformation->Handles[ 0 ];
  504. HandleNumber = 0;
  505. while (HandleNumber++ < HandleInformation->NumberOfHandles)
  506. {
  507. if (!(HandleEntry->HandleAttributes & 0x80) &&
  508. HandleEntry->Object == ObjectInfo->Object)
  509. {
  510. HandleEntry->Object = ObjectInfo;
  511. HandleEntry->HandleAttributes |= 0x80;
  512. }
  513. HandleEntry++;
  514. }
  515. }
  516. if (ObjectInfo->NextEntryOffset == 0)
  517. {
  518. break;
  519. }
  520. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  521. ((PCHAR)ObjectInformation + ObjectInfo->NextEntryOffset);
  522. }
  523. if (TypeInfo->NextEntryOffset == 0)
  524. {
  525. break;
  526. }
  527. TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
  528. ((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
  529. }
  530. return TRUE;
  531. }
  532. /*****************************************************************************
  533. Routine Description:
  534. Loads the system process .
  535. Arguments:
  536. [out] Buffer: returns sysem process
  537. Return Value:
  538. BOOLEAN
  539. ******************************************************************************/
  540. BOOLEAN
  541. LoadSystemProcesses(
  542. PRTL_DEBUG_INFORMATION Buffer
  543. )
  544. {
  545. NTSTATUS Status;
  546. SIZE_T RequiredLength;
  547. ULONG i, TotalOffset;
  548. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  549. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  550. PPROCESS_INFO ProcessEntry;
  551. CHAR NameBuffer[ MAX_PATH ];
  552. ANSI_STRING AnsiString;
  553. //
  554. // Always initialize the list head, so that a failed
  555. // NtQuerySystemInformation call won't cause an AV later on.
  556. //
  557. InitializeListHead( &ProcessListHead );
  558. RequiredLength = 64 * 1024;
  559. ProcessInformation = (PSYSTEM_PROCESS_INFORMATION)BufferAlloc( &RequiredLength );
  560. if (ProcessInformation == NULL)
  561. {
  562. return FALSE;
  563. }
  564. while (TRUE)
  565. {
  566. Status = NtQuerySystemInformation( SystemProcessInformation,
  567. ProcessInformation,
  568. (ULONG)RequiredLength,
  569. NULL
  570. );
  571. if (Status == STATUS_INFO_LENGTH_MISMATCH)
  572. {
  573. if (!VirtualFree( ProcessInformation,
  574. RequiredLength,
  575. MEM_DECOMMIT
  576. ))
  577. {
  578. return FALSE;
  579. }
  580. if (RequiredLength * 2 < RequiredLength)
  581. {
  582. // Very rare loop case, but I want to handle it anyways
  583. return FALSE;
  584. }
  585. RequiredLength = RequiredLength * 2;
  586. ProcessInformation = (PSYSTEM_PROCESS_INFORMATION)BufferAlloc( &RequiredLength );
  587. if (ProcessInformation == NULL)
  588. {
  589. return FALSE;
  590. }
  591. }
  592. else if (!NT_SUCCESS( Status ))
  593. {
  594. return FALSE;
  595. }
  596. else
  597. {
  598. break;
  599. }
  600. }
  601. ProcessInfo = ProcessInformation;
  602. TotalOffset = 0;
  603. while (TRUE)
  604. {
  605. if (ProcessInfo->ImageName.Buffer == NULL)
  606. {
  607. sprintf( NameBuffer, "System Process (%p)", ProcessInfo->UniqueProcessId );
  608. }
  609. else
  610. {
  611. sprintf( NameBuffer, "%wZ",
  612. &ProcessInfo->ImageName);
  613. }
  614. RtlInitAnsiString( &AnsiString, NameBuffer );
  615. RtlAnsiStringToUnicodeString( &ProcessInfo->ImageName, &AnsiString, TRUE );
  616. ProcessEntry =(PPROCESS_INFO) RtlAllocateHeap( RtlProcessHeap(),
  617. HEAP_ZERO_MEMORY,
  618. sizeof( *ProcessEntry ) +
  619. (sizeof( ThreadInfo ) * ProcessInfo->NumberOfThreads));
  620. if (ProcessEntry == NULL)
  621. {
  622. return FALSE;
  623. }
  624. InitializeListHead( &ProcessEntry->Entry );
  625. ProcessEntry->ProcessInfo = ProcessInfo;
  626. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
  627. for (i = 0; i < ProcessInfo->NumberOfThreads; i++)
  628. {
  629. ProcessEntry->ThreadInfo[ i ] = ThreadInfo++;
  630. }
  631. InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
  632. if (ProcessInfo->NextEntryOffset == 0)
  633. {
  634. break;
  635. }
  636. TotalOffset += ProcessInfo->NextEntryOffset;
  637. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  638. ((PCHAR)ProcessInformation + TotalOffset);
  639. }
  640. return TRUE;
  641. }
  642. /*****************************************************************************
  643. Routine Description:
  644. This routine will get Process information.
  645. Arguments:
  646. [in] UniqueProcessId = Process ID.
  647. Return Value:
  648. PSYSTEM_PROCESS_INFORMATION, Structure which hold information about process
  649. ******************************************************************************/
  650. PSYSTEM_PROCESS_INFORMATION
  651. FindProcessInfoForCid(
  652. IN HANDLE UniqueProcessId
  653. )
  654. {
  655. PLIST_ENTRY Next, Head;
  656. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  657. PPROCESS_INFO ProcessEntry;
  658. CHAR NameBuffer[ 64 ];
  659. ANSI_STRING AnsiString;
  660. Head = &ProcessListHead;
  661. Next = Head->Flink;
  662. while (Next != Head)
  663. {
  664. ProcessEntry = CONTAINING_RECORD( Next,
  665. PROCESS_INFO,
  666. Entry
  667. );
  668. ProcessInfo = ProcessEntry->ProcessInfo;
  669. if (ProcessInfo->UniqueProcessId == UniqueProcessId)
  670. {
  671. return ProcessInfo;
  672. }
  673. Next = Next->Flink;
  674. }
  675. ProcessEntry =(PPROCESS_INFO) RtlAllocateHeap( RtlProcessHeap(),
  676. HEAP_ZERO_MEMORY,
  677. sizeof( *ProcessEntry ) +
  678. sizeof( *ProcessInfo )
  679. );
  680. if (ProcessEntry == NULL)
  681. {
  682. return NULL;
  683. }
  684. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessEntry+1);
  685. ProcessEntry->ProcessInfo = ProcessInfo;
  686. sprintf( NameBuffer, "Unknown Process");
  687. RtlInitAnsiString( &AnsiString, NameBuffer );
  688. RtlAnsiStringToUnicodeString( (PUNICODE_STRING)&ProcessInfo->ImageName, &AnsiString, TRUE );
  689. ProcessInfo->UniqueProcessId = UniqueProcessId;
  690. InitializeListHead( &ProcessEntry->Entry );
  691. InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
  692. return ProcessInfo;
  693. }
  694. /*****************************************************************************
  695. Routine Description:
  696. This function will show result.
  697. Arguments:
  698. [in] dwFormat : Format value for output e.g LIST, CSV or TABLE
  699. [in] bShowNoHeader : Whether to show header or not.
  700. [in] bVerbose : Verbose ouput or not.
  701. Return Value:
  702. void
  703. ******************************************************************************/
  704. VOID
  705. DumpHandles( DWORD dwFormat,BOOL bShowNoHeader,BOOL bVerbose)
  706. {
  707. HANDLE PreviousUniqueProcessId;
  708. PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
  709. ULONG HandleNumber;
  710. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  711. PSYSTEM_OBJECT_INFORMATION ObjectInfo;
  712. PUNICODE_STRING ObjectTypeName;
  713. WCHAR ObjectName[ MAX_RES_STRING ];
  714. PVOID Object;
  715. CHAR OutputLine[ MAX_RES_STRING];
  716. CHString szFileType;
  717. PWSTR s;
  718. ULONG n;
  719. DWORD dwRow = 0; // no of rows
  720. DWORD dwAvailableLogivalDrives = 0; // Stores avalable logical drives info.
  721. TCHAR szWorkingDirectory[MAX_PATH+1] = NULL_STRING; // stores working directory.
  722. TCHAR szSystemDirectory[MAX_PATH+1] = NULL_STRING; // Stores the System (Active OS) directory
  723. struct DriveTypeInfo drvInfo[MAX_POSSIBLE_DRIVES];
  724. DWORD dwNoOfAvailableDrives = 0; // Stores no. of available drives
  725. TCHAR cDriveLater = 65; // "A" is First available driveDrive
  726. DWORD dwDriveMaskPattern = 1; // "A" is First available driveDrive
  727. // so mask pattern is
  728. // 0xFFF1
  729. // variable used for _splitpath function...
  730. TCHAR szDrive[_MAX_DRIVE] = NULL_STRING;
  731. TCHAR szDir[_MAX_DIR]= NULL_STRING;
  732. TCHAR szFname[_MAX_FNAME]= NULL_STRING;
  733. TCHAR szExt[_MAX_EXT]= NULL_STRING;
  734. TCHAR szTemp[MAX_RES_STRING*2]=NULL_STRING;
  735. TCHAR szCompleteFileName[MAX_PATH] = NULL_STRING;
  736. DWORD dwHandle = 0;
  737. BOOL bAtLeastOne = FALSE;
  738. DWORD dwIndx = 0; // variable used for indexing
  739. TCHAR szFileSystemNameBuffer[MAX_PATH+1] = NULL_STRING;
  740. TCHAR szVolName[MAX_PATH+1] = NULL_STRING;
  741. DWORD dwVolumeSerialNumber = 0;
  742. DWORD dwSerialNumber = 0;
  743. DWORD dwFileSystemFlags = 0;
  744. DWORD dwMaximumCompenentLength = 0;
  745. BOOL bReturn = FALSE;
  746. DWORD dwNoOfElements = 0;
  747. DWORD dwIteration = 0;
  748. BY_HANDLE_FILE_INFORMATION byHandleFileInfo;
  749. DWORD dwFileAttributes;
  750. BOOL bAppendToCache = FALSE;
  751. //Some column required to hide in non verbose mode query
  752. DWORD dwMask = bVerbose?SR_TYPE_STRING:SR_HIDECOLUMN|SR_TYPE_STRING;
  753. TCOLUMNS pMainCols[]=
  754. {
  755. {NULL_STRING,COL_L_ID,SR_TYPE_STRING,NULL_STRING,NULL,NULL},
  756. {NULL_STRING,COL_L_TYPE,SR_HIDECOLUMN,NULL_STRING,NULL,NULL},
  757. {NULL_STRING,COL_L_ACCESSED_BY,dwMask,NULL_STRING,NULL,NULL},
  758. {NULL_STRING,COL_L_PROCESS_NAME,SR_TYPE_STRING,NULL_STRING,NULL,NULL},
  759. {NULL_STRING,COL_L_OPEN_FILENAME,SR_TYPE_STRING|(SR_NO_TRUNCATION&~(SR_WORDWRAP)),NULL_STRING,NULL,NULL}
  760. };
  761. LPTSTR pszAccessedby = new TCHAR[MAX_RES_STRING*2];
  762. if(pszAccessedby==NULL)
  763. {
  764. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  765. DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
  766. ShowLastError(stderr);
  767. return;
  768. }
  769. TARRAY pColData = CreateDynamicArray();//array to stores
  770. //result
  771. if((pColData == NULL))
  772. {
  773. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  774. DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
  775. ShowLastError(stderr);
  776. SAFEDELETE(pszAccessedby);
  777. return;
  778. }
  779. TARRAY pCacheData = CreateDynamicArray();//array to stores
  780. if(pCacheData == NULL)
  781. {
  782. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  783. DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
  784. ShowLastError(stderr);
  785. SAFERELDYNARRAY(pColData);
  786. SAFERELDYNARRAY(pCacheData);
  787. SAFEDELETE(pszAccessedby);
  788. return;
  789. }
  790. lstrcpy(pMainCols[LOF_ID].szColumn,GetResString(IDS_STRING_ID));
  791. lstrcpy(pMainCols[LOF_TYPE].szColumn,GetResString(IDS_FILE_TYPE));
  792. lstrcpy(pMainCols[LOF_ACCESSED_BY].szColumn,GetResString(IDS_STRING_ACCESSED_BY) );
  793. lstrcpy(pMainCols[LOF_PROCESS_NAME].szColumn,GetResString(IDS_STRING_PROCESS_NAME));
  794. lstrcpy(pMainCols[LOF_OPEN_FILENAME].szColumn,GetResString(IDS_STRING_OPEN_FILE) );
  795. dwAvailableLogivalDrives = GetLogicalDrives(); // Get logical drives.
  796. // Store current working direcory.
  797. _wgetcwd(szWorkingDirectory,MAX_PATH);
  798. // Get System Active (OS) directory
  799. if(GetSystemDirectory(szSystemDirectory,MAX_PATH)==NULL)
  800. {
  801. DISPLAY_MESSAGE(stderr,GetResString(IDS_ID_SHOW_ERROR));
  802. ShowLastError(stderr); // Shows the error string set by API function.
  803. SAFERELDYNARRAY(pColData);
  804. SAFERELDYNARRAY(pCacheData);
  805. SAFEDELETE(pszAccessedby);
  806. return ;
  807. }
  808. // Check each drive and set its info.
  809. for(dwIndx=0;dwIndx<MAX_POSSIBLE_DRIVES;dwIndx++,cDriveLater++)
  810. {
  811. // dwAvailableLogivalDrives contains drive information in bit wise
  812. // 0000 0000 0000 0000 0000 01101 means A C and D drives are
  813. // logical drives.
  814. if(dwAvailableLogivalDrives & dwDriveMaskPattern)
  815. {
  816. // means we catch a drive latter.
  817. // copy drive latter (line c:\ or a: for example).
  818. wsprintf(drvInfo[dwNoOfAvailableDrives].szDrive,_T("%c:"),cDriveLater);
  819. // Check type of the drive .
  820. drvInfo[dwNoOfAvailableDrives].uiDriveType = GetDriveType(drvInfo[dwNoOfAvailableDrives].szDrive);
  821. // Check if drive is ready or not.
  822. wsprintf(szTemp,_T("%s\\"),drvInfo[dwNoOfAvailableDrives].szDrive);
  823. bReturn = GetVolumeInformation((LPCWSTR)szTemp,
  824. szVolName,
  825. MAX_PATH,
  826. &dwVolumeSerialNumber,
  827. &dwMaximumCompenentLength,
  828. &dwFileSystemFlags,
  829. szFileSystemNameBuffer,
  830. MAX_PATH);
  831. drvInfo[dwNoOfAvailableDrives].bDrivePresent = bReturn;
  832. dwNoOfAvailableDrives++;
  833. }
  834. dwDriveMaskPattern = dwDriveMaskPattern << 1; // Left shift 1
  835. }
  836. HandleEntry = &HandleInformation->Handles[ 0 ];
  837. HandleNumber = 0;
  838. PreviousUniqueProcessId = INVALID_HANDLE_VALUE;
  839. for (HandleNumber = 0;HandleNumber < HandleInformation->NumberOfHandles;HandleNumber++, HandleEntry++)
  840. {
  841. if (PreviousUniqueProcessId != (HANDLE)HandleEntry->UniqueProcessId)
  842. {
  843. PreviousUniqueProcessId = (HANDLE)HandleEntry->UniqueProcessId;
  844. ProcessInfo = FindProcessInfoForCid( PreviousUniqueProcessId );
  845. }
  846. ObjectName[ 0 ] = UNICODE_NULL;
  847. if (HandleEntry->HandleAttributes & 0x80)
  848. {
  849. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)HandleEntry->Object;
  850. Object = ObjectInfo->Object;
  851. if (ObjectInfo->NameInfo.Name.Length != 0 &&
  852. *(ObjectInfo->NameInfo.Name.Buffer) == UNICODE_NULL)
  853. {
  854. ObjectInfo->NameInfo.Name.Length = 0;
  855. }
  856. n = ObjectInfo->NameInfo.Name.Length / sizeof( WCHAR );
  857. if(ObjectInfo->NameInfo.Name.Buffer != NULL)
  858. {
  859. wcsncpy( ObjectName,
  860. ObjectInfo->NameInfo.Name.Buffer,
  861. n
  862. );
  863. ObjectName[ n ] = UNICODE_NULL;
  864. }
  865. else
  866. {
  867. ObjectName[ 0 ] = UNICODE_NULL;
  868. }
  869. }
  870. else
  871. {
  872. ObjectInfo = NULL;
  873. Object = HandleEntry->Object;
  874. }
  875. if (ProcessId != 0 && ProcessInfo->UniqueProcessId != ProcessId)
  876. {
  877. continue;
  878. }
  879. ObjectTypeName = &TypeCounts[ HandleEntry->ObjectTypeIndex < MAX_TYPE_NAMES ?
  880. HandleEntry->ObjectTypeIndex : MAX_TYPE_NAMES ].TypeName ;
  881. TypeCounts[ HandleEntry->ObjectTypeIndex < MAX_TYPE_NAMES ?
  882. HandleEntry->ObjectTypeIndex : MAX_TYPE_NAMES ].HandleCount++ ;
  883. if (TypeName[0])
  884. {
  885. if (_wcsicmp( TypeName, ObjectTypeName->Buffer ))
  886. {
  887. continue;
  888. }
  889. }
  890. if (!*ObjectName)
  891. {
  892. if (!fAnonymousToo)
  893. {
  894. continue;
  895. }
  896. }
  897. else if (SearchName[0])
  898. {
  899. if (!wcsstr( ObjectName, SearchName ))
  900. {
  901. s = ObjectName;
  902. n = wcslen( SearchName );
  903. while (*s)
  904. {
  905. if (!_wcsnicmp( s, SearchName, n ))
  906. {
  907. break;
  908. }
  909. s += 1;
  910. }
  911. if (!*s)
  912. {
  913. continue;
  914. }
  915. }
  916. }
  917. dwHandle = PtrToUlong( ProcessInfo->UniqueProcessId ); //HandleEntry->HandleValue;
  918. // SUNIL: Blocking the display of files that were opened by system accounts ( NT AUTHORITY )
  919. // if( bVerbose == TRUE )
  920. // {
  921. if ( GetProcessOwner( pszAccessedby, dwHandle ) == FALSE )
  922. continue;// As user is "SYSTEM" related....
  923. // }
  924. // Get File name ..
  925. wsprintf(szTemp,_T("%ws"),*ObjectName ? ObjectName : L"");
  926. // Search this file in cache, if it is there skip this file
  927. // for further processing. As this is already processed and
  928. // was found invalid.
  929. if(IsValidArray(pCacheData) == TRUE)
  930. {
  931. if ( DynArrayFindString( pCacheData, szTemp, TRUE, 0 ) != -1 )
  932. continue;
  933. }
  934. lstrcpy( szCompleteFileName, _T( "" ) );
  935. if(GetCompleteFileName(szTemp,szCompleteFileName,&drvInfo[0],dwNoOfAvailableDrives,szWorkingDirectory,szSystemDirectory,&bAppendToCache) == FALSE)
  936. {
  937. if(bAppendToCache == TRUE) // szTemp contains a directory which is not physicaly exist
  938. // so add this to cache to skip it in future for checking
  939. // of its existance
  940. {
  941. if(IsValidArray(pCacheData) == TRUE)
  942. {
  943. // dwNoOfElements = DynArrayGetCount( pCacheData );
  944. DynArrayAppendString(pCacheData, (LPCWSTR)szTemp,0);
  945. }
  946. }
  947. continue;
  948. }
  949. // Now fill the result to dynamic array "pColData"
  950. DynArrayAppendRow( pColData, 0 );
  951. // File id
  952. wsprintf(szTemp,_T("%ld"),HandleEntry->HandleValue);
  953. DynArrayAppendString2(pColData ,dwRow,szTemp,0);
  954. // Type
  955. DynArrayAppendString2(pColData ,dwRow,(LPCWSTR)szFileType,0);
  956. // Accessed by
  957. DynArrayAppendString2(pColData,dwRow,pszAccessedby,0);
  958. // Process Name
  959. sprintf(OutputLine,"%wZ",&ProcessInfo->ImageName);
  960. GetCompatibleStringFromMultiByte(OutputLine,szTemp,MAX_RES_STRING);
  961. DynArrayAppendString2(pColData ,dwRow,szTemp,0);
  962. if(bVerbose == FALSE) // Formate file name only in non verbose mode.
  963. {
  964. FormatFileName(szCompleteFileName,dwFormat,COL_L_OPEN_FILENAME);
  965. }
  966. // Open File name
  967. DynArrayAppendString2(pColData ,dwRow,szCompleteFileName,0);
  968. dwRow++;
  969. bAtLeastOne = TRUE;
  970. }
  971. // Display output result.
  972. //Output should start after one blank line
  973. PrintProgressMsg(hStdHandle,NULL_STRING,screenBufferInfo);
  974. if(bShowNoHeader==TRUE)
  975. {
  976. dwFormat |=SR_NOHEADER;
  977. }
  978. if(bVerbose == TRUE)
  979. {
  980. pMainCols[LOF_OPEN_FILENAME].dwWidth = 80;
  981. }
  982. if(bAtLeastOne==FALSE)// if not a single open file found, show info
  983. // as - INFO: No open file found.
  984. {
  985. ShowMessage(stdout,GetResString(IDS_NO_OPENFILES));
  986. }
  987. else
  988. {
  989. ShowMessage(stdout,GetResString(IDS_LOCAL_OPEN_FILES));
  990. ShowMessage(stdout,GetResString(IDS_LOCAL_OPEN_FILES_SP1));
  991. ShowResults(NO_OF_COL_LOCAL_OPENFILE,pMainCols,dwFormat,pColData);
  992. }
  993. SAFERELDYNARRAY(pColData);
  994. SAFERELDYNARRAY(pCacheData);
  995. SAFEDELETE(pszAccessedby);
  996. return;
  997. }
  998. /*****************************************************************************
  999. Routine Description:
  1000. Prints the message on console.
  1001. Arguments:
  1002. [in] hOutput = Handle value for console.
  1003. [in] pwszMsg = Message to be printed.
  1004. [in] csbi = Coordinates of console from where message will print.
  1005. Return Value:
  1006. none
  1007. ******************************************************************************/
  1008. void PrintProgressMsg(HANDLE hOutput,LPCWSTR pwszMsg,const CONSOLE_SCREEN_BUFFER_INFO& csbi)
  1009. {
  1010. COORD coord;
  1011. DWORD dwSize = 0;
  1012. WCHAR wszSpaces[80] = L"";
  1013. if(hOutput == NULL)
  1014. return;
  1015. coord.X = 0;
  1016. coord.Y = csbi.dwCursorPosition.Y;
  1017. ZeroMemory(wszSpaces,80);
  1018. SetConsoleCursorPosition(hOutput,coord);
  1019. WriteConsoleW(hOutput,Replicate(wszSpaces,L"",79),79,&dwSize,NULL);
  1020. SetConsoleCursorPosition(hOutput,coord);
  1021. if(pwszMsg!=NULL)
  1022. WriteConsoleW(hOutput,pwszMsg,lstrlen(pwszMsg),&dwSize,NULL);
  1023. return;
  1024. }
  1025. /*****************************************************************************
  1026. Routine Description:
  1027. This function will accept a path (with out drive letter), and returns
  1028. the path with drive letter.
  1029. Arguments:
  1030. [in] pszSourceFile = Source path
  1031. [out] pszFinalPath = Final path
  1032. [in] DriveTypeInfo = Logical drive information structure pointer
  1033. [in] pszCurrentDirectory = Current woking directory path
  1034. [in] pszSystemDirectory = Current Active (OS) System directory
  1035. [out] pAppendToCache = whether to pszSourceFile to cache
  1036. Return Value:
  1037. BOOL: TRUE: if fuction successfuly returns pszFinalPath
  1038. FALSE: otherwise
  1039. ******************************************************************************/
  1040. BOOL GetCompleteFileName(LPCTSTR pszSourceFile,LPTSTR pszFinalPath,struct DriveTypeInfo *pdrvInfo,DWORD dwTotalDrives,LPCTSTR pszCurrentDirectory,LPCTSTR pszSystemDirectory,PBOOL pAppendToCache)
  1041. {
  1042. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1043. // ALGORITHM USED
  1044. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1045. // Following is the procedure for getting full path name ..
  1046. // 1. First check if the first character in pszSourceFile is '\' .
  1047. // 2. If first character of pszSourceFile is '\' then check for the second character...
  1048. // 3. If second character is ';' then than take 3 rd character as drive letter and
  1049. // find rest of string for 3rd "\" (Or 4th from first). String after 3rd character
  1050. // will be final path. for example let the source string is
  1051. // \;Z:00000000000774c8\sanny\c$\nt\base\fs\utils\OpenFiles\Changed\obj\i386
  1052. // then final path is z:\nt\base\fs\utils\OpenFiles\Changed\obj\i386
  1053. // 4. If second character is not ';' then try to find pszSourceFile for its existance
  1054. // by first prefixing the available drive letter one by one. The first occurence
  1055. // of file existance will be the final valid path. Appending of file letter has
  1056. // a rule. First append FIXED DRIVES then try to append MOVABLE DRIVES.
  1057. //
  1058. // Here there is a known limitation. Let there exists two files with same name like...
  1059. // c:\document\abc.doc and d:\documet\abc.doc and actual file opened is d:\documet\abc.doc
  1060. // then this will show final path as c:\documet\abc.doc as it starts with A:....Z:(also preference
  1061. // will be given to FIXED TYPE DRIVE).
  1062. // 5. If first character is not '\' then prefix Current working directory path to file name.
  1063. // and check it for its existance. IF this not exits then search this path by prefixing
  1064. // logical drive letter to it.
  1065. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1066. CHString szTemp(pszSourceFile); // Temp string
  1067. DWORD dwTemp = 0;// Temp variable
  1068. LONG lTemp = 0;
  1069. LONG lCount = 0;
  1070. TCHAR szTempStr[MAX_PATH+1] = NULL_STRING;
  1071. HANDLE hHandle = NULL;
  1072. DWORD dwFoundCount = 0;
  1073. WIN32_FIND_DATA win32FindData; // data buffer for FindFirstFile function.
  1074. DriveTypeInfo *pHeadPosition = pdrvInfo; // Hold the head position.
  1075. *pAppendToCache = FALSE; // Make it false by default.
  1076. // check if first character is '\'
  1077. TCHAR szSystemDrive[5] = NULL_STRING;
  1078. lstrcpyn(szSystemDrive,pszSystemDirectory,3); // First two character will be system drive (a:).
  1079. if(pszSourceFile[0] == _T('\\'))
  1080. {
  1081. // Check if second character if it is ';'
  1082. if(pszSourceFile[1] == ';')
  1083. {
  1084. pszFinalPath[0] = pszSourceFile[2]; // make 3rd character as drive letter
  1085. pszFinalPath[1] = ':'; // make 2nd character ':'
  1086. pszFinalPath[2] = '\0'; // make 3nd character NULL
  1087. dwFoundCount = 0;
  1088. for (lTemp = 0;lTemp <5;lTemp++) // search for 3rd '\'
  1089. {
  1090. lCount = szTemp.Find(_T("\\"));
  1091. if(lCount!=-1)
  1092. {
  1093. dwFoundCount++;
  1094. if(dwFoundCount == 4 )// this should always (if any)after 4rd character from start
  1095. {
  1096. lstrcat(pszFinalPath,(LPCWSTR)szTemp.Mid(lCount));
  1097. return TRUE;
  1098. }
  1099. szTemp = szTemp.Mid(lCount+1);
  1100. continue;
  1101. }
  1102. *pAppendToCache = TRUE;
  1103. return FALSE;
  1104. }
  1105. }
  1106. else
  1107. {
  1108. // check first of all for system drive
  1109. szTemp = szSystemDrive;
  1110. szTemp+=pszSourceFile;
  1111. // now check for its existance....
  1112. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1113. if(hHandle != INVALID_HANDLE_VALUE)
  1114. {
  1115. FindClose(hHandle); // closed opened find handle
  1116. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1117. return TRUE;
  1118. }
  1119. // check file for each FIXED drive
  1120. for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
  1121. {
  1122. if(lstrcmpi(szSystemDrive,pdrvInfo->szDrive) == 0)
  1123. continue; // as system drive is already checked
  1124. if(pdrvInfo->uiDriveType == DRIVE_FIXED)
  1125. {
  1126. szTemp = pdrvInfo->szDrive;
  1127. szTemp+=pszSourceFile;
  1128. // now check for its existance....
  1129. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1130. if(hHandle == INVALID_HANDLE_VALUE)
  1131. {
  1132. continue;
  1133. }
  1134. else
  1135. {
  1136. FindClose(hHandle); // closed opened find handle
  1137. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1138. return TRUE;
  1139. }
  1140. } // end if
  1141. } // End for loop
  1142. pdrvInfo = pHeadPosition ; // retore original position.
  1143. // check file for other drive which is present...
  1144. for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
  1145. {
  1146. // Check for NON_FIXED drive only if it is physicaly present
  1147. if((pdrvInfo->uiDriveType != DRIVE_FIXED) && (pdrvInfo->bDrivePresent == TRUE))
  1148. {
  1149. szTemp = pdrvInfo->szDrive;
  1150. szTemp+=pszSourceFile;
  1151. // now check for its existance....
  1152. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1153. if(hHandle == INVALID_HANDLE_VALUE)
  1154. {
  1155. continue;
  1156. }
  1157. else
  1158. {
  1159. FindClose(hHandle); // closed opened find handle
  1160. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1161. return TRUE;
  1162. }
  1163. } // end if
  1164. } // End for loop
  1165. // Now try if file is opend on remote system without
  1166. // having drive map. in this we are assuming that file name
  1167. // is containing atleast 3 '\' characters.
  1168. szTemp = pszSourceFile;
  1169. pszFinalPath[0] = '\\'; // make 3rd character '\'
  1170. pszFinalPath[1] = '\0'; // make 2nd character '\o'
  1171. dwFoundCount = 0;
  1172. for (lTemp = 0;lTemp <4;lTemp++) // search for 3rd '\'
  1173. {
  1174. lCount = szTemp.Find(_T("\\"));
  1175. if(lCount!=-1)
  1176. {
  1177. szTemp = szTemp.Mid(lCount+1);
  1178. dwFoundCount++;
  1179. }
  1180. else
  1181. {
  1182. break;
  1183. }
  1184. if (dwFoundCount == 3)
  1185. {
  1186. lstrcat(pszFinalPath,pszSourceFile);
  1187. // Now try to check its physical existance
  1188. hHandle = FindFirstFile(pszFinalPath,&win32FindData);
  1189. if(hHandle == INVALID_HANDLE_VALUE)
  1190. {
  1191. // Now try to append \* to it...(this will check if
  1192. // if pszFinalPath is a directory or not)
  1193. lstrcpy(szTempStr,pszFinalPath);
  1194. lstrcat(szTempStr,L"\\*");
  1195. hHandle = FindFirstFile(szTempStr,&win32FindData);
  1196. if(hHandle == INVALID_HANDLE_VALUE)
  1197. {
  1198. // now its sure this is not a valid directory or file
  1199. // so append it to chache
  1200. *pAppendToCache = TRUE;
  1201. return FALSE;
  1202. }
  1203. FindClose(hHandle);
  1204. return TRUE;
  1205. }
  1206. FindClose(hHandle);
  1207. return TRUE;
  1208. }
  1209. } // End for
  1210. }// End else
  1211. } // end if
  1212. else // means string not started with '\'
  1213. {
  1214. lstrcpy(pszFinalPath,pszCurrentDirectory);
  1215. lstrcat(pszFinalPath,L"\\");
  1216. lstrcat(pszFinalPath,pszSourceFile);
  1217. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1218. if(hHandle != INVALID_HANDLE_VALUE)
  1219. {
  1220. FindClose(hHandle); // closed opened find handle
  1221. return TRUE;
  1222. }
  1223. // check first of all for system drive
  1224. szTemp = szSystemDrive;
  1225. szTemp+=pszSourceFile;
  1226. // now check for its existance....
  1227. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1228. if(hHandle != INVALID_HANDLE_VALUE)
  1229. {
  1230. FindClose(hHandle); // closed opened find handle
  1231. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1232. return TRUE;
  1233. }
  1234. // restores the head position for the pointer.
  1235. pdrvInfo = pHeadPosition ;
  1236. // check file for each FIXED drive
  1237. for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
  1238. {
  1239. if(lstrcmpi(szSystemDrive,pdrvInfo->szDrive) == 0)
  1240. continue; // as system drive is already checked
  1241. if(pdrvInfo->uiDriveType == DRIVE_FIXED)
  1242. {
  1243. szTemp = pdrvInfo->szDrive;
  1244. szTemp += L"\\"; // append \
  1245. szTemp+=pszSourceFile;
  1246. // now check for its existance....
  1247. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1248. if(hHandle == INVALID_HANDLE_VALUE)
  1249. {
  1250. continue;
  1251. }
  1252. else
  1253. {
  1254. FindClose(hHandle); // closed opened find handle
  1255. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1256. return TRUE;
  1257. }
  1258. } // end if
  1259. } // End for loop
  1260. pdrvInfo = pHeadPosition ; // retore original position.
  1261. // check file for other drive (Like Floppy or CD-ROM etc. ) which is present...
  1262. for (dwTemp=0;dwTemp<dwTotalDrives;dwTemp++,pdrvInfo++)
  1263. {
  1264. if((pdrvInfo->uiDriveType != DRIVE_FIXED) && (pdrvInfo->bDrivePresent == TRUE))
  1265. {
  1266. szTemp = pdrvInfo->szDrive;
  1267. szTemp += L"\\"; // append '\'
  1268. szTemp+=pszSourceFile;
  1269. // now check for its existance....
  1270. hHandle = FindFirstFile((LPCWSTR)szTemp,&win32FindData);
  1271. if(hHandle == INVALID_HANDLE_VALUE)
  1272. {
  1273. continue;
  1274. }
  1275. else
  1276. {
  1277. FindClose(hHandle); // closed opened find handle
  1278. lstrcpy(pszFinalPath,(LPCWSTR)szTemp);
  1279. return TRUE;
  1280. }
  1281. } // end if
  1282. } // End for loop
  1283. }
  1284. *pAppendToCache = TRUE;
  1285. return FALSE;
  1286. }
  1287. /*****************************************************************************
  1288. Routine Description:
  1289. This routine will format the pFileName according to column width
  1290. Arguments:
  1291. [in/out] pFileName : path to be formatted
  1292. [in] dwFormat : Format given
  1293. [in] dwColWidth : Column width
  1294. Return Value:
  1295. none
  1296. ******************************************************************************/
  1297. void FormatFileName(LPTSTR pFileName,DWORD dwFormat,LONG dwColWidth)
  1298. {
  1299. CHString szCHString(pFileName);
  1300. if((szCHString.GetLength()>(dwColWidth))&&
  1301. (dwFormat == SR_FORMAT_TABLE))
  1302. {
  1303. // If file path is too big to fit in column width
  1304. // then it is cut like..
  1305. // c:\..\rest_of_the_path.
  1306. CHString szTemp = szCHString.Right(dwColWidth-6);;
  1307. DWORD dwTemp = szTemp.GetLength();
  1308. szTemp = szTemp.Mid(szTemp.Find(SINGLE_SLASH),
  1309. dwTemp);
  1310. szCHString.Format(L"%s%s%s",szCHString.Mid(0,3),
  1311. DOT_DOT,
  1312. szTemp);
  1313. }
  1314. lstrcpy(pFileName,(LPCWSTR)szCHString);
  1315. return;
  1316. }