Leaked source code of windows server 2003
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.

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