| 70 | namespace // Internal linkage |
| 71 | { |
| 72 | |
| 73 | // System.Title property key, values taken from http://msdn.microsoft.com/en-us/library/bb787584.aspx |
| 74 | const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 }; |
| 75 | |
| 76 | // Helper function to convert from ANSI to unicode strings. Caller must delete[] return value. |
| 77 | LPWSTR ansiToUnicode(const char *s) |
| 78 | { |
| 79 | DWORD size = MultiByteToWideChar(CP_ACP, 0, s, -1, NULL, 0); |
| 80 | if( size > 0 ) |
| 81 | { |
| 82 | LPWSTR result = new WCHAR[size]; |
| 83 | if( MultiByteToWideChar(CP_ACP, 0, s, -1, result, size) != 0 ) |
| 84 | return result; |
| 85 | } |
| 86 | return NULL; |
| 87 | } |
| 88 | |
| 89 | bool isWin7OrLater() |
| 90 | { |
| 91 | OSVERSIONINFOEX versionInfo; |
| 92 | DWORDLONG conditionMask = 0; |
| 93 | |
| 94 | ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX)); |
| 95 | versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); |
| 96 | versionInfo.dwMajorVersion = 6; |
| 97 | versionInfo.dwMinorVersion = 1; |
| 98 | |
| 99 | VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL); |
| 100 | VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL); |
| 101 | |
| 102 | return VerifyVersionInfo(&versionInfo, VER_MAJORVERSION | VER_MINORVERSION, conditionMask); |
| 103 | } |
| 104 | |
| 105 | } |
| 106 | |
| 213 | void OSystem_Win32::engineInit() |
| 214 | { |
| 215 | OSystem_SDL::engineInit(); |
| 216 | |
| 217 | // Calling SHAddToRecentDocs with an IShellLink is only supported for jump list purposes in Windows 7, |
| 218 | // so we don't call it in older versions of Windows. |
| 219 | if (isWin7OrLater()) { |
| 220 | // ANSI version doesn't seem to work correctly with Win7 jump lists, so explicitly use Unicode interface. |
| 221 | IShellLinkW *link; |
| 222 | |
| 223 | // Get the ScummVM executable path. |
| 224 | WCHAR path[MAX_PATH]; |
| 225 | GetModuleFileNameW(NULL, path, MAX_PATH); |
| 226 | |
| 227 | // Create a shell link. |
| 228 | if (SUCCEEDED(CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&link)))) { |
| 229 | // Convert game name and description to Unicode. |
| 230 | LPWSTR game = ansiToUnicode(ConfMan.getActiveDomainName().c_str()); |
| 231 | LPWSTR description = ansiToUnicode(ConfMan.get("description").c_str()); |
| 232 | |
| 233 | // Set link properties. |
| 234 | link->SetPath(path); |
| 235 | link->SetArguments(game); |
| 236 | link->SetIconLocation(path, 0); // There's no way to get a game-specific icon, is there? |
| 237 | |
| 238 | // The link's display name must be set via property store. |
| 239 | IPropertyStore* propStore; |
| 240 | HRESULT hr = link->QueryInterface(&propStore); |
| 241 | if (SUCCEEDED(hr)) { |
| 242 | PROPVARIANT pv; |
| 243 | pv.vt = VT_LPWSTR; |
| 244 | pv.pwszVal = description; |
| 245 | |
| 246 | hr = propStore->SetValue(PKEY_Title, pv); |
| 247 | |
| 248 | propStore->Commit(); |
| 249 | propStore->Release(); |
| 250 | } |
| 251 | |
| 252 | // SHAddToRecentDocs will cause the games to be added to the Recent list, allowing the |
| 253 | // user to pin them. |
| 254 | SHAddToRecentDocs(SHARD_LINK, link); |
| 255 | link->Release(); |
| 256 | delete[] game; |
| 257 | delete[] description; |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | |