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.

1172 lines
24 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. TrackFS.cpp
  5. Abstract:
  6. Track the directories the app looks at and record them into a file.
  7. History:
  8. 04/04/2001 maonis Created
  9. --*/
  10. #include "precomp.h"
  11. #include "utils.h"
  12. #include "secutils.h"
  13. #include <stdio.h>
  14. #define APPPATCH_DIR L"AppPatch\\"
  15. #define APPPATCH_DIR_LEN (sizeof(APPPATCH_DIR) / sizeof(WCHAR) - 1)
  16. #define TRACK_LOG_SUFFIX L".LUA.log"
  17. #define TRACK_LOG_SUFFIX_LEN (sizeof(TRACK_LOG_SUFFIX) / sizeof(WCHAR) - 1)
  18. struct DISTINCT_OBJ
  19. {
  20. DISTINCT_OBJ* next;
  21. LPWSTR pwszName;
  22. };
  23. static WCHAR g_wszProgramFiles[MAX_PATH] = L"";
  24. static DWORD g_cProgramFiles = 0;
  25. DWORD
  26. LuatpGetProgramFilesDirW()
  27. {
  28. if (g_cProgramFiles == 0)
  29. {
  30. WCHAR wszProgramFiles[MAX_PATH];
  31. if (GetEnvironmentVariableW(L"ProgramFiles", wszProgramFiles, MAX_PATH))
  32. {
  33. DWORD dwSize = GetLongPathNameW(wszProgramFiles, g_wszProgramFiles, MAX_PATH);
  34. if (dwSize <= MAX_PATH)
  35. {
  36. //
  37. // Only if we successfully got the path and it's not more
  38. // than MAX_PATH will we set the global values.
  39. //
  40. g_cProgramFiles = dwSize;
  41. }
  42. else
  43. {
  44. g_wszProgramFiles[0] = L'\0';
  45. }
  46. }
  47. }
  48. return g_cProgramFiles;
  49. }
  50. BOOL
  51. LuatpIsProgramFilesDirectory(
  52. LPCWSTR pwszPath
  53. )
  54. {
  55. LuatpGetProgramFilesDirW();
  56. if (g_cProgramFiles)
  57. {
  58. return !_wcsnicmp(pwszPath, g_wszProgramFiles, g_cProgramFiles);
  59. }
  60. return FALSE;
  61. }
  62. // We only record things when the file
  63. // 1) is not in the user profile dir - in which we know we don't need to redirect;
  64. // 2) is not in the program files dir - in which we know we will need to redirect;
  65. // because in those cases we know what to do so the user doesn't need to make the
  66. // choice.
  67. BOOL
  68. LuatpShouldRecord(
  69. LPCWSTR pwszPath
  70. )
  71. {
  72. //if (LuatpIsUserDirectory(pwszPath) ||
  73. // LuatpIsProgramFilesDirectory(pwszPath))
  74. if (IsUserDirectory(pwszPath))
  75. {
  76. return FALSE;
  77. }
  78. return TRUE;
  79. }
  80. LPWSTR
  81. LuatpGetLongObjectName(
  82. LPCWSTR pwszName,
  83. BOOL fIsDirectory
  84. )
  85. {
  86. BOOL fIsSuccess = FALSE;
  87. LPWSTR pwszLongNameObject = NULL;
  88. LPWSTR pwszObject = NULL;
  89. if (!pwszName)
  90. {
  91. return NULL;
  92. }
  93. //
  94. // First get the full path.
  95. //
  96. DWORD cFullPath = GetFullPathNameW(pwszName, 0, NULL, NULL);
  97. if (!cFullPath)
  98. {
  99. DPF("TrackFS", eDbgLevelError,
  100. "[LuatpGetLongObjectName] Failed to get the length of full path: %d",
  101. GetLastError());
  102. return NULL;
  103. }
  104. //
  105. // We allocate one more char to make space for the trailing slash for dir names.
  106. //
  107. pwszObject = new WCHAR [cFullPath + 1];
  108. if (!pwszObject)
  109. {
  110. DPF("TrackFS", eDbgLevelError,
  111. "[LuatpGetLongObjectName] Failed to allocate %d WCHARs",
  112. cFullPath + 1);
  113. return NULL;
  114. }
  115. if (!GetFullPathNameW(pwszName, cFullPath, pwszObject, NULL))
  116. {
  117. DPF("TrackFS", eDbgLevelError,
  118. "[LuatpGetLongObjectName] Failed to get the full path: %d",
  119. GetLastError());
  120. goto EXIT;
  121. }
  122. //
  123. // If it's not a valid file name, we don't add it.
  124. //
  125. if (wcslen(pwszObject) < 2 || !iswalpha(pwszObject[0]) || (pwszObject[1] != L':'))
  126. {
  127. goto EXIT;
  128. }
  129. if (fIsDirectory)
  130. {
  131. //
  132. // If it's a directory we make sure there's a trailing slash.
  133. //
  134. if (pwszObject[cFullPath - 2] != L'\\')
  135. {
  136. pwszObject[cFullPath - 1] = L'\\';
  137. pwszObject[cFullPath] = L'\0';
  138. }
  139. }
  140. //
  141. // Convert it to all lower case.
  142. //
  143. _wcslwr(pwszObject);
  144. //
  145. // Convert it to the long names.
  146. //
  147. DWORD cLongPath = GetLongPathName(pwszObject, NULL, 0);
  148. if (!cLongPath)
  149. {
  150. DPF("TrackFS", eDbgLevelError,
  151. "[LuatpGetLongObjectName] Failed to get the length of long path: %d",
  152. GetLastError());
  153. goto EXIT;
  154. }
  155. pwszLongNameObject = new WCHAR [cLongPath];
  156. if (!pwszLongNameObject)
  157. {
  158. DPF("TrackFS", eDbgLevelError,
  159. "[LuatpGetLongObjectName] Failed to allocate %d WCHARs",
  160. cLongPath);
  161. goto EXIT;
  162. }
  163. if (!GetLongPathName(pwszObject, pwszLongNameObject, cLongPath))
  164. {
  165. DPF("TrackFS", eDbgLevelError,
  166. "[LuatpGetLongObjectName] Failed to get the long path: %d",
  167. GetLastError());
  168. goto EXIT;
  169. }
  170. if (LuatpShouldRecord(pwszLongNameObject))
  171. {
  172. //
  173. // We only record the objects that are not in the user profile directory.
  174. //
  175. fIsSuccess = TRUE;
  176. }
  177. EXIT:
  178. delete [] pwszObject;
  179. if (!fIsSuccess)
  180. {
  181. delete [] pwszLongNameObject;
  182. pwszLongNameObject = NULL;
  183. }
  184. return pwszLongNameObject;
  185. }
  186. /*++
  187. The tracking class for the file system.
  188. History:
  189. 04/04/2001 maonis Created
  190. --*/
  191. class CTrackObject
  192. {
  193. public:
  194. BOOL Init();
  195. VOID Free();
  196. // If the object name needs to be processed, eg, it's not the full path
  197. // or not the long name, call this method to process it first before
  198. // adding to the list.
  199. VOID AddObject(LPCWSTR pwszName, BOOL fIsDirectory);
  200. // If the caller already processed the file name, call this method
  201. // to add it directly.
  202. VOID AddObjectDirect(LPWSTR pwszName, BOOL fIsDirectory);
  203. // This is specially for GetTempFileName - we add
  204. // *.tmp after the path.
  205. VOID AddObjectGetTempFileName(LPCWSTR pwszPath);
  206. VOID Record();
  207. private:
  208. BOOL AddObjectToList(LPWSTR pwszName, BOOL fIsDirectory);
  209. VOID WriteToLog(LPCWSTR pwszDir);
  210. HANDLE m_hLog;
  211. WCHAR m_wszLog[MAX_PATH];
  212. DISTINCT_OBJ* m_pDistinctDirs;
  213. DISTINCT_OBJ* m_pDistinctFiles;
  214. DWORD m_cDistinctDirs;
  215. DWORD m_cDistinctFiles;
  216. };
  217. BOOL
  218. CTrackObject::AddObjectToList(
  219. LPWSTR pwszName,
  220. BOOL fIsDirectory
  221. )
  222. {
  223. BOOL fIsSuccess = FALSE;
  224. DISTINCT_OBJ* pDistinctObjs = fIsDirectory ? m_pDistinctDirs : m_pDistinctFiles;
  225. DISTINCT_OBJ* pObj = pDistinctObjs;
  226. // Check to see if this file already exists in the list.
  227. while (pObj)
  228. {
  229. if (!wcscmp(pObj->pwszName, pwszName))
  230. {
  231. break;
  232. }
  233. pObj = pObj->next;
  234. }
  235. if (!pObj)
  236. {
  237. pObj = new DISTINCT_OBJ;
  238. if (pObj)
  239. {
  240. DWORD cLen = wcslen(pwszName);
  241. pObj->pwszName = new WCHAR [cLen + 1];
  242. if (pObj->pwszName)
  243. {
  244. wcscpy(pObj->pwszName, pwszName);
  245. pObj->next = pDistinctObjs;
  246. if (fIsDirectory)
  247. {
  248. ++m_cDistinctDirs;
  249. m_pDistinctDirs = pObj;
  250. }
  251. else
  252. {
  253. ++m_cDistinctFiles;
  254. m_pDistinctFiles = pObj;
  255. }
  256. fIsSuccess = TRUE;
  257. }
  258. else
  259. {
  260. DPF("TrackFS", eDbgLevelError,
  261. "[CTrackObject::AddObjectToList] Error allocating %d WCHARs",
  262. cLen + 1);
  263. }
  264. }
  265. else
  266. {
  267. DPF("TrackFS", eDbgLevelError,
  268. "[CTrackObject::AddObjectToList] Error allocating memory for new node");
  269. }
  270. }
  271. return fIsSuccess;
  272. }
  273. /*++
  274. Function Description:
  275. For files it's simple - we just store the file name in a list and search
  276. through the list to see if it's already in the list. If it is we are done;
  277. else we add it to the beginning of the list.
  278. We don't expect there are too many calls to modify files so a linked list
  279. is fine.
  280. Arguments:
  281. IN pwszFileName - file name.
  282. Return Value:
  283. none.
  284. History:
  285. 05/08/2001 maonis Created
  286. --*/
  287. VOID
  288. CTrackObject::AddObject(
  289. LPCWSTR pwszName,
  290. BOOL fIsDirectory
  291. )
  292. {
  293. BOOL fIsSuccess = FALSE;
  294. LPWSTR pwszLongNameObject = LuatpGetLongObjectName(pwszName, fIsDirectory);
  295. if (pwszLongNameObject)
  296. {
  297. AddObjectToList(pwszLongNameObject, fIsDirectory);
  298. delete [] pwszLongNameObject;
  299. }
  300. }
  301. VOID
  302. CTrackObject::AddObjectDirect(
  303. LPWSTR pwszName,
  304. BOOL fIsDirectory
  305. )
  306. {
  307. if (pwszName)
  308. {
  309. AddObjectToList(pwszName, fIsDirectory);
  310. }
  311. }
  312. /*++
  313. Function Description:
  314. Write the directory to the log as ANSI characters.
  315. Note this method uses 2 str* routines and it IS DBCS aware.
  316. Arguments:
  317. IN pwszDir - the directory to write to the log.
  318. Return Value:
  319. None.
  320. History:
  321. 04/04/2001 maonis Created
  322. --*/
  323. VOID
  324. CTrackObject::WriteToLog(
  325. LPCWSTR pwsz)
  326. {
  327. if (!pwsz || !*pwsz)
  328. {
  329. return;
  330. }
  331. //
  332. // Get the number of bytes required to convert the string to ansi.
  333. //
  334. DWORD dwSize = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL);
  335. LPSTR psz = new CHAR [dwSize + 2];
  336. if (psz)
  337. {
  338. WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, dwSize, 0, 0);
  339. psz[dwSize - 1] = '\r';
  340. psz[dwSize] = '\n';
  341. psz[dwSize + 1] = '\0';
  342. DWORD dwBytesWritten = 0;
  343. WriteFile(
  344. m_hLog,
  345. psz,
  346. dwSize + 1,
  347. &dwBytesWritten,
  348. NULL);
  349. delete [] psz;
  350. }
  351. else
  352. {
  353. DPF("TrackFS", eDbgLevelError,
  354. "[CTrackObject::WriteToLog] Failed to allocate %d CHARs",
  355. dwSize);
  356. }
  357. }
  358. /*++
  359. Function Description:
  360. Create the log file in %windir%\apppatch directory. We want to make sure
  361. we can create this file so we don't run the app to the end only to find
  362. that we can't record the results into a file.
  363. Arguments:
  364. None
  365. Return Value:
  366. TRUE - if log created successfully.
  367. FALSE otherwise.
  368. History:
  369. 04/04/2001 maonis Created
  370. --*/
  371. BOOL
  372. CTrackObject::Init()
  373. {
  374. m_pDistinctDirs = NULL;
  375. m_pDistinctFiles = NULL;
  376. m_cDistinctDirs = 0;
  377. m_cDistinctFiles = 0;
  378. WCHAR szModuleName[MAX_PATH + 1] = L"";
  379. LPWSTR pwszModuleNameStart = NULL;
  380. LPWSTR pwszModuleNameExtStart = NULL;
  381. DWORD cAppPatchLen = 0;
  382. DWORD cModuleNameLen = 0;
  383. DWORD cTotalLen = 0;
  384. DWORD dwRes = 0;
  385. GetSystemRootDirW();
  386. //
  387. // GetModuleFileNameW is an awful API. If you don't pass in a buffer
  388. // that's big enough to hold the module (including the terminating NULL), it
  389. // returns the passed in buffer size (NOT the required length) which means
  390. // it doesn't return an error - it just fills upto the passed in buffer size
  391. // so does NOT NULL terminate the string. So we set the last char to NULL and
  392. // make sure it doesn't get overwritten.
  393. //
  394. szModuleName[MAX_PATH] = L'\0';
  395. dwRes = GetModuleFileNameW(NULL, szModuleName, MAX_PATH + 1);
  396. if (!dwRes || szModuleName[MAX_PATH] != L'\0')
  397. {
  398. DPF("TrackFS", eDbgLevelError,
  399. "[CTrackObject::Init] Error getting the module name: %d",
  400. GetLastError());
  401. return FALSE;
  402. }
  403. pwszModuleNameStart = wcsrchr(szModuleName, L'\\');
  404. if (!pwszModuleNameStart)
  405. {
  406. DPF("TrackFS", eDbgLevelError,
  407. "[CTrackObject::Init] We can't find where the file name starts??? %S",
  408. szModuleName);
  409. return FALSE;
  410. }
  411. ++pwszModuleNameStart;
  412. cModuleNameLen = wcslen(pwszModuleNameStart);
  413. //
  414. // We don't need the path anymore.
  415. //
  416. memmove(szModuleName, pwszModuleNameStart, cModuleNameLen * sizeof(WCHAR));
  417. szModuleName[cModuleNameLen] = L'\0';
  418. //
  419. // Get rid of the extension.
  420. //
  421. pwszModuleNameExtStart = wcsrchr(szModuleName, L'.');
  422. //
  423. // If there's no extension we just use the whole file name.
  424. //
  425. if (pwszModuleNameExtStart)
  426. {
  427. *pwszModuleNameExtStart = L'\0';
  428. }
  429. cModuleNameLen = wcslen(szModuleName);
  430. //
  431. // Make sure we don't have a buffer overflow.
  432. //
  433. cTotalLen =
  434. g_cSystemRoot + APPPATCH_DIR_LEN + // %windir%\AppPatch\ dir
  435. cModuleNameLen + // module name without extension
  436. TRACK_LOG_SUFFIX_LEN + // .LUA.log suffix
  437. 1; // terminating NULL
  438. if (cTotalLen > MAX_PATH)
  439. {
  440. DPF("TrackFS", eDbgLevelError,
  441. "[CTrackObject::Init] The file name is %d chars - "
  442. "we don't handle names longer than MAX_PATH",
  443. cTotalLen);
  444. return FALSE;
  445. }
  446. //
  447. // Construct the file name.
  448. //
  449. wcsncpy(m_wszLog, g_wszSystemRoot, g_cSystemRoot);
  450. wcsncpy(m_wszLog + g_cSystemRoot, APPPATCH_DIR, APPPATCH_DIR_LEN);
  451. wcsncpy(m_wszLog + (g_cSystemRoot + APPPATCH_DIR_LEN), szModuleName, cModuleNameLen);
  452. wcsncpy(m_wszLog + (g_cSystemRoot + APPPATCH_DIR_LEN + cModuleNameLen), TRACK_LOG_SUFFIX, TRACK_LOG_SUFFIX_LEN);
  453. m_wszLog[cTotalLen - 1] = L'\0';
  454. //
  455. // Delete the file first if it exists.
  456. //
  457. DeleteFileW(m_wszLog);
  458. if ((m_hLog = CreateFileW(
  459. m_wszLog,
  460. GENERIC_READ | GENERIC_WRITE,
  461. FILE_SHARE_READ,
  462. NULL,
  463. CREATE_ALWAYS,
  464. 0,
  465. NULL)) == INVALID_HANDLE_VALUE)
  466. {
  467. DPF("TrackFS", eDbgLevelError,
  468. "[CTrackObject::Init] Error creating log %S: %d", m_wszLog, GetLastError());
  469. return FALSE;
  470. }
  471. else
  472. {
  473. DPF("TrackFS", eDbgLevelInfo, "[CTrackObject::Init] Created the log %S", m_wszLog);
  474. CloseHandle(m_hLog);
  475. return TRUE;
  476. }
  477. }
  478. /*++
  479. Function Description:
  480. Free the linked list.
  481. Arguments:
  482. None
  483. Return Value:
  484. None
  485. History:
  486. 04/04/2001 maonis Created
  487. --*/
  488. VOID
  489. CTrackObject::Free()
  490. {
  491. DISTINCT_OBJ* pDir = m_pDistinctDirs;
  492. DISTINCT_OBJ* pTempDir;
  493. while (pDir)
  494. {
  495. pTempDir = pDir;
  496. pDir = pDir->next;
  497. delete [] pTempDir->pwszName;
  498. delete pTempDir;
  499. }
  500. }
  501. /*++
  502. Function Description:
  503. Write the list of directories to the log.
  504. Arguments:
  505. None
  506. Return Value:
  507. None
  508. History:
  509. 04/04/2001 maonis Created
  510. --*/
  511. VOID
  512. CTrackObject::Record()
  513. {
  514. if ((m_hLog = CreateFileW(
  515. m_wszLog,
  516. GENERIC_READ | GENERIC_WRITE,
  517. FILE_SHARE_READ,
  518. NULL,
  519. OPEN_EXISTING,
  520. 0,
  521. NULL)) != INVALID_HANDLE_VALUE)
  522. {
  523. // Empty the old log.
  524. SetFilePointer(m_hLog, 0, 0, FILE_BEGIN);
  525. SetEndOfFile(m_hLog);
  526. WCHAR wszHeader[32];
  527. if (_snwprintf(wszHeader, 31, L"D%d", m_cDistinctDirs) < 0)
  528. {
  529. DPF("TrackFS", eDbgLevelError,
  530. "[CTrackObject::Record] Too many dirs??? %d",
  531. m_cDistinctDirs);
  532. return;
  533. }
  534. wszHeader[31] = L'\0';
  535. WriteToLog(wszHeader);
  536. //
  537. // Dump the directories to the log - each dir is on its own line.
  538. //
  539. DISTINCT_OBJ* pDir = m_pDistinctDirs;
  540. while (pDir)
  541. {
  542. WriteToLog(pDir->pwszName);
  543. pDir = pDir->next;
  544. }
  545. if (_snwprintf(wszHeader, 31, L"F%d", m_cDistinctFiles) < 0)
  546. {
  547. DPF("TrackFS", eDbgLevelError,
  548. "[CTrackObject::Record] Too many files??? %d",
  549. m_cDistinctFiles);
  550. return;
  551. }
  552. wszHeader[31] = L'\0';
  553. WriteToLog(wszHeader);
  554. //
  555. // Dump the files to the log - each file is on its own line.
  556. //
  557. DISTINCT_OBJ* pFile = m_pDistinctFiles;
  558. while (pFile)
  559. {
  560. WriteToLog(pFile->pwszName);
  561. pFile = pFile->next;
  562. }
  563. CloseHandle(m_hLog);
  564. }
  565. // Make the file hidden so people don't accidently mess it up.
  566. DWORD dwAttrib = GetFileAttributes(m_wszLog);
  567. SetFileAttributes(m_wszLog, dwAttrib | FILE_ATTRIBUTE_HIDDEN);
  568. }
  569. CTrackObject g_td;
  570. /*++
  571. Custom exception handler.
  572. --*/
  573. LONG
  574. ExceptionFilter(
  575. struct _EXCEPTION_POINTERS *ExceptionInfo
  576. )
  577. {
  578. // Whenever we get an unhandled exception, we dump the stuff to the log.
  579. g_td.Record();
  580. return EXCEPTION_CONTINUE_SEARCH;
  581. }
  582. //
  583. // Exported APIs.
  584. //
  585. HANDLE
  586. LuatCreateFileW(
  587. LPCWSTR lpFileName,
  588. DWORD dwDesiredAccess,
  589. DWORD dwShareMode,
  590. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  591. DWORD dwCreationDisposition,
  592. DWORD dwFlagsAndAttributes,
  593. HANDLE hTemplateFile
  594. )
  595. {
  596. DPF("TrackFS", eDbgLevelInfo,
  597. "[CreateFileW] lpFileName=%S; dwDesiredAccess=0x%08x; dwCreationDisposition=%d",
  598. lpFileName, dwDesiredAccess, dwCreationDisposition);
  599. HANDLE hFile = CreateFileW(
  600. lpFileName,
  601. dwDesiredAccess,
  602. dwShareMode,
  603. lpSecurityAttributes,
  604. dwCreationDisposition,
  605. dwFlagsAndAttributes,
  606. hTemplateFile);
  607. if (hFile != INVALID_HANDLE_VALUE)
  608. {
  609. LUA_GET_API_ERROR;
  610. if (RequestWriteAccess(dwCreationDisposition, dwDesiredAccess))
  611. {
  612. g_td.AddObject(lpFileName, FALSE);
  613. }
  614. LUA_SET_API_ERROR;
  615. }
  616. return hFile;
  617. }
  618. BOOL
  619. LuatCopyFileW(
  620. LPCWSTR lpExistingFileName,
  621. LPCWSTR lpNewFileName,
  622. BOOL bFailIfExists
  623. )
  624. {
  625. DPF("TrackFS", eDbgLevelInfo,
  626. "[CopyFileW] lpExistingFileName=%S; lpNewFileName=%S; bFailIfExists=%d",
  627. lpExistingFileName, lpNewFileName, bFailIfExists);
  628. BOOL bRet = CopyFileW(lpExistingFileName, lpNewFileName, bFailIfExists);
  629. if (bRet)
  630. {
  631. LUA_GET_API_ERROR;
  632. g_td.AddObject(lpNewFileName, FALSE);
  633. LUA_SET_API_ERROR;
  634. }
  635. return bRet;
  636. }
  637. BOOL
  638. LuatCreateDirectoryW(
  639. LPCWSTR lpPathName,
  640. LPSECURITY_ATTRIBUTES lpSecurityAttributes
  641. )
  642. {
  643. DPF("TrackFS", eDbgLevelInfo,
  644. "[CreateDirectoryW] lpPathName=%S", lpPathName);
  645. BOOL bRet = CreateDirectoryW(lpPathName, lpSecurityAttributes);
  646. if (bRet)
  647. {
  648. LUA_GET_API_ERROR;
  649. g_td.AddObject(lpPathName, TRUE);
  650. LUA_SET_API_ERROR;
  651. }
  652. return bRet;
  653. }
  654. BOOL
  655. LuatSetFileAttributesW(
  656. LPCWSTR lpFileName,
  657. DWORD dwFileAttributes
  658. )
  659. {
  660. DPF("TrackFS", eDbgLevelInfo,
  661. "[SetFileAttributesW] lpFileName=%S", lpFileName);
  662. BOOL bRet = SetFileAttributesW(lpFileName, dwFileAttributes);
  663. if (bRet)
  664. {
  665. LUA_GET_API_ERROR;
  666. DWORD dwAttrib = GetFileAttributesW(lpFileName);
  667. if (dwAttrib != -1)
  668. {
  669. g_td.AddObject(lpFileName, dwAttrib & FILE_ATTRIBUTE_DIRECTORY);
  670. }
  671. LUA_SET_API_ERROR;
  672. }
  673. return bRet;
  674. }
  675. BOOL
  676. LuatDeleteFileW(
  677. LPCWSTR lpFileName
  678. )
  679. {
  680. DPF("TrackFS", eDbgLevelInfo,
  681. "[DeleteFileW] lpFileName=%S", lpFileName);
  682. LPWSTR pwszTempFile = LuatpGetLongObjectName(lpFileName, FALSE);
  683. BOOL bRet = DeleteFileW(lpFileName);
  684. if (bRet)
  685. {
  686. LUA_GET_API_ERROR;
  687. g_td.AddObjectDirect(pwszTempFile, FALSE);
  688. LUA_SET_API_ERROR;
  689. }
  690. delete [] pwszTempFile;
  691. return bRet;
  692. }
  693. BOOL
  694. LuatMoveFileW(
  695. LPCWSTR lpExistingFileName,
  696. LPCWSTR lpNewFileName
  697. )
  698. {
  699. DPF("TrackFS", eDbgLevelInfo,
  700. "[MoveFileW] lpExistingFileName=%S; lpNewFileName=%S", lpExistingFileName, lpNewFileName);
  701. LPWSTR pwszTempFile = LuatpGetLongObjectName(lpExistingFileName, FALSE);
  702. BOOL bRet = MoveFileW(lpExistingFileName, lpNewFileName);
  703. if (bRet)
  704. {
  705. LUA_GET_API_ERROR;
  706. g_td.AddObjectDirect(pwszTempFile, FALSE);
  707. g_td.AddObject(lpNewFileName, FALSE);
  708. LUA_SET_API_ERROR;
  709. }
  710. delete [] pwszTempFile;
  711. return bRet;
  712. }
  713. BOOL
  714. LuatRemoveDirectoryW(
  715. LPCWSTR lpPathName
  716. )
  717. {
  718. DPF("TrackFS", eDbgLevelInfo,
  719. "[RemoveDirectoryW] lpPathName=%S", lpPathName);
  720. LPWSTR pwszTempDir = LuatpGetLongObjectName(lpPathName, TRUE);
  721. BOOL bRet = RemoveDirectoryW(lpPathName);
  722. if (bRet)
  723. {
  724. LUA_GET_API_ERROR;
  725. g_td.AddObjectDirect(pwszTempDir, TRUE);
  726. LUA_SET_API_ERROR;
  727. }
  728. delete [] pwszTempDir;
  729. return bRet;
  730. }
  731. UINT
  732. LuatGetTempFileNameW(
  733. LPCWSTR lpPathName,
  734. LPCWSTR lpPrefixString,
  735. UINT uUnique,
  736. LPWSTR lpTempFileName
  737. )
  738. {
  739. DPF("TrackFS", eDbgLevelInfo,
  740. "[GetTempFileNameW] lpPathName=%S", lpPathName);
  741. UINT uiRet = GetTempFileNameW(lpPathName, lpPrefixString, uUnique, lpTempFileName);
  742. if (uiRet && !uUnique)
  743. {
  744. LUA_GET_API_ERROR;
  745. g_td.AddObject(lpTempFileName, FALSE);
  746. LUA_SET_API_ERROR;
  747. }
  748. return uiRet;
  749. }
  750. BOOL
  751. LuatWritePrivateProfileStringW(
  752. LPCWSTR lpAppName,
  753. LPCWSTR lpKeyName,
  754. LPCWSTR lpString,
  755. LPCWSTR lpFileName
  756. )
  757. {
  758. DPF("TrackFS", eDbgLevelInfo,
  759. "[WritePrivateProfileStringW] lpAppName=%S; lpKeyName=%S; lpString=%S; lpFileName=%S",
  760. lpAppName, lpKeyName, lpString, lpFileName);
  761. BOOL bRet = WritePrivateProfileStringW(
  762. lpAppName,
  763. lpKeyName,
  764. lpString,
  765. lpFileName);
  766. if (bRet)
  767. {
  768. LUA_GET_API_ERROR;
  769. WCHAR wszFileName[MAX_PATH] = L"";
  770. MakeFileNameForProfileAPIsW(lpFileName, wszFileName);
  771. g_td.AddObject(wszFileName, FALSE);
  772. LUA_SET_API_ERROR;
  773. }
  774. return bRet;
  775. }
  776. BOOL
  777. LuatWritePrivateProfileSectionW(
  778. LPCWSTR lpAppName,
  779. LPCWSTR lpString,
  780. LPCWSTR lpFileName
  781. )
  782. {
  783. DPF("TrackFS", eDbgLevelInfo,
  784. "[WritePrivateProfileSectionW] lpAppName=%S; lpString=%S; lpFileName=%S",
  785. lpAppName, lpString, lpFileName);
  786. BOOL bRet = WritePrivateProfileSectionW(
  787. lpAppName,
  788. lpString,
  789. lpFileName);
  790. if (bRet)
  791. {
  792. LUA_GET_API_ERROR;
  793. WCHAR wszFileName[MAX_PATH] = L"";
  794. MakeFileNameForProfileAPIsW(lpFileName, wszFileName);
  795. g_td.AddObject(wszFileName, FALSE);
  796. LUA_SET_API_ERROR;
  797. }
  798. return bRet;
  799. }
  800. BOOL
  801. LuatWritePrivateProfileStructW(
  802. LPCWSTR lpszSection,
  803. LPCWSTR lpszKey,
  804. LPVOID lpStruct,
  805. UINT uSizeStruct,
  806. LPCWSTR szFile
  807. )
  808. {
  809. DPF("TrackFS", eDbgLevelInfo,
  810. "[WritePrivateProfileStructW] lpszKey=%S; szFile=%S",
  811. lpszKey, szFile);
  812. BOOL bRet = WritePrivateProfileStructW(
  813. lpszSection,
  814. lpszKey,
  815. lpStruct,
  816. uSizeStruct,
  817. szFile);
  818. if (bRet)
  819. {
  820. LUA_GET_API_ERROR;
  821. WCHAR wszFileName[MAX_PATH] = L"";
  822. MakeFileNameForProfileAPIsW(szFile, wszFileName);
  823. g_td.AddObject(wszFileName, FALSE);
  824. LUA_SET_API_ERROR;
  825. }
  826. return bRet;
  827. }
  828. HFILE
  829. LuatOpenFile(
  830. LPCSTR lpFileName,
  831. LPOFSTRUCT lpReOpenBuff,
  832. UINT uStyle
  833. )
  834. {
  835. DPF("TrackFS", eDbgLevelInfo,
  836. "[OpenFile] lpFileName=%s", lpFileName);
  837. STRINGA2W wstrFileName(lpFileName);
  838. LPWSTR pwszTempFile = LuatpGetLongObjectName(wstrFileName, FALSE);
  839. HFILE hFile = OpenFile(lpFileName, lpReOpenBuff, uStyle);
  840. if (hFile != HFILE_ERROR)
  841. {
  842. if (uStyle & OF_CREATE ||
  843. uStyle & OF_DELETE ||
  844. uStyle & OF_READWRITE ||
  845. uStyle & OF_WRITE)
  846. {
  847. LUA_GET_API_ERROR;
  848. g_td.AddObjectDirect(pwszTempFile, FALSE);
  849. LUA_SET_API_ERROR;
  850. }
  851. }
  852. delete [] pwszTempFile;
  853. return hFile;
  854. }
  855. HFILE
  856. Luat_lopen(
  857. LPCSTR lpPathName,
  858. int iReadWrite
  859. )
  860. {
  861. DPF("TrackFS", eDbgLevelInfo,
  862. "[_lopen] lpPathName=%s", lpPathName);
  863. HFILE hFile = _lopen(lpPathName, iReadWrite);
  864. if (hFile != HFILE_ERROR)
  865. {
  866. if (iReadWrite & OF_READWRITE || iReadWrite & OF_WRITE)
  867. {
  868. LUA_GET_API_ERROR;
  869. STRINGA2W wstrPathName(lpPathName);
  870. g_td.AddObject(wstrPathName, FALSE);
  871. LUA_SET_API_ERROR;
  872. }
  873. }
  874. return hFile;
  875. }
  876. HFILE
  877. Luat_lcreat(
  878. LPCSTR lpPathName,
  879. int iAttribute
  880. )
  881. {
  882. DPF("TrackFS", eDbgLevelInfo,
  883. "[_lcreat] lpPathName=%s", lpPathName);
  884. HFILE hFile = _lcreat(lpPathName, iAttribute);
  885. if (hFile != HFILE_ERROR)
  886. {
  887. LUA_GET_API_ERROR;
  888. STRINGA2W wstrPathName(lpPathName);
  889. g_td.AddObject(wstrPathName, FALSE);
  890. LUA_SET_API_ERROR;
  891. }
  892. return hFile;
  893. }
  894. BOOL
  895. LuatFSInit()
  896. {
  897. SetUnhandledExceptionFilter(ExceptionFilter);
  898. return g_td.Init();
  899. }
  900. VOID
  901. LuatFSCleanup()
  902. {
  903. g_td.Record();
  904. g_td.Free();
  905. }