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.

453 lines
13 KiB

  1. //
  2. // Mime stuff used by shell32/shdocvw/shdoc401
  3. //
  4. #include "priv.h"
  5. #define TF_MIME 0
  6. /*----------------------------------------------------------
  7. Purpose: Generates the HKEY_CLASSES_ROOT subkey for a MIME
  8. type
  9. Returns:
  10. Cond: --
  11. */
  12. STDAPI_(BOOL) GetMIMETypeSubKeyA(LPCSTR pcszMIMEType, LPSTR pszSubKeyBuf, UINT cchBuf)
  13. {
  14. BOOL bResult;
  15. bResult = ((UINT)lstrlenA(TEXT("MIME\\Database\\Content Type\\%s")) +
  16. (UINT)lstrlenA(pcszMIMEType) < cchBuf);
  17. if (bResult)
  18. EVAL((UINT)wsprintfA(pszSubKeyBuf, TEXT("MIME\\Database\\Content Type\\%s"),
  19. pcszMIMEType) < cchBuf);
  20. else
  21. {
  22. if (cchBuf > 0)
  23. *pszSubKeyBuf = '\0';
  24. TraceMsg(TF_WARNING, "GetMIMETypeSubKey(): Given sub key buffer of length %u is too short to hold sub key for MIME type %hs.",
  25. cchBuf, pcszMIMEType);
  26. }
  27. ASSERT(! cchBuf ||
  28. (IS_VALID_STRING_PTRA(pszSubKeyBuf, -1) &&
  29. (UINT)lstrlenA(pszSubKeyBuf) < cchBuf));
  30. ASSERT(bResult ||
  31. ! cchBuf ||
  32. ! *pszSubKeyBuf);
  33. return(bResult);
  34. }
  35. STDAPI_(BOOL) GetMIMETypeSubKeyW(LPCWSTR pszMIMEType, LPWSTR pszBuf, UINT cchBuf)
  36. {
  37. BOOL bRet;
  38. char szMIMEType[MAX_PATH];
  39. char sz[MAX_PATH];
  40. ASSERT(IS_VALID_STRING_PTRW(pszMIMEType, -1));
  41. WideCharToMultiByte(CP_ACP, 0, pszMIMEType, -1, szMIMEType, SIZECHARS(szMIMEType), NULL, NULL);
  42. bRet = GetMIMETypeSubKeyA(szMIMEType, sz, SIZECHARS(sz));
  43. if (bRet)
  44. {
  45. ASSERT(cchBuf <= SIZECHARS(sz));
  46. MultiByteToWideChar(CP_ACP, 0, sz, -1, pszBuf, cchBuf);
  47. }
  48. return bRet;
  49. }
  50. /*
  51. ** RegisterExtensionForMIMEType()
  52. **
  53. ** Under HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type, add
  54. ** Content Type = mime/type and Extension = .ext.
  55. **
  56. */
  57. STDAPI_(BOOL) RegisterExtensionForMIMETypeA(LPCSTR pcszExtension, LPCSTR pcszMIMEContentType)
  58. {
  59. BOOL bResult;
  60. CHAR szMIMEContentTypeSubKey[MAX_PATH];
  61. ASSERT(IS_VALID_STRING_PTRA(pcszExtension, -1));
  62. ASSERT(IS_VALID_STRING_PTRA(pcszMIMEContentType, -1));
  63. ASSERT(IsValidExtensionA(pcszExtension));
  64. bResult = GetMIMETypeSubKeyA(pcszMIMEContentType, szMIMEContentTypeSubKey,
  65. SIZECHARS(szMIMEContentTypeSubKey));
  66. if (bResult)
  67. {
  68. /* (+ 1) for null terminator. */
  69. bResult = (NO_ERROR == SHSetValueA(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
  70. "Extension", REG_SZ, pcszExtension,
  71. CbFromCchA(lstrlenA(pcszExtension) + 1)));
  72. }
  73. return(bResult);
  74. }
  75. STDAPI_(BOOL) RegisterExtensionForMIMETypeW(LPCWSTR pcszExtension, LPCWSTR pcszMIMEContentType)
  76. {
  77. BOOL bResult;
  78. WCHAR szMIMEContentTypeSubKey[MAX_PATH];
  79. ASSERT(IS_VALID_STRING_PTRW(pcszExtension, -1));
  80. ASSERT(IS_VALID_STRING_PTRW(pcszMIMEContentType, -1));
  81. ASSERT(IsValidExtensionW(pcszExtension));
  82. bResult = GetMIMETypeSubKeyW(pcszMIMEContentType, szMIMEContentTypeSubKey,
  83. SIZECHARS(szMIMEContentTypeSubKey));
  84. if (bResult)
  85. {
  86. /* (+ 1) for null terminator. */
  87. bResult = (NO_ERROR == SHSetValueW(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
  88. TEXTW("Extension"), REG_SZ, pcszExtension,
  89. (lstrlenW(pcszExtension) + 1)*sizeof(WCHAR)));
  90. }
  91. return(bResult);
  92. }
  93. /*
  94. ** UnregisterExtensionForMIMEType()
  95. **
  96. ** Deletes Extension under
  97. ** HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type. If no other values
  98. ** or sub keys are left, deletes
  99. ** HKEY_CLASSES_ROOT\MIME\Database\Content Type\mime/type.
  100. **
  101. ** Side Effects: May also delete MIME key.
  102. */
  103. STDAPI_(BOOL) UnregisterExtensionForMIMETypeA(LPCSTR pcszMIMEContentType)
  104. {
  105. BOOL bResult;
  106. CHAR szMIMEContentTypeSubKey[MAX_PATH];
  107. ASSERT(IS_VALID_STRING_PTRA(pcszMIMEContentType, -1));
  108. bResult = (GetMIMETypeSubKeyA(pcszMIMEContentType, szMIMEContentTypeSubKey,
  109. SIZECHARS(szMIMEContentTypeSubKey)) &&
  110. NO_ERROR == SHDeleteValueA(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
  111. "Extension") &&
  112. NO_ERROR == SHDeleteEmptyKeyA(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey));
  113. return(bResult);
  114. }
  115. STDAPI_(BOOL) UnregisterExtensionForMIMETypeW(LPCWSTR pcszMIMEContentType)
  116. {
  117. BOOL bResult;
  118. WCHAR szMIMEContentTypeSubKey[MAX_PATH];
  119. ASSERT(IS_VALID_STRING_PTRW(pcszMIMEContentType, -1));
  120. bResult = (GetMIMETypeSubKeyW(pcszMIMEContentType, szMIMEContentTypeSubKey,
  121. SIZECHARS(szMIMEContentTypeSubKey)) &&
  122. NO_ERROR == SHDeleteValueW(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey,
  123. TEXTW("Extension")) &&
  124. NO_ERROR == SHDeleteEmptyKeyW(HKEY_CLASSES_ROOT, szMIMEContentTypeSubKey));
  125. return(bResult);
  126. }
  127. /*
  128. ** UnregisterMIMETypeForExtension()
  129. **
  130. ** Deletes Content Type under HKEY_CLASSES_ROOT\.ext.
  131. **
  132. ** Side Effects: none
  133. */
  134. STDAPI_(BOOL) UnregisterMIMETypeForExtensionA(LPCSTR pcszExtension)
  135. {
  136. ASSERT(IS_VALID_STRING_PTRA(pcszExtension, -1));
  137. ASSERT(IsValidExtensionA(pcszExtension));
  138. return NO_ERROR == SHDeleteValueA(HKEY_CLASSES_ROOT, pcszExtension, "Content Type");
  139. }
  140. STDAPI_(BOOL) UnregisterMIMETypeForExtensionW(LPCWSTR pcszExtension)
  141. {
  142. ASSERT(IS_VALID_STRING_PTRW(pcszExtension, -1));
  143. ASSERT(IsValidExtensionW(pcszExtension));
  144. return NO_ERROR == SHDeleteValueW(HKEY_CLASSES_ROOT, pcszExtension, TEXTW("Content Type"));
  145. }
  146. /*
  147. ** RegisterMIMETypeForExtension()
  148. **
  149. ** Under HKEY_CLASSES_ROOT\.ext, add Content Type = mime/type.
  150. **
  151. ** Arguments:
  152. **
  153. ** Returns:
  154. **
  155. ** Side Effects: none
  156. */
  157. STDAPI_(BOOL) RegisterMIMETypeForExtensionA(LPCSTR pcszExtension, LPCSTR pcszMIMEContentType)
  158. {
  159. ASSERT(IS_VALID_STRING_PTRA(pcszExtension, -1));
  160. ASSERT(IS_VALID_STRING_PTRA(pcszMIMEContentType, -1));
  161. ASSERT(IsValidExtensionA(pcszExtension));
  162. /* (+ 1) for null terminator. */
  163. return NO_ERROR == SHSetValueA(HKEY_CLASSES_ROOT, pcszExtension, "Content Type",
  164. REG_SZ, pcszMIMEContentType,
  165. CbFromCchA(lstrlenA(pcszMIMEContentType) + 1));
  166. }
  167. STDAPI_(BOOL) RegisterMIMETypeForExtensionW(LPCWSTR pcszExtension, LPCWSTR pcszMIMEContentType)
  168. {
  169. ASSERT(IS_VALID_STRING_PTRW(pcszExtension, -1));
  170. ASSERT(IS_VALID_STRING_PTRW(pcszMIMEContentType, -1));
  171. ASSERT(IsValidExtensionW(pcszExtension));
  172. /* (+ 1) for null terminator. */
  173. return NO_ERROR == SHSetValueW(HKEY_CLASSES_ROOT, pcszExtension, TEXTW("Content Type"),
  174. REG_SZ, pcszMIMEContentType,
  175. (lstrlenW(pcszMIMEContentType) + 1) * sizeof(WCHAR));
  176. }
  177. /*
  178. ** GetMIMEValue()
  179. **
  180. ** Retrieves the data for a value of a MIME type.
  181. **
  182. ** Arguments:
  183. **
  184. ** Returns:
  185. **
  186. ** Side Effects: none
  187. */
  188. STDAPI_(BOOL) GetMIMEValueA(LPCSTR pcszMIMEType, LPCSTR pcszValue,
  189. PDWORD pdwValueType, PBYTE pbyteValueBuf,
  190. PDWORD pdwcbValueBufLen)
  191. {
  192. BOOL bResult;
  193. CHAR szMIMETypeSubKey[MAX_PATH];
  194. ASSERT(IS_VALID_STRING_PTRA(pcszMIMEType, -1));
  195. ASSERT(! pcszValue ||
  196. IS_VALID_STRING_PTRA(pcszValue, -1));
  197. ASSERT(IS_VALID_WRITE_PTR(pdwValueType, DWORD));
  198. ASSERT(IS_VALID_WRITE_BUFFER(pbyteValueBuf, BYTE, *pdwcbValueBufLen));
  199. bResult = (GetMIMETypeSubKeyA(pcszMIMEType, szMIMETypeSubKey,SIZECHARS(szMIMETypeSubKey)) &&
  200. NO_ERROR == SHGetValueA(HKEY_CLASSES_ROOT, szMIMETypeSubKey,
  201. pcszValue, pdwValueType, pbyteValueBuf,
  202. pdwcbValueBufLen));
  203. return(bResult);
  204. }
  205. STDAPI_(BOOL) GetMIMEValueW(LPCWSTR pcszMIMEType, LPCWSTR pcszValue,
  206. PDWORD pdwValueType, PBYTE pbyteValueBuf,
  207. PDWORD pdwcbValueBufLen)
  208. {
  209. BOOL bResult;
  210. WCHAR szMIMETypeSubKey[MAX_PATH];
  211. ASSERT(IS_VALID_STRING_PTRW(pcszMIMEType, -1));
  212. ASSERT(! pcszValue ||
  213. IS_VALID_STRING_PTRW(pcszValue, -1));
  214. ASSERT(IS_VALID_WRITE_PTR(pdwValueType, DWORD));
  215. ASSERT(IS_VALID_WRITE_BUFFER(pbyteValueBuf, BYTE, *pdwcbValueBufLen));
  216. bResult = (GetMIMETypeSubKeyW(pcszMIMEType, szMIMETypeSubKey,SIZECHARS(szMIMETypeSubKey)) &&
  217. NO_ERROR == SHGetValueW(HKEY_CLASSES_ROOT, szMIMETypeSubKey,
  218. pcszValue, pdwValueType, pbyteValueBuf,
  219. pdwcbValueBufLen));
  220. return(bResult);
  221. }
  222. /*
  223. ** GetMIMETypeStringValue()
  224. **
  225. ** Retrieves the string for a registered MIME type's value.
  226. **
  227. ** Arguments:
  228. **
  229. ** Returns:
  230. **
  231. ** Side Effects: none
  232. */
  233. STDAPI_(BOOL) GetMIMETypeStringValueA(LPCSTR pcszMIMEType, LPCSTR pcszValue,
  234. LPSTR pszBuf, UINT ucBufLen)
  235. {
  236. BOOL bResult;
  237. DWORD dwValueType;
  238. DWORD dwcbLen = CbFromCchA(ucBufLen);
  239. /* GetMIMEValue() will verify parameters. */
  240. bResult = (GetMIMEValueA(pcszMIMEType, pcszValue, &dwValueType, (PBYTE)pszBuf, &dwcbLen) &&
  241. dwValueType == REG_SZ);
  242. if (! bResult)
  243. {
  244. if (ucBufLen > 0)
  245. *pszBuf = '\0';
  246. }
  247. ASSERT(! ucBufLen || IS_VALID_STRING_PTRA(pszBuf, -1));
  248. return(bResult);
  249. }
  250. STDAPI_(BOOL) GetMIMETypeStringValueW(LPCWSTR pcszMIMEType, LPCWSTR pcszValue,
  251. LPWSTR pszBuf, UINT ucBufLen)
  252. {
  253. BOOL bResult;
  254. DWORD dwValueType;
  255. DWORD dwcbLen = CbFromCchW(ucBufLen);
  256. /* GetMIMEValue() will verify parameters. */
  257. bResult = (GetMIMEValueW(pcszMIMEType, pcszValue, &dwValueType, (PBYTE)pszBuf, &dwcbLen) &&
  258. dwValueType == REG_SZ);
  259. if (! bResult)
  260. {
  261. if (ucBufLen > 0)
  262. *pszBuf = '\0';
  263. }
  264. ASSERT(! ucBufLen || IS_VALID_STRING_PTRW(pszBuf, -1));
  265. return(bResult);
  266. }
  267. /*
  268. ** MIME_GetExtension()
  269. **
  270. ** Determines the file name extension to be used when writing a file of a MIME
  271. ** type to the file system.
  272. **
  273. ** Arguments:
  274. **
  275. ** Returns:
  276. **
  277. ** Side Effects: none
  278. */
  279. STDAPI_(BOOL) MIME_GetExtensionA(LPCSTR pcszMIMEType, LPSTR pszExtensionBuf, UINT ucExtensionBufLen)
  280. {
  281. BOOL bResult = FALSE;
  282. ASSERT(IS_VALID_STRING_PTRA(pcszMIMEType, -1));
  283. ASSERT(IS_VALID_WRITE_BUFFER(pszExtensionBuf, CHAR, ucExtensionBufLen));
  284. if (EVAL(ucExtensionBufLen > 2))
  285. {
  286. /* Leave room for possible leading period. */
  287. if (GetMIMETypeStringValueA(pcszMIMEType, "Extension", pszExtensionBuf + 1, ucExtensionBufLen - 1))
  288. {
  289. if (pszExtensionBuf[1])
  290. {
  291. /* Prepend period if necessary. */
  292. if (pszExtensionBuf[1] == TEXT('.'))
  293. /* (+ 1) for null terminator. */
  294. MoveMemory(pszExtensionBuf, pszExtensionBuf + 1,
  295. CbFromCchA(lstrlenA(pszExtensionBuf + 1) + 1));
  296. else
  297. pszExtensionBuf[0] = TEXT('.');
  298. bResult = TRUE;
  299. }
  300. }
  301. }
  302. if (! bResult)
  303. {
  304. if (ucExtensionBufLen > 0)
  305. *pszExtensionBuf = '\0';
  306. }
  307. if (bResult)
  308. TraceMsgA(TF_MIME, "MIME_GetExtension(): Extension %s registered as default extension for MIME type %s.",
  309. pszExtensionBuf, pcszMIMEType);
  310. ASSERT((bResult &&
  311. IsValidExtensionA(pszExtensionBuf)) ||
  312. (! bResult &&
  313. (! ucExtensionBufLen ||
  314. ! *pszExtensionBuf)));
  315. ASSERT(! ucExtensionBufLen ||
  316. (UINT)lstrlenA(pszExtensionBuf) < ucExtensionBufLen);
  317. return(bResult);
  318. }
  319. STDAPI_(BOOL) MIME_GetExtensionW(LPCWSTR pcszMIMEType, LPWSTR pszExtensionBuf, UINT ucExtensionBufLen)
  320. {
  321. BOOL bResult = FALSE;
  322. ASSERT(IS_VALID_STRING_PTRW(pcszMIMEType, -1));
  323. ASSERT(IS_VALID_WRITE_BUFFER(pszExtensionBuf, CHAR, ucExtensionBufLen));
  324. if (EVAL(ucExtensionBufLen > 2))
  325. {
  326. /* Leave room for possible leading period. */
  327. if (GetMIMETypeStringValueW(pcszMIMEType, TEXTW("Extension"), pszExtensionBuf + 1, ucExtensionBufLen - 1))
  328. {
  329. if (pszExtensionBuf[1])
  330. {
  331. /* Prepend period if necessary. */
  332. if (pszExtensionBuf[1] == TEXT('.'))
  333. /* (+ 1) for null terminator. */
  334. MoveMemory(pszExtensionBuf, pszExtensionBuf + 1,
  335. CbFromCchW(lstrlenW(pszExtensionBuf + 1) + 1));
  336. else
  337. pszExtensionBuf[0] = TEXT('.');
  338. bResult = TRUE;
  339. }
  340. }
  341. }
  342. if (! bResult)
  343. {
  344. if (ucExtensionBufLen > 0)
  345. *pszExtensionBuf = '\0';
  346. }
  347. if (bResult)
  348. TraceMsgW(TF_MIME, "MIME_GetExtension(): Extension %s registered as default extension for MIME type %s.",
  349. pszExtensionBuf, pcszMIMEType);
  350. ASSERT((bResult &&
  351. IsValidExtensionW(pszExtensionBuf)) ||
  352. (! bResult &&
  353. (! ucExtensionBufLen ||
  354. ! *pszExtensionBuf)));
  355. ASSERT(! ucExtensionBufLen ||
  356. (UINT)lstrlenW(pszExtensionBuf) < ucExtensionBufLen);
  357. return(bResult);
  358. }