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.

466 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. SyncSystemAndSystem32.cpp
  5. Abstract:
  6. This shim takes a semi-colon delimited command line of filenames.
  7. At process termination, the DLL will parse the extract each filename
  8. from the command line and make sure that the file exists in both
  9. the System directory and System32 (if it exists in either).
  10. Some older apps expect certain DLLs to be in System when under NT they
  11. belong in System32 (and vice versa).
  12. History:
  13. 03/15/2000 markder Created
  14. 10/18/2000 a-larrsh Add Wild Card support for command line.
  15. --*/
  16. #include "precomp.h"
  17. #include "CharVector.h"
  18. IMPLEMENT_SHIM_BEGIN(SyncSystemAndSystem32)
  19. #include "ShimHookMacro.h"
  20. APIHOOK_ENUM_BEGIN
  21. APIHOOK_ENUM_ENTRY(CreateFileA)
  22. APIHOOK_ENUM_ENTRY(CreateFileW)
  23. APIHOOK_ENUM_ENTRY(CloseHandle)
  24. APIHOOK_ENUM_ENTRY(CopyFileA)
  25. APIHOOK_ENUM_ENTRY(CopyFileW)
  26. APIHOOK_ENUM_ENTRY(CopyFileExA)
  27. APIHOOK_ENUM_ENTRY(CopyFileExW)
  28. APIHOOK_ENUM_ENTRY(GetFileVersionInfoSizeA)
  29. APIHOOK_ENUM_ENTRY(GetFileVersionInfoSizeW)
  30. APIHOOK_ENUM_END
  31. int g_nrgFilesToSync = 0;
  32. CString * g_rgFilesToSync = NULL;
  33. CString * g_csSystem = NULL; // c:\windows\system
  34. CString * g_csSystem32 = NULL; // c:\windows\system32
  35. VectorT<HANDLE> * g_hCachedHandles = NULL;
  36. void
  37. SyncDir(const CString & csFileToSync, const CString & csSrc, const CString & csDest)
  38. {
  39. // Don't need our own excpetion handler,
  40. // this routine is only called inside one already.
  41. CString csSrcFile(csSrc);
  42. csSrcFile.AppendPath(csFileToSync);
  43. WIN32_FIND_DATAW FindFileData;
  44. HANDLE hFind = FindFirstFileW(csSrcFile, &FindFileData);
  45. if (hFind != INVALID_HANDLE_VALUE)
  46. {
  47. // csFileToSync might be a wildcard
  48. do
  49. {
  50. CString csDestFile(csDest);
  51. csDestFile.AppendPath(FindFileData.cFileName);
  52. if (GetFileAttributesW(csDestFile) == -1)
  53. {
  54. // In System but not System32, copy it over
  55. CopyFileW(csSrcFile, csDestFile, FALSE);
  56. DPFN( eDbgLevelInfo, "File found in System but not in System32: %S", FindFileData.cFileName);
  57. DPFN( eDbgLevelInfo, "Copied over");
  58. }
  59. }
  60. while (FindNextFileW(hFind, &FindFileData));
  61. FindClose(hFind);
  62. }
  63. }
  64. void
  65. SyncSystemAndSystem32(const CString & csFileToSync)
  66. {
  67. SyncDir(csFileToSync, *g_csSystem, *g_csSystem32);
  68. SyncDir(csFileToSync, *g_csSystem32, *g_csSystem);
  69. }
  70. void
  71. SyncAllFiles()
  72. {
  73. CSTRING_TRY
  74. {
  75. for (int nFileCount = 0; nFileCount < g_nrgFilesToSync; ++nFileCount)
  76. {
  77. SyncSystemAndSystem32(g_rgFilesToSync[nFileCount]);
  78. }
  79. }
  80. CSTRING_CATCH
  81. {
  82. // Do nothing
  83. }
  84. }
  85. BOOL
  86. IsFileToSync(const CString & csFileName)
  87. {
  88. CSTRING_TRY
  89. {
  90. CString csFilePart;
  91. csFileName.GetLastPathComponent(csFilePart);
  92. for (int i = 0; i < g_nrgFilesToSync; ++i)
  93. {
  94. if (csFilePart == g_rgFilesToSync[i])
  95. {
  96. LOGN( eDbgLevelWarning, "File to sync detected: %S", csFileName.Get());
  97. return TRUE;
  98. }
  99. }
  100. }
  101. CSTRING_CATCH
  102. {
  103. // Do nothing
  104. }
  105. return FALSE;
  106. }
  107. BOOL
  108. IsFileToSync(LPCSTR szFileName)
  109. {
  110. CSTRING_TRY
  111. {
  112. CString csFileName(szFileName);
  113. return IsFileToSync(csFileName);
  114. }
  115. CSTRING_CATCH
  116. {
  117. // Do nothing
  118. }
  119. return FALSE;
  120. }
  121. BOOL
  122. IsFileToSync(LPCWSTR szFileName)
  123. {
  124. CSTRING_TRY
  125. {
  126. CString csFileName(szFileName);
  127. return IsFileToSync(csFileName);
  128. }
  129. CSTRING_CATCH
  130. {
  131. // Do nothing
  132. }
  133. return FALSE;
  134. }
  135. HANDLE
  136. APIHOOK(CreateFileA)(
  137. LPCSTR lpFileName, // file name
  138. DWORD dwDesiredAccess, // access mode
  139. DWORD dwShareMode, // share mode
  140. LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
  141. DWORD dwCreationDisposition, // how to create
  142. DWORD dwFlagsAndAttributes, // file attributes
  143. HANDLE hTemplateFile // handle to template file
  144. )
  145. {
  146. HANDLE hRet;
  147. LONG nHandleCount = 0;
  148. hRet = ORIGINAL_API(CreateFileA)(
  149. lpFileName,
  150. dwDesiredAccess,
  151. dwShareMode,
  152. lpSecurityAttributes,
  153. dwCreationDisposition,
  154. dwFlagsAndAttributes,
  155. hTemplateFile);
  156. if (hRet != INVALID_HANDLE_VALUE)
  157. {
  158. if (IsFileToSync(lpFileName))
  159. {
  160. g_hCachedHandles->AppendUnique(hRet);
  161. }
  162. }
  163. return hRet;
  164. }
  165. HANDLE
  166. APIHOOK(CreateFileW)(
  167. LPCWSTR lpFileName, // file name
  168. DWORD dwDesiredAccess, // access mode
  169. DWORD dwShareMode, // share mode
  170. LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD
  171. DWORD dwCreationDisposition, // how to create
  172. DWORD dwFlagsAndAttributes, // file attributes
  173. HANDLE hTemplateFile // handle to template file
  174. )
  175. {
  176. HANDLE hRet;
  177. LONG nHandleCount = 0;
  178. hRet = ORIGINAL_API(CreateFileW)(
  179. lpFileName,
  180. dwDesiredAccess,
  181. dwShareMode,
  182. lpSecurityAttributes,
  183. dwCreationDisposition,
  184. dwFlagsAndAttributes,
  185. hTemplateFile);
  186. if (hRet != INVALID_HANDLE_VALUE)
  187. {
  188. if (IsFileToSync(lpFileName))
  189. {
  190. g_hCachedHandles->AppendUnique(hRet);
  191. }
  192. }
  193. return hRet;
  194. }
  195. BOOL
  196. APIHOOK(CloseHandle)(HANDLE hObject)
  197. {
  198. int nIndex = g_hCachedHandles->Find(hObject);
  199. if (nIndex >= 0)
  200. {
  201. g_hCachedHandles->Remove(nIndex);
  202. SyncAllFiles();
  203. }
  204. return ORIGINAL_API(CloseHandle)(hObject);
  205. }
  206. BOOL
  207. APIHOOK(CopyFileA)(
  208. LPCSTR lpExistingFileName, // name of an existing file
  209. LPCSTR lpNewFileName, // name of new file
  210. BOOL bFailIfExists // operation if file exists
  211. )
  212. {
  213. BOOL bRet;
  214. bRet = ORIGINAL_API(CopyFileA)(
  215. lpExistingFileName,
  216. lpNewFileName,
  217. bFailIfExists);
  218. if (bRet)
  219. {
  220. if (IsFileToSync(lpNewFileName))
  221. {
  222. SyncAllFiles();
  223. }
  224. }
  225. return bRet;
  226. }
  227. BOOL
  228. APIHOOK(CopyFileW)(
  229. LPCWSTR lpExistingFileName, // name of an existing file
  230. LPCWSTR lpNewFileName, // name of new file
  231. BOOL bFailIfExists // operation if file exists
  232. )
  233. {
  234. BOOL bRet;
  235. bRet = ORIGINAL_API(CopyFileW)(
  236. lpExistingFileName,
  237. lpNewFileName,
  238. bFailIfExists);
  239. if (bRet)
  240. {
  241. if (IsFileToSync(lpNewFileName))
  242. {
  243. SyncAllFiles();
  244. }
  245. }
  246. return bRet;
  247. }
  248. BOOL
  249. APIHOOK(CopyFileExA)(
  250. LPCSTR lpExistingFileName, // name of existing file
  251. LPCSTR lpNewFileName, // name of new file
  252. LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
  253. LPVOID lpData, // callback parameter
  254. LPBOOL pbCancel, // cancel status
  255. DWORD dwCopyFlags // copy options
  256. )
  257. {
  258. BOOL bRet;
  259. bRet = ORIGINAL_API(CopyFileExA)(
  260. lpExistingFileName,
  261. lpNewFileName,
  262. lpProgressRoutine,
  263. lpData,
  264. pbCancel,
  265. dwCopyFlags);
  266. if (bRet)
  267. {
  268. if (IsFileToSync(lpNewFileName))
  269. {
  270. SyncAllFiles();
  271. }
  272. }
  273. return bRet;
  274. }
  275. BOOL
  276. APIHOOK(CopyFileExW)(
  277. LPCWSTR lpExistingFileName, // name of existing file
  278. LPCWSTR lpNewFileName, // name of new file
  279. LPPROGRESS_ROUTINE lpProgressRoutine, // callback function
  280. LPVOID lpData, // callback parameter
  281. LPBOOL pbCancel, // cancel status
  282. DWORD dwCopyFlags // copy options
  283. )
  284. {
  285. BOOL bRet;
  286. bRet = ORIGINAL_API(CopyFileExW)(
  287. lpExistingFileName,
  288. lpNewFileName,
  289. lpProgressRoutine,
  290. lpData,
  291. pbCancel,
  292. dwCopyFlags);
  293. if (bRet)
  294. {
  295. if (IsFileToSync(lpNewFileName))
  296. {
  297. SyncAllFiles();
  298. }
  299. }
  300. return bRet;
  301. }
  302. //
  303. // GetFileVersionInfoSize was added for the Madeline series.
  304. // There was a specific point at which the sync had to occur.
  305. //
  306. DWORD
  307. APIHOOK(GetFileVersionInfoSizeA)(
  308. LPSTR lptstrFilename, // file name
  309. LPDWORD lpdwHandle // set to zero
  310. )
  311. {
  312. if (IsFileToSync(lptstrFilename))
  313. {
  314. SyncAllFiles();
  315. }
  316. return ORIGINAL_API(GetFileVersionInfoSizeA)(lptstrFilename, lpdwHandle);
  317. }
  318. DWORD
  319. APIHOOK(GetFileVersionInfoSizeW)(
  320. LPWSTR lptstrFilename, // file name
  321. LPDWORD lpdwHandle // set to zero
  322. )
  323. {
  324. if (IsFileToSync(lptstrFilename))
  325. {
  326. SyncAllFiles();
  327. }
  328. return ORIGINAL_API(GetFileVersionInfoSizeW)(lptstrFilename, lpdwHandle);
  329. }
  330. BOOL
  331. ParseCommandLine()
  332. {
  333. CSTRING_TRY
  334. {
  335. g_hCachedHandles = new VectorT<HANDLE>;
  336. CString csCl(COMMAND_LINE);
  337. CStringParser csParser(csCl, L";");
  338. g_nrgFilesToSync = csParser.GetCount();
  339. g_rgFilesToSync = csParser.ReleaseArgv();
  340. // Create strings to %windir%\system and %windir%\system32
  341. g_csSystem = new CString;
  342. g_csSystem->GetWindowsDirectoryW();
  343. g_csSystem->AppendPath(L"System");
  344. g_csSystem32 = new CString;
  345. g_csSystem32->GetWindowsDirectoryW();
  346. g_csSystem32->AppendPath(L"System32");
  347. }
  348. CSTRING_CATCH
  349. {
  350. return FALSE;
  351. }
  352. return TRUE;
  353. }
  354. /*++
  355. Register hooked functions
  356. --*/
  357. BOOL
  358. NOTIFY_FUNCTION(
  359. DWORD fdwReason
  360. )
  361. {
  362. if (fdwReason == DLL_PROCESS_ATTACH)
  363. {
  364. return ParseCommandLine();
  365. }
  366. else if (fdwReason == SHIM_STATIC_DLLS_INITIALIZED)
  367. {
  368. SyncAllFiles();
  369. }
  370. else if (fdwReason == DLL_PROCESS_DETACH)
  371. {
  372. SyncAllFiles();
  373. }
  374. return TRUE;
  375. }
  376. HOOK_BEGIN
  377. CALL_NOTIFY_FUNCTION
  378. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA);
  379. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileW);
  380. APIHOOK_ENTRY(KERNEL32.DLL, CloseHandle);
  381. APIHOOK_ENTRY(KERNEL32.DLL, CopyFileA);
  382. APIHOOK_ENTRY(KERNEL32.DLL, CopyFileW);
  383. APIHOOK_ENTRY(KERNEL32.DLL, CopyFileExA);
  384. APIHOOK_ENTRY(KERNEL32.DLL, CopyFileExW);
  385. APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoSizeA);
  386. APIHOOK_ENTRY(VERSION.DLL, GetFileVersionInfoSizeW);
  387. HOOK_END
  388. IMPLEMENT_SHIM_END