os.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 11k
Category:

Windows Kernel

Development Platform:

Visual C++

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