comparison src/windows/native/sun/windows/ShellFolder2.cpp @ 1133:51148b9aed43

6491795: COM should be initialized for Shell API calls in ShellFolder2.cpp Reviewed-by: peterz, loneid
author rupashka
date Thu, 12 Mar 2009 14:00:26 +0300
parents 75755e92430c
children b8d8ec2dac68
comparison
equal deleted inserted replaced
1:f80b22208922 2:5d89dee0586f
223 MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V"); 223 MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V");
224 FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;"); 224 FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;");
225 FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;"); 225 FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;");
226 } 226 }
227 227
228
229 /*
230 * Class: sun_awt_shell_Win32ShellFolderManager2
231 * Method: initializeCom
232 * Signature: ()V
233 */
234 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_initializeCom
235 (JNIEnv* env, jclass cls)
236 {
237 HRESULT hr = ::CoInitialize(NULL);
238 if (FAILED(hr)) {
239 char c[64];
240 sprintf(c, "Could not initialize COM: HRESULT=0x%08X", hr);
241 JNU_ThrowInternalError(env, c);
242 }
243 }
244
245 /*
246 * Class: sun_awt_shell_Win32ShellFolderManager2
247 * Method: uninitializeCom
248 * Signature: ()V
249 */
250 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_uninitializeCom
251 (JNIEnv* env, jclass cls)
252 {
253 ::CoUninitialize();
254 }
255
228 static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) { 256 static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) {
229 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp 257 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
230 HRESULT hres; 258 HRESULT hres;
231 HICON hIcon = NULL; 259 HICON hIcon = NULL;
232 IShellIcon* pIShellIcon; 260 IShellIcon* pIShellIcon;
237 } 265 }
238 } 266 }
239 return (IShellIcon*)NULL; 267 return (IShellIcon*)NULL;
240 } 268 }
241 269
242 // Fixed 6263669
243 //
244 // CoInitialize wrapper
245 // call CoInitialize to initialize COM in STA mode and check result
246 // RPC_E_CHANGED_MODE means COM has already been initialized in MTA mode,
247 // so don't set the flag to call CoUninitialize later
248
249 BOOL CoInit(BOOL& doCoUninit) { // returns TRUE if initialized successfully
250 switch(::CoInitialize(NULL)) {
251 case S_OK:
252 case S_FALSE:
253 doCoUninit = TRUE;
254 return TRUE;
255 break;
256 case RPC_E_CHANGED_MODE:
257 doCoUninit = FALSE;
258 return TRUE;
259 break;
260 default:
261 return FALSE;
262 }
263 }
264
265 270
266 /* 271 /*
267 * Class: sun_awt_shell_Win32ShellFolder2 272 * Class: sun_awt_shell_Win32ShellFolder2
268 * Method: getIShellIcon 273 * Method: getIShellIcon
269 * Signature: (J)J 274 * Signature: (J)J
505 } 510 }
506 511
507 512
508 /* 513 /*
509 * Class: sun_awt_shell_Win32ShellFolder2 514 * Class: sun_awt_shell_Win32ShellFolder2
510 * Method: getFileSystemPath 515 * Method: getFileSystemPath0
511 * Signature: (I)Ljava/lang/String; 516 * Signature: (I)Ljava/lang/String;
512 */ 517 */
513 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath__I 518 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath0
514 (JNIEnv* env, jclass cls, jint csidl) 519 (JNIEnv* env, jclass cls, jint csidl)
515 { 520 {
516 LPITEMIDLIST relPIDL; 521 LPITEMIDLIST relPIDL;
517 TCHAR szBuf[MAX_PATH]; 522 TCHAR szBuf[MAX_PATH];
518 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, csidl, &relPIDL); 523 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, csidl, &relPIDL);
609 IShellFolder* pFolder; 614 IShellFolder* pFolder;
610 HRESULT hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder); 615 HRESULT hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
611 if (SUCCEEDED (hr)) { 616 if (SUCCEEDED (hr)) {
612 return (jlong)pFolder; 617 return (jlong)pFolder;
613 } 618 }
614 if (IS_WINVISTA) {
615 BOOL doCoUninit;
616 if (CoInit(doCoUninit)) {
617 hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
618 if (doCoUninit) {
619 ::CoUninitialize();
620 }
621 if (SUCCEEDED (hr)) {
622 return (jlong)pFolder;
623 }
624 }
625 }
626 return 0; 619 return 0;
627 } 620 }
628 621
629 622
630 /* 623 /*
648 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 641 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
649 if (pidl == NULL) { 642 if (pidl == NULL) {
650 return NULL; 643 return NULL;
651 } 644 }
652 645
653 pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret); 646 hres = pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret);
647 if (FAILED(hres)) {
648 return NULL;
649 }
654 650
655 switch (strret.uType) { 651 switch (strret.uType) {
656 case STRRET_CSTR : 652 case STRRET_CSTR :
657 // IShellFolder::ParseDisplayName requires the path name in Unicode. 653 // IShellFolder::ParseDisplayName requires the path name in Unicode.
658 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strret.cStr, -1, olePath, MAX_PATH); 654 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strret.cStr, -1, olePath, MAX_PATH);
667 case STRRET_WSTR : 663 case STRRET_WSTR :
668 wstr = strret.pOleStr; 664 wstr = strret.pOleStr;
669 break; 665 break;
670 } 666 }
671 667
672 BOOL doCoUninit;
673 if (!CoInit(doCoUninit)) {
674 return 0;
675 }
676 IShellLinkW* psl; 668 IShellLinkW* psl;
677 hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl); 669 hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl);
678 if (SUCCEEDED(hres)) { 670 if (SUCCEEDED(hres)) {
679 IPersistFile* ppf; 671 IPersistFile* ppf;
680 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 672 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
690 } 682 }
691 ppf->Release(); 683 ppf->Release();
692 } 684 }
693 psl->Release(); 685 psl->Release();
694 } 686 }
695 if (doCoUninit) {
696 ::CoUninitialize();
697 }
698 687
699 if (SUCCEEDED(hres)) { 688 if (SUCCEEDED(hres)) {
700 return (jlong)pidl; 689 return (jlong)pidl;
701 } else { 690 } else {
702 return 0; 691 return 0;
739 728
740 729
741 /* 730 /*
742 * Class: sun_awt_shell_Win32ShellFolder2 731 * Class: sun_awt_shell_Win32ShellFolder2
743 * Method: getDisplayNameOf 732 * Method: getDisplayNameOf
744 * Signature: (JJ)Ljava/lang/String; 733 * Signature: (JJI)Ljava/lang/String;
745 */ 734 */
746 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf 735 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf
747 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs) 736 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs)
748 { 737 {
749 IShellFolder* pParent = (IShellFolder*)parentIShellFolder; 738 IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
831 if (pIShellIcon == NULL && pidl == NULL) { 820 if (pIShellIcon == NULL && pidl == NULL) {
832 return 0; 821 return 0;
833 } 822 }
834 823
835 INT index = -1; 824 INT index = -1;
836 BOOL doCoUninit;
837 if (!CoInit(doCoUninit)) {
838 return (jint)index;
839 }
840 825
841 HRESULT hres; 826 HRESULT hres;
842 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp 827 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
843 if (pIShellIcon != NULL) { 828 if (pIShellIcon != NULL) {
844 hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index); 829 hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index);
845 } 830 }
846 831
847 if (doCoUninit) {
848 ::CoUninitialize();
849 }
850 return (jint)index; 832 return (jint)index;
851 } 833 }
852 834
853 835
854 /* 836 /*
864 if (pIShellFolder == NULL || pidl == NULL) { 846 if (pIShellFolder == NULL || pidl == NULL) {
865 return 0; 847 return 0;
866 } 848 }
867 849
868 HICON hIcon = NULL; 850 HICON hIcon = NULL;
869 BOOL doCoUninit;
870 if (!CoInit(doCoUninit)) {
871 return (jlong)hIcon;
872 }
873 851
874 HRESULT hres; 852 HRESULT hres;
875 IExtractIconW* pIcon; 853 IExtractIconW* pIcon;
876 hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl), 854 hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl),
877 IID_IExtractIconW, NULL, (void**)&pIcon); 855 IID_IExtractIconW, NULL, (void**)&pIcon);
891 fn_DestroyIcon((HICON)hIconLarge); 869 fn_DestroyIcon((HICON)hIconLarge);
892 } 870 }
893 } 871 }
894 } 872 }
895 pIcon->Release(); 873 pIcon->Release();
896 }
897 if (doCoUninit) {
898 ::CoUninitialize();
899 } 874 }
900 return (jlong)hIcon; 875 return (jlong)hIcon;
901 } 876 }
902 877
903 878
992 HBITMAP hBitmap = NULL; 967 HBITMAP hBitmap = NULL;
993 BITMAP bm; 968 BITMAP bm;
994 HINSTANCE libComCtl32; 969 HINSTANCE libComCtl32;
995 HINSTANCE libShell32; 970 HINSTANCE libShell32;
996 971
997
998 libShell32 = LoadLibrary(TEXT("shell32.dll")); 972 libShell32 = LoadLibrary(TEXT("shell32.dll"));
999 if (libShell32 != NULL) { 973 if (libShell32 != NULL) {
1000 long osVersion = GetVersion();
1001 BOOL isVista = (!(osVersion & 0x80000000) && (LOBYTE(LOWORD(osVersion)) >= 6));
1002
1003 hBitmap = (HBITMAP)LoadImage(libShell32, 974 hBitmap = (HBITMAP)LoadImage(libShell32,
1004 isVista ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216), 975 IS_WINVISTA ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216),
1005 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); 976 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
1006 } 977 }
1007 if (hBitmap == NULL) { 978 if (hBitmap == NULL) {
1008 libComCtl32 = LoadLibrary(TEXT("comctl32.dll")); 979 libComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
1009 if (libComCtl32 != NULL) { 980 if (libComCtl32 != NULL) {
1093 } 1064 }
1094 return 0; 1065 return 0;
1095 } 1066 }
1096 1067
1097 1068
1098 // Helper functions for workaround COM initialization:
1099
1100 static HRESULT GetDetailsOfFolder(
1101 IShellFolder2 *folder,
1102 LPCITEMIDLIST pidl,
1103 UINT column,
1104 SHELLDETAILS *psd)
1105 {
1106 HRESULT hr = folder->GetDetailsOf(pidl, column, psd);
1107 if (IS_WINVISTA && FAILED (hr)) {
1108 BOOL doCoUninit;
1109 if (CoInit(doCoUninit)) {
1110 hr = folder->GetDetailsOf(pidl, column, psd);
1111 if (doCoUninit) {
1112 ::CoUninitialize();
1113 }
1114 }
1115 }
1116 return hr;
1117 }
1118
1119 static HRESULT GetDetailsOf(
1120 IShellDetails *details,
1121 LPCITEMIDLIST pidl,
1122 UINT column,
1123 SHELLDETAILS *psd)
1124 {
1125 HRESULT hr = details->GetDetailsOf(pidl, column, psd);
1126 if (IS_WINVISTA && FAILED (hr)) {
1127 BOOL doCoUninit;
1128 if (CoInit(doCoUninit)) {
1129 hr = details->GetDetailsOf(pidl, column, psd);
1130 if (doCoUninit) {
1131 ::CoUninitialize();
1132 }
1133 }
1134 }
1135 return hr;
1136 }
1137
1138 /* 1069 /*
1139 * Helper function for creating Java column info object 1070 * Helper function for creating Java column info object
1140 */ 1071 */
1141 static jobject CreateColumnInfo(JNIEnv *pEnv, 1072 static jobject CreateColumnInfo(JNIEnv *pEnv,
1142 jclass *pClass, jmethodID *pConstructor, 1073 jclass *pClass, jmethodID *pConstructor,
1185 1116
1186 // Count columns 1117 // Count columns
1187 int colNum = -1; 1118 int colNum = -1;
1188 hr = S_OK; 1119 hr = S_OK;
1189 do{ 1120 do{
1190 hr = GetDetailsOfFolder(pIShellFolder2, NULL, ++colNum, &sd); 1121 hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd);
1191 } while (SUCCEEDED (hr)); 1122 } while (SUCCEEDED (hr));
1192 1123
1193 jobjectArray columns = 1124 jobjectArray columns =
1194 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1125 env->NewObjectArray((jsize) colNum, columnClass, NULL);
1195 if(NULL == columns) { 1126 if(NULL == columns) {
1200 // Fill column details list 1131 // Fill column details list
1201 SHCOLSTATEF csFlags; 1132 SHCOLSTATEF csFlags;
1202 colNum = 0; 1133 colNum = 0;
1203 hr = S_OK; 1134 hr = S_OK;
1204 while (SUCCEEDED (hr)) { 1135 while (SUCCEEDED (hr)) {
1205 hr = GetDetailsOfFolder(pIShellFolder2, NULL, colNum, &sd); 1136 hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd);
1206 1137
1207 if (SUCCEEDED (hr)) { 1138 if (SUCCEEDED (hr)) {
1208 hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags); 1139 hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags);
1209 if (SUCCEEDED (hr)) { 1140 if (SUCCEEDED (hr)) {
1210 if(!(csFlags & SHCOLSTATE_HIDDEN)) { 1141 if(!(csFlags & SHCOLSTATE_HIDDEN)) {
1230 1161
1231 // Count columns 1162 // Count columns
1232 int colNum = -1; 1163 int colNum = -1;
1233 hr = S_OK; 1164 hr = S_OK;
1234 do{ 1165 do{
1235 hr = GetDetailsOf(pIShellDetails, NULL, ++colNum, &sd); 1166 hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd);
1236 } while (SUCCEEDED (hr)); 1167 } while (SUCCEEDED (hr));
1237 1168
1238 jobjectArray columns = 1169 jobjectArray columns =
1239 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1170 env->NewObjectArray((jsize) colNum, columnClass, NULL);
1240 if(NULL == columns) { 1171 if(NULL == columns) {
1244 1175
1245 // Fill column details list 1176 // Fill column details list
1246 colNum = 0; 1177 colNum = 0;
1247 hr = S_OK; 1178 hr = S_OK;
1248 while (SUCCEEDED (hr)) { 1179 while (SUCCEEDED (hr)) {
1249 hr = GetDetailsOf(pIShellDetails, NULL, colNum, &sd); 1180 hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd);
1250 if (SUCCEEDED (hr)) { 1181 if (SUCCEEDED (hr)) {
1251 jobject column = CreateColumnInfo(env, 1182 jobject column = CreateColumnInfo(env,
1252 &columnClass, &columnConstructor, 1183 &columnClass, &columnConstructor,
1253 &sd, 1); 1184 &sd, 1);
1254 env->SetObjectArrayElement(columns, (jsize) colNum++, column); 1185 env->SetObjectArrayElement(columns, (jsize) colNum++, column);
1286 1217
1287 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); 1218 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown);
1288 if(SUCCEEDED (hr)) { 1219 if(SUCCEEDED (hr)) {
1289 // The folder exposes IShellFolder2 interface 1220 // The folder exposes IShellFolder2 interface
1290 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; 1221 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
1291 hr = GetDetailsOfFolder(pIShellFolder2, pidl, (UINT)columnIdx, &sd); 1222 hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
1292 pIShellFolder2->Release(); 1223 pIShellFolder2->Release();
1293 if (SUCCEEDED (hr)) { 1224 if (SUCCEEDED (hr)) {
1294 STRRET strRet = sd.str; 1225 STRRET strRet = sd.str;
1295 return jstringFromSTRRET(env, pidl, &strRet); 1226 return jstringFromSTRRET(env, pidl, &strRet);
1296 } 1227 }
1298 1229
1299 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); 1230 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown);
1300 if(SUCCEEDED (hr)) { 1231 if(SUCCEEDED (hr)) {
1301 // The folder exposes IShellDetails interface 1232 // The folder exposes IShellDetails interface
1302 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; 1233 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
1303 hr = GetDetailsOf(pIShellDetails, pidl, (UINT)columnIdx, &sd); 1234 hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
1304 pIShellDetails->Release(); 1235 pIShellDetails->Release();
1305 if (SUCCEEDED (hr)) { 1236 if (SUCCEEDED (hr)) {
1306 STRRET strRet = sd.str; 1237 STRRET strRet = sd.str;
1307 return jstringFromSTRRET(env, pidl, &strRet); 1238 return jstringFromSTRRET(env, pidl, &strRet);
1308 } 1239 }