| /* |
| * Copyright 2000-2012 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @author Denis Fokin |
| */ |
| |
| #include "stdafx.h" |
| #include <windows.h> |
| #include <Objbase.h> |
| #include "jumplistbridge64.h" |
| #include <ShObjIdl.h> |
| #include <Objectarray.h> |
| #include <Knownfolders.h> |
| #include <Shlobj.h> |
| #pragma comment(lib, "Shlwapi.lib") |
| #include <wchar.h> |
| #include <propvarutil.h> |
| #include <propsys.h> |
| #include <propkey.h> |
| #include <stdio.h> |
| #include <comdef.h> |
| |
| wchar_t * jstowsz(JNIEnv* env, jstring string) |
| { |
| if (string == NULL) { |
| return NULL; |
| } |
| |
| int chCount = env->GetStringLength(string); |
| const jchar* javaChars = env->GetStringChars(string, NULL); |
| |
| if (javaChars == NULL) { |
| return NULL; |
| } |
| |
| wchar_t* wideString = new wchar_t[chCount+1]; |
| memcpy(wideString, javaChars, chCount*2); |
| wideString[chCount] = 0; |
| env->ReleaseStringChars(string, javaChars); |
| return wideString; |
| } |
| |
| PCWSTR jetBrainsAppId; |
| |
| /* |
| * Class: com_intellij_ui_win_RecentTasks |
| * Method: initialize |
| * Signature: (Ljava/lang/String;)V |
| */ |
| JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_initialize |
| (JNIEnv * jEnv, jclass clz, jstring jAppId) { |
| jetBrainsAppId = jstowsz(jEnv, jAppId); |
| SetCurrentProcessExplicitAppUserModelID(jetBrainsAppId); |
| ::CoInitialize(NULL); |
| } |
| |
| /* |
| * Class: com_intellij_ui_win_RecentTasks |
| * Method: clearNative |
| * Signature: ()V |
| */ |
| JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_clearNative |
| (JNIEnv *, jclass) { |
| |
| ICustomDestinationList * pcdl; |
| HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void**)&pcdl); |
| |
| if (SUCCEEDED(hr)) { |
| pcdl->SetAppID(jetBrainsAppId); |
| |
| UINT uMaxSlots; |
| IObjectArray *poaRemoved; |
| hr = pcdl->BeginList( |
| &uMaxSlots, |
| IID_PPV_ARGS(&poaRemoved)); |
| pcdl->DeleteList(jetBrainsAppId); |
| hr = pcdl->CommitList(); |
| } |
| } |
| |
| HRESULT _CreateShellLink(PCWSTR pszPath, |
| PCWSTR pszArguments, PCWSTR pszTitle, |
| IShellLink **ppsl) |
| { |
| IShellLink *psl; |
| HRESULT hr = CoCreateInstance( |
| CLSID_ShellLink, |
| NULL, |
| CLSCTX_INPROC_SERVER, |
| IID_PPV_ARGS(&psl)); |
| if (SUCCEEDED(hr)) |
| { |
| hr = psl->SetPath(pszPath); |
| if (SUCCEEDED(hr)) |
| { |
| hr = psl->SetArguments(pszArguments); |
| if (SUCCEEDED(hr)) |
| { |
| IPropertyStore *pps; |
| hr = psl->QueryInterface(IID_PPV_ARGS(&pps)); |
| if (SUCCEEDED(hr)) |
| { |
| PROPVARIANT propvar; |
| hr = InitPropVariantFromString(pszTitle, &propvar); |
| if (SUCCEEDED(hr)) |
| { hr = pps->SetValue(PKEY_Title, propvar); |
| if (SUCCEEDED(hr)) |
| { |
| hr = pps->Commit(); |
| if (SUCCEEDED(hr)) |
| { |
| hr = psl->QueryInterface |
| (IID_PPV_ARGS(ppsl)); |
| } |
| } |
| PropVariantClear(&propvar); |
| } |
| pps->Release(); |
| } |
| } |
| } |
| else |
| { |
| hr = HRESULT_FROM_WIN32(GetLastError()); |
| } |
| psl->Release(); |
| } |
| return hr; |
| } |
| |
| void checkJNISuccess (JNIEnv * jEnv) { |
| if (jEnv->ExceptionOccurred()) { |
| jEnv->ExceptionDescribe(); |
| } |
| } |
| |
| |
| LPCWSTR getShortPath (LPCWSTR lpszPath) { |
| long length = 0; |
| TCHAR* buffer = NULL; |
| length = GetShortPathName(lpszPath, NULL, 0); |
| buffer = new TCHAR[length]; |
| length = GetShortPathName(lpszPath, buffer, length); |
| return buffer; |
| |
| } |
| |
| /* |
| * Class: com_intellij_ui_win_RecentTasks |
| * Method: getShortenPath |
| * Signature: ([Ljava/lang/String;)[Ljava/lang/String; |
| */ |
| JNIEXPORT jstring JNICALL Java_com_intellij_ui_win_RecentTasks_getShortenPath |
| (JNIEnv * jEnv, jclass c, jstring path) |
| { |
| |
| if (path == NULL) { |
| wprintf(L"The object is NULL \n"); |
| } |
| |
| long length = 0; |
| TCHAR* shortenPath = NULL; |
| length = GetShortPathName(jstowsz(jEnv, path), NULL, 0); |
| shortenPath = new TCHAR[length]; |
| GetShortPathName(jstowsz(jEnv, path), shortenPath, length); |
| |
| char *mbDcr = 0; |
| |
| int mblen = WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortenPath, length, mbDcr, NULL, NULL, NULL); |
| mbDcr = new char[mblen + 1]; |
| WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, shortenPath, length, mbDcr, length + 1, NULL, NULL); |
| |
| jstring jstrBuf = jEnv->NewStringUTF(mbDcr); |
| |
| return jstrBuf; |
| } |
| |
| /* |
| * Class: com_intellij_ui_win_RecentTasks |
| * Method: addTasksNativeForCategory |
| * Signature: (Ljava/lang/String;[Lcom/intellij/ui/win/RecentTasks/Task;)V |
| */ |
| JNIEXPORT void JNICALL Java_com_intellij_ui_win_RecentTasks_addTasksNativeForCategory |
| (JNIEnv * jEnv, jclass c, jstring cn, jobjectArray linksArray) |
| { |
| LPCWSTR categoryName = (wchar_t*) jEnv->GetStringChars(cn, 0); |
| |
| ICustomDestinationList * pcdl; |
| HRESULT hr = CoCreateInstance(CLSID_DestinationList, NULL, CLSCTX_INPROC_SERVER, IID_ICustomDestinationList, (void**)&pcdl); |
| |
| if (SUCCEEDED(hr)) { |
| pcdl->SetAppID(jetBrainsAppId); |
| |
| UINT uMaxSlots; |
| IObjectArray *poaRemoved; |
| hr = pcdl->BeginList( |
| &uMaxSlots, |
| IID_PPV_ARGS(&poaRemoved)); |
| if (SUCCEEDED(hr)) |
| { |
| IObjectCollection *poc; |
| HRESULT hr = CoCreateInstance(CLSID_EnumerableObjectCollection, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&poc)); |
| if (SUCCEEDED(hr)) |
| { |
| jint i; |
| jint count = jEnv->GetArrayLength(linksArray); |
| for (i=0; i < count; i++) { |
| jobject linkData = jEnv->GetObjectArrayElement(linksArray, i); |
| checkJNISuccess(jEnv); |
| |
| jclass cls = jEnv->GetObjectClass(linkData); |
| checkJNISuccess(jEnv); |
| |
| jfieldID pathFieldId = jEnv->GetFieldID(cls, "path", "Ljava/lang/String;"); |
| checkJNISuccess(jEnv); |
| |
| jfieldID argsFieldId = jEnv->GetFieldID(cls, "args", "Ljava/lang/String;"); |
| checkJNISuccess(jEnv); |
| |
| jfieldID descriptionFieldId = jEnv->GetFieldID(cls, "description", "Ljava/lang/String;"); |
| checkJNISuccess(jEnv); |
| |
| jstring path = (jstring)jEnv->GetObjectField(linkData, pathFieldId); |
| checkJNISuccess(jEnv); |
| |
| jstring args = (jstring)jEnv->GetObjectField(linkData, argsFieldId); |
| checkJNISuccess(jEnv); |
| |
| jstring description = (jstring)jEnv->GetObjectField(linkData, descriptionFieldId); |
| checkJNISuccess(jEnv); |
| |
| IShellLink * psl; |
| hr = _CreateShellLink(jstowsz(jEnv, path), |
| jstowsz(jEnv, args), |
| jstowsz(jEnv, description), &psl); |
| |
| if (SUCCEEDED(hr)) |
| { |
| hr = poc->AddObject(psl); |
| psl->Release(); |
| |
| } else { |
| jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot create a shell link"); |
| } |
| |
| jEnv->DeleteLocalRef(linkData); |
| } |
| |
| pcdl->AppendCategory(categoryName, poc); |
| } else { |
| jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot recieve CLSID_EnumerableObjectCollection interface"); |
| } |
| pcdl->CommitList(); |
| pcdl->Release(); |
| } else { |
| jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot begin DestinationList"); |
| } |
| } else { |
| jEnv->ThrowNew(jEnv->FindClass("java/lang/Exception"), "Cannot recieve CLSID_DestinationList interface"); |
| } |
| } |