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.

314 lines
9.7 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. #include <ntimage.h>
  4. #include <ntrtl.h>
  5. static DWORD s_dwThreadIDSuspendNotify = 0;
  6. STDAPI_(BOOL) SuspendSHNotify()
  7. {
  8. DWORD dwID = GetCurrentThreadId();
  9. DWORD dwOldID = InterlockedCompareExchange(&s_dwThreadIDSuspendNotify, dwID, 0);
  10. return (dwOldID == 0);
  11. }
  12. STDAPI_(BOOL) ResumeSHNotify()
  13. {
  14. DWORD dwID = GetCurrentThreadId();
  15. DWORD dwOldID = InterlockedCompareExchange(&s_dwThreadIDSuspendNotify, 0, dwID);
  16. return (dwOldID == dwID);
  17. }
  18. STDAPI_(BOOL) SHMoveFile(LPCTSTR pszExisting, LPCTSTR pszNew, LONG lEvent)
  19. {
  20. BOOL res;
  21. // CreateDirectory fails if the directory name being created does
  22. // not have room for an 8.3 name to be tagged onto the end of it,
  23. // i.e., lstrlen(new_directory_name)+12 must be less or equal to MAX_PATH.
  24. // However, NT does not impose this restriction on MoveFile -- which the
  25. // shell sometimes uses to manipulate directory names. So, in order to
  26. // maintain consistency, we now check the length of the name before we
  27. // move the directory...
  28. if (IsDirPathTooLongForCreateDir(pszNew) &&
  29. (GetFileAttributes(pszExisting) & FILE_ATTRIBUTE_DIRECTORY))
  30. {
  31. SetLastError(ERROR_FILENAME_EXCED_RANGE);
  32. res = FALSE;
  33. }
  34. else
  35. {
  36. res = MoveFile(pszExisting, pszNew);
  37. if (FALSE == res)
  38. {
  39. // If we couldn't move the file, see if it had the readonly or system attributes.
  40. // If so, clear them, move the file, and set them back on the destination
  41. DWORD dwAttributes = GetFileAttributes(pszExisting);
  42. if (-1 != dwAttributes && (dwAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
  43. {
  44. if (SetFileAttributes(pszExisting, dwAttributes & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
  45. {
  46. res = MoveFile(pszExisting, pszNew);
  47. if (res)
  48. {
  49. SetFileAttributes(pszNew, dwAttributes);
  50. }
  51. else
  52. {
  53. SetFileAttributes(pszExisting, dwAttributes); // if move failed, return attributes.
  54. }
  55. }
  56. }
  57. }
  58. }
  59. if (res && s_dwThreadIDSuspendNotify != GetCurrentThreadId())
  60. {
  61. SHChangeNotify(lEvent, SHCNF_PATH, pszExisting, pszNew);
  62. }
  63. return res;
  64. }
  65. STDAPI_(BOOL) Win32MoveFile(LPCTSTR pszExisting, LPCTSTR pszNew, BOOL fDir)
  66. {
  67. return SHMoveFile(pszExisting, pszNew, fDir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM);
  68. }
  69. STDAPI_(BOOL) Win32DeleteFilePidl(LPCTSTR pszFileName, LPCITEMIDLIST pidlFile)
  70. {
  71. BOOL res = DeleteFile(pszFileName);
  72. if (FALSE == res)
  73. {
  74. // If we couldn't delete the file, see if it has the readonly or
  75. // system bits set. If so, clear them and try again
  76. DWORD dwAttributes = GetFileAttributes(pszFileName);
  77. if (-1 != dwAttributes && (dwAttributes & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
  78. {
  79. if (SetFileAttributes(pszFileName, dwAttributes & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)))
  80. {
  81. res = DeleteFile(pszFileName);
  82. }
  83. }
  84. }
  85. if (res && s_dwThreadIDSuspendNotify != GetCurrentThreadId())
  86. {
  87. if (pidlFile)
  88. {
  89. SHChangeNotify(SHCNE_DELETE, SHCNF_IDLIST, pidlFile, NULL);
  90. }
  91. else
  92. {
  93. SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, pszFileName, NULL);
  94. }
  95. }
  96. return res;
  97. }
  98. STDAPI_(BOOL) Win32DeleteFile(LPCTSTR pszFileName)
  99. {
  100. return Win32DeleteFilePidl(pszFileName, NULL);
  101. }
  102. STDAPI_(BOOL) Win32CreateDirectory(LPCTSTR pszPath, LPSECURITY_ATTRIBUTES lpsa)
  103. {
  104. BOOL res = CreateDirectory(pszPath, lpsa);
  105. if (res && s_dwThreadIDSuspendNotify != GetCurrentThreadId())
  106. {
  107. SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, pszPath, NULL);
  108. }
  109. return res;
  110. }
  111. //
  112. // Some filesystems (like NTFS, perchance) actually pay attention to
  113. // the readonly bit on folders. So, in order to pretend we're sort of
  114. // FAT and dumb, we clear the attribute before trying to delete the
  115. // directory.
  116. //
  117. STDAPI_(BOOL) Win32RemoveDirectory(LPCTSTR pszDir)
  118. {
  119. BOOL res = RemoveDirectory(pszDir);
  120. if (FALSE == res)
  121. {
  122. DWORD dwAttr = GetFileAttributes(pszDir);
  123. if ((-1 != dwAttr) && (dwAttr & FILE_ATTRIBUTE_READONLY))
  124. {
  125. dwAttr &= ~FILE_ATTRIBUTE_READONLY;
  126. SetFileAttributes(pszDir, dwAttr);
  127. res = RemoveDirectory(pszDir);
  128. }
  129. }
  130. if (res && s_dwThreadIDSuspendNotify != GetCurrentThreadId())
  131. {
  132. SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, pszDir, NULL);
  133. }
  134. return res;
  135. }
  136. STDAPI_(HANDLE) Win32CreateFile(LPCTSTR pszFileName, DWORD dwAttrib)
  137. {
  138. HANDLE hFile = CreateFile(pszFileName,
  139. GENERIC_READ | GENERIC_WRITE,
  140. FILE_SHARE_READ | FILE_SHARE_WRITE,
  141. NULL,
  142. CREATE_ALWAYS,
  143. dwAttrib & FILE_ATTRIBUTE_VALID_FLAGS,
  144. NULL);
  145. if ((INVALID_HANDLE_VALUE != hFile) && (s_dwThreadIDSuspendNotify != GetCurrentThreadId()))
  146. {
  147. SHChangeNotify(SHCNE_CREATE, SHCNF_PATH, pszFileName, NULL);
  148. }
  149. return hFile;
  150. }
  151. STDAPI_(BOOL) CreateWriteCloseFile(HWND hwnd, LPCTSTR pszFile, void *pData, DWORD cbData)
  152. {
  153. BOOL bRet;
  154. HANDLE hfile = Win32CreateFile(pszFile, 0);
  155. if (hfile != INVALID_HANDLE_VALUE)
  156. {
  157. if (cbData)
  158. {
  159. DWORD dwBytesWritten;
  160. WriteFile(hfile, pData, cbData, &dwBytesWritten, 0);
  161. }
  162. CloseHandle(hfile);
  163. bRet = TRUE;
  164. }
  165. else
  166. {
  167. TCHAR szPath[MAX_PATH];
  168. // ok to truncate (displayed in error message only)
  169. StringCchCopy(szPath, ARRAYSIZE(szPath), pszFile);
  170. PathRemoveExtension(szPath);
  171. SHSysErrorMessageBox(hwnd, NULL, IDS_CANNOTCREATEFILE,
  172. GetLastError(), PathFindFileName(szPath),
  173. MB_OK | MB_ICONEXCLAMATION);
  174. bRet = FALSE;
  175. }
  176. return bRet;
  177. }
  178. #undef SHGetProcessDword
  179. STDAPI_(DWORD) SHGetProcessDword(DWORD idProcess, LONG iIndex)
  180. {
  181. return 0;
  182. }
  183. STDAPI_(BOOL) SHSetShellWindowEx(HWND hwnd, HWND hwndChild)
  184. {
  185. return SetShellWindowEx(hwnd, hwndChild);
  186. }
  187. #define ISEXETSAWARE_MAX_IMAGESIZE (4 * 1024) // allocate at most a 4k block to hold the image header (eg 1 page on x86)
  188. //
  189. // this is a function that takes a full path to an executable and returns whether or not
  190. // the exe has the TS_AWARE bit set in the image header
  191. //
  192. STDAPI_(BOOL) IsExeTSAware(LPCTSTR pszExe)
  193. {
  194. BOOL bRet = FALSE;
  195. HANDLE hFile = CreateFile(pszExe,
  196. GENERIC_READ,
  197. FILE_SHARE_READ | FILE_SHARE_WRITE,
  198. NULL,
  199. OPEN_EXISTING,
  200. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  201. NULL);
  202. if (hFile != INVALID_HANDLE_VALUE)
  203. {
  204. DWORD cbImageSize = GetFileSize(hFile, NULL);
  205. LPBYTE pBuffer;
  206. if (cbImageSize > ISEXETSAWARE_MAX_IMAGESIZE)
  207. {
  208. // 4k should be enough to get the image header for everything...
  209. cbImageSize = ISEXETSAWARE_MAX_IMAGESIZE;
  210. }
  211. pBuffer = LocalAlloc(LPTR, cbImageSize);
  212. if (pBuffer)
  213. {
  214. HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, cbImageSize, NULL);
  215. if (hMap)
  216. {
  217. // map the first 4k of the file in
  218. LPBYTE pFileMapping = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, cbImageSize);
  219. if (pFileMapping)
  220. {
  221. _try
  222. {
  223. memcpy(pBuffer, pFileMapping, cbImageSize);
  224. }
  225. _except(UnhandledExceptionFilter(GetExceptionInformation()))
  226. {
  227. // We hit an exception while copying! doh!
  228. LocalFree(pBuffer);
  229. pBuffer = NULL;
  230. }
  231. UnmapViewOfFile(pFileMapping);
  232. }
  233. else
  234. {
  235. LocalFree(pBuffer);
  236. pBuffer = NULL;
  237. }
  238. CloseHandle(hMap);
  239. }
  240. else
  241. {
  242. LocalFree(pBuffer);
  243. pBuffer = NULL;
  244. }
  245. if (pBuffer)
  246. {
  247. PIMAGE_NT_HEADERS pImageNTHeader;
  248. // NOTE: this should work ok for 64-bit images too, since both the IMAGE_NT_HEADERS and the IMAGE_NT_HEADERS64
  249. // structs have a ->Signature and ->OptionalHeader that is identical up to the DllCharacteristics offset.
  250. pImageNTHeader = RtlImageNtHeader(pBuffer);
  251. if (pImageNTHeader)
  252. {
  253. if (pImageNTHeader->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE)
  254. {
  255. // yes, this is a TSAWARE executable!
  256. bRet = TRUE;
  257. }
  258. }
  259. LocalFree(pBuffer);
  260. }
  261. }
  262. CloseHandle(hFile);
  263. }
  264. return bRet;
  265. }