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.

273 lines
7.3 KiB

  1. /*++
  2. Copyright (c) 2000-2002 Microsoft Corporation
  3. Module Name:
  4. CorrectVerInstallFile.cpp
  5. Abstract:
  6. In Windows XP, due to a modification in the caching between MoveFile and
  7. DeleteFile API's, when the VerInstallFileW API was called, the SHORT
  8. filename gets SET instead of the long filename.
  9. This SHIM corrects this problem which effects the installation of a few
  10. apps when the older version is still present.
  11. Notes:
  12. This can be a layer shim. This is a general purpose shim.
  13. History:
  14. 04/05/2001 prashkud Created
  15. 02/28/2002 mnikkel Added check for nulls passed in for temporary file name
  16. buffer and size. This was not checked on win9x but is
  17. immediately used on XP.
  18. --*/
  19. #include "precomp.h"
  20. IMPLEMENT_SHIM_BEGIN(CorrectVerInstallFile)
  21. #include "ShimHookMacro.h"
  22. APIHOOK_ENUM_BEGIN
  23. APIHOOK_ENUM_ENTRY(VerInstallFileW)
  24. APIHOOK_ENUM_ENTRY(VerInstallFileA)
  25. APIHOOK_ENUM_END
  26. /*++
  27. GetTitle takes the app path and returns just the EXE name.
  28. --*/
  29. VOID
  30. SplitTitleAndPath(CString& csAppName, CString& csAppTitle)
  31. {
  32. //
  33. // Go to the first '\' from the end.
  34. // The return value is the number of characters
  35. // from the beginning of the string starting at
  36. // index 0.
  37. //
  38. int len = csAppName.ReverseFind(L'\\');
  39. if (len)
  40. {
  41. csAppTitle.Delete(0, len+1);
  42. }
  43. int DirLen = csAppName.GetLength() - len;
  44. csAppName.Delete(len, DirLen);
  45. }
  46. DWORD
  47. APIHOOK(VerInstallFileA)(
  48. DWORD uFlags,
  49. LPSTR szSrcFileName,
  50. LPSTR szDestFileName,
  51. LPSTR szSrcDir,
  52. LPSTR szDestDir,
  53. LPSTR szCurDir,
  54. LPSTR szTmpFile,
  55. PUINT lpuTmpFileLen
  56. )
  57. {
  58. CHAR DummyBuffer[MAX_PATH];
  59. UINT DummySize = MAX_PATH;
  60. DWORD dwRet = 0;
  61. // check for a null szTmpFile or a null lpuTmpFileLen.
  62. if (szTmpFile == NULL)
  63. {
  64. szTmpFile = DummyBuffer;
  65. DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFile.");
  66. }
  67. if (lpuTmpFileLen == NULL)
  68. {
  69. lpuTmpFileLen = &DummySize;
  70. DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFileLen.");
  71. }
  72. CSTRING_TRY
  73. {
  74. CString csDestFilePath(szDestDir);
  75. CString csDestFileName(szDestFileName);
  76. csDestFilePath.AppendPath(csDestFileName);
  77. //
  78. // Now csDestFileName possibly contains the SHORT path name
  79. // Convert it into long pathname
  80. //
  81. DWORD dwAttr = GetFileAttributesW(csDestFilePath.Get());
  82. if ((dwAttr != 0xFFFFFFFF) &&
  83. (dwAttr != FILE_ATTRIBUTE_DIRECTORY))
  84. {
  85. //
  86. // This file exists in the current destination directory.
  87. // This API had problems replacing it if the filename
  88. // is a SHORT name. Convert it into LONG name.
  89. //
  90. if (csDestFilePath.GetLongPathNameW())
  91. {
  92. DPFN( eDbgLevelWarning, "Short Path \
  93. converted to Long Path = %S",
  94. csDestFilePath.Get());
  95. csDestFileName = csDestFilePath;
  96. SplitTitleAndPath(csDestFilePath,csDestFileName);
  97. dwRet= ORIGINAL_API(VerInstallFileA)(uFlags,szSrcFileName,
  98. (char*)csDestFileName.GetAnsi(), szSrcDir,
  99. (char*)csDestFilePath.GetAnsi(), szCurDir,
  100. szTmpFile,lpuTmpFileLen);
  101. // If using the dummy buffer then they had a null temp buffer
  102. // Set the buffer too small flag.
  103. if (szTmpFile == DummyBuffer)
  104. {
  105. dwRet &= VIF_BUFFTOOSMALL;
  106. }
  107. return dwRet;
  108. }
  109. }
  110. }
  111. CSTRING_CATCH
  112. {
  113. DPFN(eDbgLevelError,
  114. "Exception raised ! Calling Original API");
  115. }
  116. dwRet = ORIGINAL_API(VerInstallFileA)(uFlags,szSrcFileName,szDestFileName,
  117. szSrcDir,szDestDir,szCurDir,szTmpFile,lpuTmpFileLen);
  118. // If using the dummy buffer then they had a null temp buffer
  119. // Set the buffer too small flag.
  120. if (szTmpFile == DummyBuffer)
  121. {
  122. dwRet &= VIF_BUFFTOOSMALL;
  123. }
  124. return dwRet;
  125. }
  126. /*++
  127. Modify the Short filename to its corresponding long filename.
  128. --*/
  129. DWORD
  130. APIHOOK(VerInstallFileW)(
  131. DWORD uFlags,
  132. LPWSTR szSrcFileName,
  133. LPWSTR szDestFileName,
  134. LPWSTR szSrcDir,
  135. LPWSTR szDestDir,
  136. LPWSTR szCurDir,
  137. LPWSTR szTmpFile,
  138. PUINT lpuTmpFileLen
  139. )
  140. {
  141. WCHAR DummyBuffer[MAX_PATH];
  142. UINT DummySize = MAX_PATH;
  143. DWORD dwRet = 0;
  144. // check for a null szTmpFile or a null lpuTmpFileLen.
  145. if (szTmpFile == NULL)
  146. {
  147. szTmpFile = DummyBuffer;
  148. DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFile.");
  149. }
  150. if (lpuTmpFileLen == NULL)
  151. {
  152. lpuTmpFileLen = &DummySize;
  153. DPFN(eDbgLevelInfo, "VerInstallFileA using dummy TmpFileLen.");
  154. }
  155. CSTRING_TRY
  156. {
  157. CString csDestFilePath(szDestDir);
  158. csDestFilePath.AppendPath(szDestFileName);
  159. //
  160. // Now csDestFileName possibly contains the SHORT path name
  161. // Convert it into long pathname
  162. //
  163. DWORD dwAttr = GetFileAttributesW(csDestFilePath.Get());
  164. if ((dwAttr != 0xFFFFFFFF) &&
  165. (dwAttr != FILE_ATTRIBUTE_DIRECTORY))
  166. {
  167. //
  168. // This file exists in the current destination directory.
  169. // This API had problems replacing it if the filename
  170. // is a SHORT name. Convert it into LONG name.
  171. //
  172. if (csDestFilePath.GetLongPathNameW())
  173. {
  174. DPFN( eDbgLevelWarning, "Short Path \
  175. converted to Long Path = %S",
  176. csDestFilePath.Get());
  177. CString csDestFileName(csDestFilePath);
  178. SplitTitleAndPath(csDestFilePath,csDestFileName);
  179. dwRet = ORIGINAL_API(VerInstallFileW)(uFlags,szSrcFileName,
  180. (WCHAR*)csDestFileName.Get(), szSrcDir,
  181. (WCHAR*)csDestFilePath.Get(), szCurDir,
  182. szTmpFile,lpuTmpFileLen);
  183. // If using the dummy buffer then they had a null temp buffer
  184. // Set the buffer too small flag.
  185. if (szTmpFile == DummyBuffer)
  186. {
  187. dwRet &= VIF_BUFFTOOSMALL;
  188. }
  189. return dwRet;
  190. }
  191. }
  192. }
  193. CSTRING_CATCH
  194. {
  195. DPFN( eDbgLevelError,
  196. "Exception raised ! Calling Original API");
  197. }
  198. dwRet = ORIGINAL_API(VerInstallFileW)(uFlags,szSrcFileName,szDestFileName,
  199. szSrcDir,szDestDir,szCurDir,szTmpFile,lpuTmpFileLen);
  200. // If using the dummy buffer then they had a null temp buffer
  201. // Set the buffer too small flag.
  202. if (szTmpFile == DummyBuffer)
  203. {
  204. dwRet &= VIF_BUFFTOOSMALL;
  205. }
  206. return dwRet;
  207. }
  208. /*++
  209. Register hooked functions
  210. --*/
  211. HOOK_BEGIN
  212. APIHOOK_ENTRY(VERSION.DLL, VerInstallFileW)
  213. APIHOOK_ENTRY(VERSION.DLL, VerInstallFileA)
  214. HOOK_END
  215. IMPLEMENT_SHIM_END