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.

211 lines
6.7 KiB

  1. #include "precomp.h"
  2. #include "shutil.h"
  3. HRESULT SHStringFromCLSIDA( LPSTR szCLSID, DWORD cSize, REFCLSID rCLSID )
  4. {
  5. if ( cSize < 39 )
  6. {
  7. return E_INVALIDARG;
  8. }
  9. WCHAR szWCLSID[40];
  10. HRESULT hr = StringFromGUID2( rCLSID, szWCLSID, 40 );
  11. if ( FAILED( hr ))
  12. {
  13. return hr;
  14. }
  15. WideCharToMultiByte( CP_ACP, 0, szWCLSID, -1, szCLSID, cSize, 0, 0);
  16. return hr;
  17. }
  18. HRESULT GetFileInfoByHandle(LPCTSTR pszFile, BY_HANDLE_FILE_INFORMATION *pInfo)
  19. {
  20. HRESULT hr;
  21. HANDLE hFile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  22. if (INVALID_HANDLE_VALUE != hFile)
  23. {
  24. if (GetFileInformationByHandle(hFile, pInfo))
  25. {
  26. hr = S_OK;
  27. }
  28. else
  29. {
  30. hr = HRESULT_FROM_WIN32(GetLastError());
  31. }
  32. CloseHandle(hFile);
  33. }
  34. else
  35. {
  36. hr = HRESULT_FROM_WIN32(GetLastError());
  37. }
  38. return hr;
  39. }
  40. // S_OK -> YES, S_FALSE -> NO, FAILED(hr) otherwise
  41. STDAPI IsSameFile(LPCTSTR pszFile1, LPCTSTR pszFile2)
  42. {
  43. HRESULT hr;
  44. // use CRT str cmp semantics as localized strcmp should not be used for the file system
  45. if (0 == StrCmpIC(pszFile1, pszFile2))
  46. {
  47. hr = S_OK; // test the names
  48. }
  49. else
  50. {
  51. // very clever here... we can test for alias names that map to the same
  52. // file. for example the short name vs long name of the same file
  53. // the UNC name vs drive letter version of the name
  54. BY_HANDLE_FILE_INFORMATION hfi1;
  55. hr = GetFileInfoByHandle(pszFile1, &hfi1);
  56. if (SUCCEEDED(hr))
  57. {
  58. BY_HANDLE_FILE_INFORMATION hfi2;
  59. hr = GetFileInfoByHandle(pszFile2, &hfi2);
  60. if (SUCCEEDED(hr))
  61. {
  62. if (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber &&
  63. hfi1.nFileIndexHigh == hfi2.nFileIndexHigh &&
  64. hfi1.nFileIndexLow == hfi2.nFileIndexLow)
  65. {
  66. hr = S_OK; // same!
  67. }
  68. else
  69. {
  70. hr = S_FALSE; // different
  71. }
  72. }
  73. }
  74. }
  75. return hr;
  76. }
  77. UINT FindInDecoderList(ImageCodecInfo *pici, UINT cDecoders, LPCTSTR pszFile)
  78. {
  79. LPCTSTR pszExt = PathFindExtension(pszFile); // speed up PathMatchSpec calls
  80. // look at the list of decoders to see if this format is there
  81. for (UINT i = 0; i < cDecoders; i++)
  82. {
  83. if (PathMatchSpec(pszExt, pici[i].FilenameExtension))
  84. return i;
  85. }
  86. return (UINT)-1; // not found!
  87. }
  88. HRESULT GetUIObjectFromPath(LPCTSTR pszFile, REFIID riid, void **ppv)
  89. {
  90. *ppv = NULL;
  91. LPITEMIDLIST pidl;
  92. HRESULT hr = SHILCreateFromPath(pszFile, &pidl, NULL);
  93. if (SUCCEEDED(hr))
  94. {
  95. hr = SHGetUIObjectFromFullPIDL(pidl, NULL, riid, ppv);
  96. ILFree(pidl);
  97. }
  98. return hr;
  99. }
  100. BOOL FmtSupportsMultiPage(IShellImageData *pData, GUID *pguidFmt)
  101. {
  102. BOOL bRet = FALSE;
  103. EncoderParameters *pencParams;
  104. if (SUCCEEDED(pData->GetEncoderParams(pguidFmt, &pencParams)))
  105. {
  106. for (UINT i=0;!bRet && i<pencParams->Count;i++)
  107. {
  108. if (EncoderSaveFlag == pencParams->Parameter[i].Guid)
  109. {
  110. if (EncoderValueMultiFrame == *((ULONG*)pencParams->Parameter[i].Value))
  111. {
  112. bRet = TRUE;
  113. }
  114. }
  115. }
  116. CoTaskMemFree(pencParams);
  117. }
  118. return bRet;
  119. }
  120. HRESULT SetWallpaperHelper(LPCWSTR pszPath)
  121. {
  122. IActiveDesktop* pad;
  123. HRESULT hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC, IID_PPV_ARG(IActiveDesktop, &pad));
  124. if (SUCCEEDED(hr))
  125. {
  126. IShellImageDataFactory* pidf;
  127. hr = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC, IID_PPV_ARG(IShellImageDataFactory, &pidf));
  128. if (SUCCEEDED(hr))
  129. {
  130. IShellImageData* pid;
  131. hr = pidf->CreateImageFromFile(pszPath, &pid);
  132. if (SUCCEEDED(hr))
  133. {
  134. hr = pid->Decode(SHIMGDEC_DEFAULT, 0,0);
  135. if (SUCCEEDED(hr))
  136. {
  137. // we are basing this on a best fit to the primary screen
  138. ULONG cxScreen = GetSystemMetrics(SM_CXSCREEN);
  139. ULONG cyScreen = GetSystemMetrics(SM_CYSCREEN);
  140. SIZE szImg;
  141. pid->GetSize(&szImg);
  142. hr = pad->SetWallpaper(pszPath, 0);
  143. if (SUCCEEDED(hr))
  144. {
  145. WALLPAPEROPT wpo;
  146. wpo.dwSize = sizeof(wpo);
  147. wpo.dwStyle = WPSTYLE_CENTER;
  148. // if the image is small on either axis then tile
  149. if (((ULONG)szImg.cx*2 < cxScreen) || ((ULONG)szImg.cy*2 < cyScreen))
  150. {
  151. wpo.dwStyle = WPSTYLE_TILE;
  152. }
  153. // if the image is larger than the screen then stretch
  154. else if ((ULONG)szImg.cx > cxScreen && (ULONG)szImg.cy > cyScreen)
  155. {
  156. wpo.dwStyle = WPSTYLE_STRETCH;
  157. }
  158. else
  159. {
  160. // If the aspect ratio matches the screen then stretch.
  161. // I'm checking is the aspect ratios are *close* to matching.
  162. // Here's the logic behind this:
  163. //
  164. // a / b == c / d
  165. // a * d == c * b
  166. // (a * d) / (c * b) == 1
  167. // 0.75 <= (a * d) / (c * b) < 1.25 <-- our *close* factor
  168. // 3 <= 4 * (a * d) / (c * b) < 5
  169. //
  170. // We do an integer division which will floor the result meaning
  171. // that if the result is 3 or 4 we are inside the rang we want.
  172. DWORD dwRes = (4 * (ULONG)szImg.cx * cyScreen) / (cxScreen * (ULONG)szImg.cy);
  173. if (dwRes == 4 || dwRes == 3)
  174. wpo.dwStyle = WPSTYLE_STRETCH;
  175. }
  176. hr = pad->SetWallpaperOptions(&wpo, 0);
  177. if (SUCCEEDED(hr))
  178. {
  179. hr = pad->ApplyChanges(AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH);
  180. }
  181. }
  182. }
  183. pid->Release();
  184. }
  185. pidf->Release();
  186. }
  187. pad->Release();
  188. }
  189. return hr;
  190. }