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.

355 lines
9.9 KiB

  1. #include "precomp.h" // pch file
  2. #pragma hdrstop
  3. #define DECL_CRTFREE
  4. #include <crtfree.h>
  5. // deal with IShellLinkA/W uglyness...
  6. HRESULT ShellLinkSetPath(IUnknown *punk, LPCTSTR pszPath)
  7. {
  8. HRESULT hres;
  9. #ifdef UNICODE
  10. IShellLinkW *pslW;
  11. hres = punk->QueryInterface(IID_PPV_ARG(IShellLinkW, &pslW));
  12. if (SUCCEEDED(hres))
  13. {
  14. hres = pslW->SetPath(pszPath);
  15. pslW->Release();
  16. }
  17. else
  18. #endif
  19. {
  20. IShellLinkA *pslA;
  21. hres = punk->QueryInterface(IID_PPV_ARG(IShellLinkA, &pslA));
  22. if (SUCCEEDED(hres))
  23. {
  24. CHAR szPath[MAX_PATH];
  25. SHUnicodeToAnsi(pszPath, szPath, ARRAYSIZE(szPath));
  26. hres = pslA->SetPath(szPath);
  27. pslA->Release();
  28. }
  29. }
  30. return hres;
  31. }
  32. // deal with IShellLinkA/W uglyness...
  33. HRESULT ShellLinkGetPath(IUnknown *punk, LPTSTR pszPath, UINT cch)
  34. {
  35. HRESULT hres;
  36. #ifdef UNICODE
  37. IShellLinkW *pslW;
  38. hres = punk->QueryInterface(IID_PPV_ARG(IShellLinkW, &pslW));
  39. if (SUCCEEDED(hres))
  40. {
  41. hres = pslW->GetPath(pszPath, cch, NULL, SLGP_UNCPRIORITY);
  42. pslW->Release();
  43. }
  44. else
  45. #endif
  46. {
  47. IShellLinkA *pslA;
  48. hres = punk->QueryInterface(IID_PPV_ARG(IShellLinkA, &pslA));
  49. if (SUCCEEDED(hres))
  50. {
  51. CHAR szPath[MAX_PATH];
  52. hres = pslA->GetPath(szPath, ARRAYSIZE(szPath), NULL, SLGP_UNCPRIORITY);
  53. if (SUCCEEDED(hres))
  54. SHAnsiToUnicode(szPath, pszPath, cch);
  55. pslA->Release();
  56. }
  57. }
  58. return hres;
  59. }
  60. // return if we are running on NT or not?
  61. BOOL RunningOnNT()
  62. {
  63. static int s_bOnNT = -1; // -1 means uninited, 0 means no, 1 means yes
  64. if (s_bOnNT == -1)
  65. {
  66. OSVERSIONINFO osvi;
  67. osvi.dwOSVersionInfoSize = sizeof(osvi);
  68. GetVersionEx(&osvi);
  69. if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  70. s_bOnNT = 1;
  71. else
  72. s_bOnNT = 0;
  73. }
  74. return (BOOL)s_bOnNT;
  75. }
  76. // is a file a shortcut? check its attributes
  77. BOOL IsShortcut(LPCTSTR pszFile)
  78. {
  79. SHFILEINFO sfi;
  80. return SHGetFileInfo(pszFile, 0, &sfi, sizeof(sfi), SHGFI_ATTRIBUTES)
  81. && (sfi.dwAttributes & SFGAO_LINK);
  82. }
  83. // like OLE GetClassFile(), but it only works on ProgID\CLSID type registration
  84. // not real doc files or pattern matched files
  85. HRESULT CLSIDFromExtension(LPCTSTR pszExt, CLSID *pclsid)
  86. {
  87. TCHAR szProgID[80];
  88. LONG cb = SIZEOF(szProgID);
  89. if (RegQueryValue(HKEY_CLASSES_ROOT, pszExt, szProgID, &cb) == ERROR_SUCCESS)
  90. {
  91. TCHAR szCLSID[80];
  92. lstrcat(szProgID, TEXT("\\CLSID"));
  93. cb = SIZEOF(szCLSID);
  94. if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szCLSID, &cb) == ERROR_SUCCESS)
  95. {
  96. WCHAR wszCLSID[80];
  97. SHTCharToUnicode(szCLSID, wszCLSID, ARRAYSIZE(wszCLSID));
  98. return CLSIDFromString(wszCLSID, pclsid);
  99. }
  100. }
  101. return E_FAIL;
  102. }
  103. // get the target of a shortcut. this uses IShellLink which
  104. // Internet Shortcuts (.URL) and Shell Shortcuts (.LNK) support so
  105. // it should work generally
  106. BOOL GetShortcutTarget(LPCTSTR pszPath, LPTSTR pszTarget, UINT cch)
  107. {
  108. IUnknown *punk;
  109. HRESULT hres;
  110. CLSID clsid;
  111. *pszTarget = 0; // assume none
  112. if (!IsShortcut(pszPath))
  113. return FALSE;
  114. if (FAILED(CLSIDFromExtension(PathFindExtension(pszPath), &clsid)))
  115. clsid = CLSID_ShellLink; // assume it's a shell link
  116. hres = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IUnknown, &punk));
  117. if (SUCCEEDED(hres))
  118. {
  119. IPersistFile *ppf;
  120. if (SUCCEEDED(punk->QueryInterface(IID_PPV_ARG(IPersistFile, &ppf))))
  121. {
  122. WCHAR wszPath[MAX_PATH];
  123. SHTCharToUnicode(pszPath, wszPath, ARRAYSIZE(wszPath));
  124. ppf->Load(wszPath, 0);
  125. ppf->Release();
  126. }
  127. hres = ShellLinkGetPath(punk, pszTarget, cch);
  128. punk->Release();
  129. }
  130. return FALSE;
  131. }
  132. // get the pathname to a sendto folder item
  133. HRESULT GetDropTargetPath(LPTSTR pszPath, int id, LPCTSTR pszExt)
  134. {
  135. LPITEMIDLIST pidl;
  136. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_SENDTO, &pidl)))
  137. {
  138. TCHAR szFileName[128], szBase[64];
  139. SHGetPathFromIDList(pidl, pszPath);
  140. SHFree(pidl);
  141. LoadString(g_hinst, id, szBase, ARRAYSIZE(szBase));
  142. wnsprintf(szFileName, ARRAYSIZE(szFileName), TEXT("\\%s.%s"), szBase, pszExt);
  143. lstrcat(pszPath, szFileName);
  144. return S_OK;
  145. }
  146. return E_FAIL;
  147. }
  148. // do common registration
  149. #define NEVERSHOWEXT TEXT("NeverShowExt")
  150. #define SHELLEXT_DROPHANDLER TEXT("shellex\\DropHandler")
  151. void CommonRegister(HKEY hkCLSID, LPCTSTR pszCLSID, LPCTSTR pszExtension, int idFileName)
  152. {
  153. TCHAR szFile[MAX_PATH];
  154. HKEY hk;
  155. TCHAR szKey[80];
  156. RegSetValueEx(hkCLSID, NEVERSHOWEXT, 0, REG_SZ, (BYTE *)TEXT(""), SIZEOF(TCHAR));
  157. if (RegCreateKey(hkCLSID, SHELLEXT_DROPHANDLER, &hk) == ERROR_SUCCESS)
  158. {
  159. RegSetValueEx(hk, NULL, 0, REG_SZ, (LPBYTE)pszCLSID, (lstrlen(pszCLSID) + 1) * SIZEOF(TCHAR));
  160. RegCloseKey(hk);
  161. }
  162. wnsprintf(szKey, ARRAYSIZE(szKey), TEXT(".%s"), pszExtension);
  163. if (RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hk) == ERROR_SUCCESS)
  164. {
  165. TCHAR szProgID[80];
  166. wnsprintf(szProgID, ARRAYSIZE(szProgID), TEXT("CLSID\\%s"), pszCLSID);
  167. RegSetValueEx(hk, NULL, 0, REG_SZ, (LPBYTE)szProgID, (lstrlen(szProgID) + 1) * SIZEOF(TCHAR));
  168. RegCloseKey(hk);
  169. }
  170. if (SUCCEEDED(GetDropTargetPath(szFile, idFileName, pszExtension)))
  171. {
  172. HANDLE hfile = CreateFile(szFile, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  173. if (hfile != INVALID_HANDLE_VALUE)
  174. {
  175. CloseHandle(hfile);
  176. SHSetLocalizedName(szFile, L"sendmail.dll", idFileName);
  177. }
  178. }
  179. }
  180. // SHPathToAnsi creates an ANSI version of a pathname. If there is going to be a
  181. // loss when converting from Unicode, the short pathname is obtained and stored in the
  182. // destination.
  183. //
  184. // pszSrc : Source buffer containing filename (of existing file) to be converted
  185. // pszDest : Destination buffer to receive converted ANSI string.
  186. // cbDest : Size of the destination buffer, in bytes.
  187. //
  188. // returns:
  189. // TRUE, the filename was converted without change
  190. // FALSE, we had to convert to short name
  191. //
  192. BOOL SHPathToAnsi(LPCTSTR pszSrc, LPSTR pszDest, int cbDest)
  193. {
  194. #ifdef UNICODE
  195. BOOL bUsedDefaultChar = FALSE;
  196. WideCharToMultiByte(CP_ACP, 0, pszSrc, -1, pszDest, cbDest, NULL, &bUsedDefaultChar);
  197. if (bUsedDefaultChar)
  198. {
  199. TCHAR szTemp[MAX_PATH];
  200. if (GetShortPathName(pszSrc, szTemp, ARRAYSIZE(szTemp)))
  201. SHTCharToAnsi(szTemp, pszDest, cbDest);
  202. }
  203. return !bUsedDefaultChar;
  204. #else
  205. SHTCharToAnsi(pszSrc, pszDest, cbDest);
  206. return TRUE;
  207. #endif
  208. }
  209. // First undefine everything that we are intercepting as to not forward back to us...
  210. #undef SHGetSpecialFolderPath
  211. // Explicit prototype because only the A/W prototypes exist in the headers
  212. STDAPI_(BOOL) SHGetSpecialFolderPath(HWND hwnd, LPTSTR lpszPath, int nFolder, BOOL fCreate);
  213. BOOL _SHGetSpecialFolderPath(HWND hwnd, LPTSTR pszPath, int nFolder, BOOL fCreate)
  214. {
  215. BOOL fRet;
  216. if (RunningOnNT())
  217. {
  218. #ifdef UNICODE
  219. fRet = SHGetSpecialFolderPath(hwnd, pszPath, nFolder, fCreate);
  220. #else
  221. WCHAR wszPath[MAX_PATH];
  222. fRet = SHGetSpecialFolderPath(hwnd, (LPTSTR)wszPath, nFolder, fCreate);
  223. if (fRet)
  224. SHUnicodeToTChar(wszPath, pszPath, MAX_PATH);
  225. #endif
  226. }
  227. else
  228. {
  229. #ifdef UNICODE
  230. CHAR szPath[MAX_PATH];
  231. fRet = SHGetSpecialFolderPath(hwnd, (LPTSTR)szPath, nFolder, fCreate);
  232. if (fRet)
  233. SHAnsiToTChar(szPath, pszPath, MAX_PATH);
  234. #else
  235. fRet = SHGetSpecialFolderPath(hwnd, pszPath, nFolder, fCreate);
  236. #endif
  237. }
  238. return fRet;
  239. }
  240. BOOL PathYetAnotherMakeUniqueNameT(LPTSTR pszUniqueName,
  241. LPCTSTR pszPath,
  242. LPCTSTR pszShort,
  243. LPCTSTR pszFileSpec)
  244. {
  245. if (RunningOnNT())
  246. {
  247. WCHAR wszUniqueName[MAX_PATH];
  248. WCHAR wszPath[MAX_PATH];
  249. WCHAR wszShort[32];
  250. WCHAR wszFileSpec[MAX_PATH];
  251. BOOL fRet;
  252. SHTCharToUnicode(pszPath, wszPath, ARRAYSIZE(wszPath));
  253. pszPath = (LPCTSTR)wszPath; // overload the pointer to pass through...
  254. if (pszShort)
  255. {
  256. SHTCharToUnicode(pszShort, wszShort, ARRAYSIZE(wszShort));
  257. pszShort = (LPCTSTR)wszShort; // overload the pointer to pass through...
  258. }
  259. if (pszFileSpec)
  260. {
  261. SHTCharToUnicode(pszFileSpec, wszFileSpec, ARRAYSIZE(wszFileSpec));
  262. pszFileSpec = (LPCTSTR)wszFileSpec; // overload the pointer to pass through...
  263. }
  264. fRet = PathYetAnotherMakeUniqueName((LPTSTR)wszUniqueName, pszPath, pszShort, pszFileSpec);
  265. if (fRet)
  266. SHUnicodeToTChar(wszUniqueName, pszUniqueName, MAX_PATH);
  267. return fRet;
  268. }
  269. else {
  270. // win9x thunk code from runonnt.c
  271. CHAR szUniqueName[MAX_PATH];
  272. CHAR szPath[MAX_PATH];
  273. CHAR szShort[32];
  274. CHAR szFileSpec[MAX_PATH];
  275. BOOL fRet;
  276. SHTCharToAnsi(pszPath, szPath, ARRAYSIZE(szPath));
  277. pszPath = (LPCTSTR)szPath; // overload the pointer to pass through...
  278. if (pszShort)
  279. {
  280. SHTCharToAnsi(pszShort, szShort, ARRAYSIZE(szShort));
  281. pszShort = (LPCTSTR)szShort; // overload the pointer to pass through...
  282. }
  283. if (pszFileSpec)
  284. {
  285. SHTCharToAnsi(pszFileSpec, szFileSpec, ARRAYSIZE(szFileSpec));
  286. pszFileSpec = (LPCTSTR)szFileSpec; // overload the pointer to pass through...
  287. }
  288. fRet = PathYetAnotherMakeUniqueName((LPTSTR)szUniqueName, pszPath, pszShort, pszFileSpec);
  289. if (fRet)
  290. SHAnsiToTChar(szUniqueName, pszUniqueName, MAX_PATH);
  291. return fRet;
  292. }
  293. }