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.

332 lines
8.9 KiB

  1. #include "precomp.hxx"
  2. #pragma hdrstop
  3. #include <winnlsp.h> // NORM_STOP_ON_NULL
  4. #include "resource.h"
  5. #include "timewarp.h"
  6. #include "util.h"
  7. DWORD FormatString(LPWSTR *ppszResult, HINSTANCE hInstance, LPCWSTR pszFormat, ...)
  8. {
  9. DWORD dwResult;
  10. va_list args;
  11. LPWSTR pszFormatAlloc = NULL;
  12. if (IS_INTRESOURCE(pszFormat))
  13. {
  14. if (LoadStringAlloc(&pszFormatAlloc, hInstance, PtrToUlong(pszFormat)))
  15. {
  16. pszFormat = pszFormatAlloc;
  17. }
  18. else
  19. {
  20. return 0;
  21. }
  22. }
  23. va_start(args, pszFormat);
  24. dwResult = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  25. pszFormat,
  26. 0,
  27. 0,
  28. (LPWSTR)ppszResult,
  29. 1,
  30. &args);
  31. va_end(args);
  32. LocalFree(pszFormatAlloc);
  33. return dwResult;
  34. }
  35. HRESULT FormatFriendlyDateName(LPWSTR *ppszResult, LPCWSTR pszName, const FILETIME UNALIGNED *pft, DWORD dwDateFlags)
  36. {
  37. WCHAR szDate[MAX_PATH];
  38. SHFormatDateTime(pft, &dwDateFlags, szDate, ARRAYSIZE(szDate));
  39. if (!FormatString(ppszResult, g_hInstance, MAKEINTRESOURCE(IDS_FOLDER_TITLE_FORMAT), pszName, szDate))
  40. {
  41. DWORD dwErr = GetLastError();
  42. return HRESULT_FROM_WIN32(dwErr);
  43. }
  44. return S_OK;
  45. }
  46. void EliminateGMTPathSegment(LPWSTR pszPath)
  47. {
  48. LPWSTR pszGMT = wcsstr(pszPath, SNAPSHOT_MARKER);
  49. if (pszGMT)
  50. {
  51. ASSERT(pszGMT >= pszPath && pszGMT < (pszPath + lstrlenW(pszPath)));
  52. // It's tempting to just say "pszGMT + SNAPSHOT_NAME_LENGTH" here, but
  53. // we might miss an intervening '\0' on a malformed path.
  54. LPWSTR pszSeparator = wcschr(pszGMT, L'\\');
  55. if (pszSeparator)
  56. {
  57. ASSERT(pszSeparator == pszGMT + SNAPSHOT_NAME_LENGTH);
  58. ASSERT(pszSeparator < (pszGMT + lstrlenW(pszGMT)));
  59. pszSeparator++; // skip '\\'
  60. MoveMemory(pszGMT, pszSeparator, (lstrlenW(pszSeparator)+1)*sizeof(WCHAR));
  61. }
  62. else
  63. {
  64. // Truncate here
  65. *pszGMT = L'\0';
  66. // Remove the previous separator if we can
  67. PathRemoveBackslashW(pszPath);
  68. }
  69. }
  70. }
  71. void EliminatePathPrefix(LPWSTR pszPath)
  72. {
  73. // Note that sometimes the "\\?\" is not at the beginning of the
  74. // path. See CTimeWarpProp::_OnView in twprop.cpp.
  75. LPWSTR pszPrefix = wcsstr(pszPath, L"\\\\?\\");
  76. if (pszPrefix)
  77. {
  78. LPWSTR pszDest;
  79. LPWSTR pszSrc;
  80. ASSERT(pszPrefix >= pszPath && pszPrefix < (pszPath + lstrlenW(pszPath)));
  81. if (CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT,
  82. SORT_STRINGSORT | NORM_IGNORECASE | NORM_STOP_ON_NULL,
  83. pszPrefix+4, 4,
  84. L"UNC\\", 4))
  85. {
  86. // UNC case: preserve the 2 leading backslashes
  87. pszDest = pszPrefix + 2;
  88. pszSrc = pszPrefix + 8;
  89. }
  90. else
  91. {
  92. pszDest = pszPrefix;
  93. pszSrc = pszPrefix + 4;
  94. }
  95. ASSERT(pszDest >= pszPath && pszSrc > pszDest && pszSrc <= (pszPath + lstrlenW(pszPath)));
  96. MoveMemory(pszDest, pszSrc, (lstrlenW(pszSrc)+1)*sizeof(WCHAR));
  97. }
  98. }
  99. HRESULT GetFSIDListFromTimeWarpPath(PIDLIST_ABSOLUTE *ppidlTarget, LPCWSTR pszPath, DWORD dwFileAttributes)
  100. {
  101. HRESULT hr;
  102. LPWSTR pszDup;
  103. hr = SHStrDup(pszPath, &pszDup);
  104. if (SUCCEEDED(hr))
  105. {
  106. // Note that SHSimpleIDListFromPath (which is exported from shell32)
  107. // is not good enough here. It always uses 0 for attributes, but
  108. // we usually need FILE_ATTRIBUTE_DIRECTORY here.
  109. EliminateGMTPathSegment(pszDup);
  110. hr = SimpleIDListFromAttributes(pszDup, dwFileAttributes, ppidlTarget);
  111. LocalFree(pszDup);
  112. }
  113. return hr;
  114. }
  115. class CFileSysBindData : public IFileSystemBindData
  116. {
  117. public:
  118. CFileSysBindData();
  119. // *** IUnknown methods ***
  120. STDMETHODIMP QueryInterface(REFIID riid, void **ppvObj);
  121. STDMETHODIMP_(ULONG) AddRef(void);
  122. STDMETHODIMP_(ULONG) Release(void);
  123. // IFileSystemBindData
  124. STDMETHODIMP SetFindData(const WIN32_FIND_DATAW *pfd);
  125. STDMETHODIMP GetFindData(WIN32_FIND_DATAW *pfd);
  126. private:
  127. ~CFileSysBindData();
  128. LONG _cRef;
  129. WIN32_FIND_DATAW _fd;
  130. };
  131. CFileSysBindData::CFileSysBindData() : _cRef(1)
  132. {
  133. ZeroMemory(&_fd, sizeof(_fd));
  134. }
  135. CFileSysBindData::~CFileSysBindData()
  136. {
  137. }
  138. HRESULT CFileSysBindData::QueryInterface(REFIID riid, void **ppv)
  139. {
  140. static const QITAB qit[] = {
  141. QITABENT(CFileSysBindData, IFileSystemBindData), // IID_IFileSystemBindData
  142. { 0 },
  143. };
  144. return QISearch(this, qit, riid, ppv);
  145. }
  146. STDMETHODIMP_(ULONG) CFileSysBindData::AddRef(void)
  147. {
  148. return InterlockedIncrement(&_cRef);
  149. }
  150. STDMETHODIMP_(ULONG) CFileSysBindData::Release()
  151. {
  152. ASSERT( 0 != _cRef );
  153. ULONG cRef = InterlockedDecrement(&_cRef);
  154. if ( 0 == cRef )
  155. {
  156. delete this;
  157. }
  158. return cRef;
  159. }
  160. HRESULT CFileSysBindData::SetFindData(const WIN32_FIND_DATAW *pfd)
  161. {
  162. _fd = *pfd;
  163. return S_OK;
  164. }
  165. HRESULT CFileSysBindData::GetFindData(WIN32_FIND_DATAW *pfd)
  166. {
  167. *pfd = _fd;
  168. return S_OK;
  169. }
  170. STDAPI SHCreateFileSysBindCtx(const WIN32_FIND_DATAW *pfd, IBindCtx **ppbc)
  171. {
  172. HRESULT hres;
  173. IFileSystemBindData *pfsbd = new CFileSysBindData();
  174. if (pfsbd)
  175. {
  176. if (pfd)
  177. {
  178. pfsbd->SetFindData(pfd);
  179. }
  180. hres = CreateBindCtx(0, ppbc);
  181. if (SUCCEEDED(hres))
  182. {
  183. BIND_OPTS bo = {sizeof(bo)}; // Requires size filled in.
  184. bo.grfMode = STGM_CREATE;
  185. (*ppbc)->SetBindOptions(&bo);
  186. (*ppbc)->RegisterObjectParam(STR_FILE_SYS_BIND_DATA, pfsbd);
  187. }
  188. pfsbd->Release();
  189. }
  190. else
  191. {
  192. *ppbc = NULL;
  193. hres = E_OUTOFMEMORY;
  194. }
  195. return hres;
  196. }
  197. STDAPI SHSimpleIDListFromFindData(LPCWSTR pszPath, const WIN32_FIND_DATAW *pfd, PIDLIST_ABSOLUTE *ppidl)
  198. {
  199. *ppidl = NULL;
  200. IBindCtx *pbc;
  201. HRESULT hr = SHCreateFileSysBindCtx(pfd, &pbc);
  202. if (SUCCEEDED(hr))
  203. {
  204. hr = SHParseDisplayName(pszPath, pbc, ppidl, 0, NULL);
  205. pbc->Release();
  206. }
  207. return hr;
  208. }
  209. STDAPI SimpleIDListFromAttributes(LPCWSTR pszPath, DWORD dwAttributes, PIDLIST_ABSOLUTE *ppidl)
  210. {
  211. WIN32_FIND_DATAW fd = {0};
  212. fd.dwFileAttributes = dwAttributes;
  213. // SHCreateFSIDList(pszPath, &fd, ppidl);
  214. return SHSimpleIDListFromFindData(pszPath, &fd, ppidl);
  215. }
  216. //*************************************************************
  217. //
  218. // SizeofStringResource
  219. //
  220. // Purpose: Find the length (in chars) of a string resource
  221. //
  222. // Parameters: HINSTANCE hInstance - module containing the string
  223. // UINT idStr - ID of string
  224. //
  225. //
  226. // Return: UINT - # of chars in string, not including NULL
  227. //
  228. // Notes: Based on code from user32.
  229. //
  230. //*************************************************************
  231. UINT
  232. SizeofStringResource(HINSTANCE hInstance, UINT idStr)
  233. {
  234. UINT cch = 0;
  235. HRSRC hRes = FindResource(hInstance, (LPTSTR)((LONG_PTR)(((USHORT)idStr >> 4) + 1)), RT_STRING);
  236. if (NULL != hRes)
  237. {
  238. HGLOBAL hStringSeg = LoadResource(hInstance, hRes);
  239. if (NULL != hStringSeg)
  240. {
  241. LPWSTR psz = (LPWSTR)LockResource(hStringSeg);
  242. if (NULL != psz)
  243. {
  244. idStr &= 0x0F;
  245. while(true)
  246. {
  247. cch = *psz++;
  248. if (idStr-- == 0)
  249. break;
  250. psz += cch;
  251. }
  252. }
  253. }
  254. }
  255. return cch;
  256. }
  257. //*************************************************************
  258. //
  259. // LoadStringAlloc
  260. //
  261. // Purpose: Loads a string resource into an alloc'd buffer
  262. //
  263. // Parameters: ppszResult - string resource returned here
  264. // hInstance - module to load string from
  265. // idStr - string resource ID
  266. //
  267. // Return: same as LoadString
  268. //
  269. // Notes: On successful return, the caller must
  270. // LocalFree *ppszResult
  271. //
  272. //*************************************************************
  273. int
  274. LoadStringAlloc(LPWSTR *ppszResult, HINSTANCE hInstance, UINT idStr)
  275. {
  276. int nResult = 0;
  277. UINT cch = SizeofStringResource(hInstance, idStr);
  278. if (cch)
  279. {
  280. cch++; // for NULL
  281. *ppszResult = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  282. if (*ppszResult)
  283. nResult = LoadString(hInstance, idStr, *ppszResult, cch);
  284. }
  285. return nResult;
  286. }