#include "precomp.h" #include "shutil.h" HRESULT SHStringFromCLSIDA( LPSTR szCLSID, DWORD cSize, REFCLSID rCLSID ) { if ( cSize < 39 ) { return E_INVALIDARG; } WCHAR szWCLSID[40]; HRESULT hr = StringFromGUID2( rCLSID, szWCLSID, 40 ); if ( FAILED( hr )) { return hr; } WideCharToMultiByte( CP_ACP, 0, szWCLSID, -1, szCLSID, cSize, 0, 0); return hr; } HRESULT GetFileInfoByHandle(LPCTSTR pszFile, BY_HANDLE_FILE_INFORMATION *pInfo) { HRESULT hr; HANDLE hFile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE != hFile) { if (GetFileInformationByHandle(hFile, pInfo)) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(GetLastError()); } CloseHandle(hFile); } else { hr = HRESULT_FROM_WIN32(GetLastError()); } return hr; } // S_OK -> YES, S_FALSE -> NO, FAILED(hr) otherwise STDAPI IsSameFile(LPCTSTR pszFile1, LPCTSTR pszFile2) { HRESULT hr; // use CRT str cmp semantics as localized strcmp should not be used for the file system if (0 == StrCmpIC(pszFile1, pszFile2)) { hr = S_OK; // test the names } else { // very clever here... we can test for alias names that map to the same // file. for example the short name vs long name of the same file // the UNC name vs drive letter version of the name BY_HANDLE_FILE_INFORMATION hfi1; hr = GetFileInfoByHandle(pszFile1, &hfi1); if (SUCCEEDED(hr)) { BY_HANDLE_FILE_INFORMATION hfi2; hr = GetFileInfoByHandle(pszFile2, &hfi2); if (SUCCEEDED(hr)) { if (hfi1.dwVolumeSerialNumber == hfi2.dwVolumeSerialNumber && hfi1.nFileIndexHigh == hfi2.nFileIndexHigh && hfi1.nFileIndexLow == hfi2.nFileIndexLow) { hr = S_OK; // same! } else { hr = S_FALSE; // different } } } } return hr; } UINT FindInDecoderList(ImageCodecInfo *pici, UINT cDecoders, LPCTSTR pszFile) { LPCTSTR pszExt = PathFindExtension(pszFile); // speed up PathMatchSpec calls // look at the list of decoders to see if this format is there for (UINT i = 0; i < cDecoders; i++) { if (PathMatchSpec(pszExt, pici[i].FilenameExtension)) return i; } return (UINT)-1; // not found! } HRESULT GetUIObjectFromPath(LPCTSTR pszFile, REFIID riid, void **ppv) { *ppv = NULL; LPITEMIDLIST pidl; HRESULT hr = SHILCreateFromPath(pszFile, &pidl, NULL); if (SUCCEEDED(hr)) { hr = SHGetUIObjectFromFullPIDL(pidl, NULL, riid, ppv); ILFree(pidl); } return hr; } BOOL FmtSupportsMultiPage(IShellImageData *pData, GUID *pguidFmt) { BOOL bRet = FALSE; EncoderParameters *pencParams; if (SUCCEEDED(pData->GetEncoderParams(pguidFmt, &pencParams))) { for (UINT i=0;!bRet && iCount;i++) { if (EncoderSaveFlag == pencParams->Parameter[i].Guid) { if (EncoderValueMultiFrame == *((ULONG*)pencParams->Parameter[i].Value)) { bRet = TRUE; } } } CoTaskMemFree(pencParams); } return bRet; } HRESULT SetWallpaperHelper(LPCWSTR pszPath) { IActiveDesktop* pad; HRESULT hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC, IID_PPV_ARG(IActiveDesktop, &pad)); if (SUCCEEDED(hr)) { IShellImageDataFactory* pidf; hr = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC, IID_PPV_ARG(IShellImageDataFactory, &pidf)); if (SUCCEEDED(hr)) { IShellImageData* pid; hr = pidf->CreateImageFromFile(pszPath, &pid); if (SUCCEEDED(hr)) { hr = pid->Decode(SHIMGDEC_DEFAULT, 0,0); if (SUCCEEDED(hr)) { // we are basing this on a best fit to the primary screen ULONG cxScreen = GetSystemMetrics(SM_CXSCREEN); ULONG cyScreen = GetSystemMetrics(SM_CYSCREEN); SIZE szImg; pid->GetSize(&szImg); hr = pad->SetWallpaper(pszPath, 0); if (SUCCEEDED(hr)) { WALLPAPEROPT wpo; wpo.dwSize = sizeof(wpo); wpo.dwStyle = WPSTYLE_CENTER; // if the image is small on either axis then tile if (((ULONG)szImg.cx*2 < cxScreen) || ((ULONG)szImg.cy*2 < cyScreen)) { wpo.dwStyle = WPSTYLE_TILE; } // if the image is larger than the screen then stretch else if ((ULONG)szImg.cx > cxScreen && (ULONG)szImg.cy > cyScreen) { wpo.dwStyle = WPSTYLE_STRETCH; } else { // If the aspect ratio matches the screen then stretch. // I'm checking is the aspect ratios are *close* to matching. // Here's the logic behind this: // // a / b == c / d // a * d == c * b // (a * d) / (c * b) == 1 // 0.75 <= (a * d) / (c * b) < 1.25 <-- our *close* factor // 3 <= 4 * (a * d) / (c * b) < 5 // // We do an integer division which will floor the result meaning // that if the result is 3 or 4 we are inside the rang we want. DWORD dwRes = (4 * (ULONG)szImg.cx * cyScreen) / (cxScreen * (ULONG)szImg.cy); if (dwRes == 4 || dwRes == 3) wpo.dwStyle = WPSTYLE_STRETCH; } hr = pad->SetWallpaperOptions(&wpo, 0); if (SUCCEEDED(hr)) { hr = pad->ApplyChanges(AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH); } } } pid->Release(); } pidf->Release(); } pad->Release(); } return hr; }