From: <mie...@us...> - 2013-03-17 21:58:49
|
Revision: 9108 http://sourceforge.net/p/oorexx/code-0/9108 Author: miesfeld Date: 2013-03-17 21:58:47 +0000 (Sun, 17 Mar 2013) Log Message: ----------- Bugs: #1165 oleObject using click or submit methods fails in IE See ticket [Bugs:#537] Modified Paths: -------------- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c Modified: main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c =================================================================== --- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-03-16 21:31:04 UTC (rev 9107) +++ main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-03-17 21:58:47 UTC (rev 9108) @@ -1182,7 +1182,7 @@ } /** - * Try to get the dispatch id for a function / methd by name. + * Try to get the dispatch id for a function / method by name. * * @param pszFunction Function / method name * @param pDispatch Pointer to IDispatch, may not be null. @@ -1228,6 +1228,143 @@ } +/** + * Try to get the dispatch id for a function / method by name from a IDispatchEx + * interface. + * + * @param pszFunction Function / method name + * @param pDispatchEx Pointer to IDispatchEx, may not be null. + * @param pMemId [in/out] returned dispatch id, if found. + * @param wFlags [in/out] returned flags for the IDispatchEx::Invoke call. + * + * @return True if the dispatch ID was obtained, otherwise false. + * + * @note This an attempt to fix a problem when the IDispatchEx interface is + * available. In the old IBM code, when this happened, the invoke flags + * were set to 0, and if there were 0 arguments, the flags ended up + * getting set to DISPATCH_METHOD | DISPATCH_PROPERTYGET. When using + * IDispatchEx::Invoke, if the member was a method and not a property, the + * property get flag caused things to fail. At least for IE9. + * + * The code here is assuming IDispatchEx::GetMemberProperties works. But, + * it does not work when the IDipatchEx interfaces comes from IE9. + * + * On input wFlags may already contain DISPATCH_PROPERTYPUT, and perhaps + * in the future some other flags. We remove any existing flag that + * GetMemberProperties indicates is not supported. + * + * GetMemberProperties() always sets props to 0 for IE9, which pretty much + * causes things to not work for IE9. If we see that the flags are 0 and + * we have a pTypeInfo pointer, then we try to get the flags by searching + * the type library. + * + * This *does* work for the broken case of IE9, but who knows about some + * other case. The way the code is structured, if GetMemberProperties + * fails and there either is or is not a type info pointer, the code path + * exactly follows the old IBM code. + */ +static BOOL getDispatchIDByName(const char *pszFunction, IDispatch *pDispatch, IDispatchEx *pDispatchEx, ITypeInfo *pTypeInfo, + POLECLASSINFO pClsInfo, PPOLEFUNCINFO pFuncInfo, MEMBERID *pMemId, unsigned short *wFlags, + size_t argCount) +{ + LPOLESTR unicodeName = NULL; + HRESULT hr = E_FAIL; + BOOL gotID = FALSE; + + unicodeName = lpAnsiToUnicode(pszFunction, strlen(pszFunction) + 1); + if ( unicodeName == NULL ) + { + goto done_out; + } + + BSTR bstrName = SysAllocString(unicodeName); + if ( bstrName ) + { + MEMBERID id; + hr = pDispatchEx->GetDispID(bstrName, fdexNameCaseInsensitive, &id); + SysFreeString(bstrName); + + if ( FAILED(hr) ) + { + goto done_out; + } + + uint16_t flags = *wFlags; + DWORD which = grfdexPropCanAll | grfdexPropCannotAll; + DWORD props = 0; + + hr = pDispatchEx->GetMemberProperties(id, which, &props); + if ( FAILED(hr) ) + { + // This should not be possible. + goto done_out; + } + + if ( props & fdexPropCanGet ) flags |= DISPATCH_PROPERTYGET; + if ( props & fdexPropCanPut ) flags |= DISPATCH_PROPERTYPUT; + if ( props & fdexPropCanPutRef ) flags |= DISPATCH_PROPERTYPUTREF; + if ( props & fdexPropCanCall ) flags |= DISPATCH_METHOD; + if ( props & fdexPropCannotGet ) flags &= ~DISPATCH_PROPERTYGET; + if ( props & fdexPropCannotPut ) flags &= ~DISPATCH_PROPERTYPUT; + if ( props & fdexPropCannotPutRef ) flags &= ~DISPATCH_PROPERTYPUTREF; + if ( props & fdexPropCannotCall ) flags &= ~DISPATCH_METHOD; + + // If flags are 0, something is wrong ... but we just ignore this for now. + if ( flags == 0 && pTypeInfo ) + { + POLEFUNCINFO tempFuncInfo = NULL; + MEMBERID tempMemId = 0; + BOOL tempFound = FALSE; + + // We need to send NULL for the pDispatchEx arg for fFindFunction to + // actually have the function search the type library. We also want + // to discard the found return and any change to the DISPID that we + // found above. + tempFound = fFindFunction(pszFunction, pDispatch, NULL, pTypeInfo, pClsInfo, *wFlags, &tempFuncInfo, &tempMemId, argCount); + if ( tempFound && tempFuncInfo ) + { + *pFuncInfo = tempFuncInfo; + flags = tempFuncInfo->invkind; + } + } + + gotID = TRUE; + *pMemId = id; + *wFlags = flags; + } + +done_out: + if ( unicodeName != NULL ) + { + ORexxOleFree(unicodeName); + } + return gotID; +} + + +void printDispatchExNames(IDispatchEx *pDispatchEx) +{ + HRESULT hr; + BSTR bstrName; + DISPID dispid; + + // Assign to pDispatchEx + hr = pDispatchEx->GetNextDispID(fdexEnumAll, DISPID_STARTENUM, &dispid); + while ( hr == S_OK ) + { + hr = pDispatchEx->GetMemberName(dispid, &bstrName); + wprintf(L"%s\n", bstrName); + if (!wcscmp(bstrName, OLESTR("submit"))) + { + wprintf(L"%s id=%d\n", bstrName, dispid); + } + + SysFreeString(bstrName); + + hr = pDispatchEx->GetNextDispID(fdexEnumAll, dispid, &dispid); + } +} + BOOL fFindConstant(const char * pszConstName, POLECLASSINFO pClsInfo, PPOLECONSTINFO ppConstInfo ) { BOOL fFound = FALSE; @@ -3408,7 +3545,7 @@ getCachedClassInfo(context, &pClsInfo, &pTypeInfo); pszFunction = pszStringDupe(msgName); - if (!pszFunction) + if ( ! pszFunction ) { context->RaiseException0(Rexx_Error_System_resources); return NULLOBJECT; @@ -3422,10 +3559,16 @@ } hResult = pDispatch->QueryInterface(IID_IDispatchEx, (LPVOID*)&pDispatchEx); + if ( pDispatchEx != NULL ) + { + fFound = getDispatchIDByName(pszFunction, pDispatch, pDispatchEx, pTypeInfo, pClsInfo, &pFuncInfo, &MemId, &wFlags, iArgCount); + } + else + { + fFound = fFindFunction(pszFunction, pDispatch, pDispatchEx, pTypeInfo, + pClsInfo, wFlags, &pFuncInfo, &MemId, iArgCount); + } - fFound = fFindFunction(pszFunction, pDispatch, pDispatchEx, pTypeInfo, - pClsInfo, wFlags, &pFuncInfo, &MemId, iArgCount); - /* This change honors the function description better; before, the wFlag * (invocation kind) was determined by use, regardless of the description. * Now, if this is no direct PROPERTYPUT (format: "obj~function=") the @@ -3440,11 +3583,11 @@ // DISPATCH_XXX & INVOKE_XXX flags have the same values. wFlags = pFuncInfo->invkind; } - else + else if ( fFound ) { wFlags = DISPATCH_METHOD; - if (iArgCount == 0) + if ( iArgCount == 0 ) { /* this could be a property get or a dispatch method */ wFlags |= DISPATCH_PROPERTYGET; @@ -3472,28 +3615,6 @@ pClsInfo, wFlags, &pFuncInfo, &MemId, iArgCount); } - /* The below was used to allow setting a property by calling it like a - * method. This creates problems, because it might "shadow" a method with - * the same signature. Therefore it is disabled... - */ - /* - // call of PROPERTYPUT with braces: e.g. ~visible(.true) - if (fFound && pFuncInfo) - { - // are we sure this is a PROPERTYGET? - if (pFuncInfo->invkind == DISPATCH_PROPERTYGET) - { - // check if parameter list is valid. but how? - if (iArgCount > (pFuncInfo->iParmCount - pFuncInfo->iOptParms) ) - { - // oh, we must rethink our call: this must be a property put, and not a get!!! - wFlags = DISPATCH_PROPERTYPUT; - fFound = fFindFunction(pszFunction, pDispatch, pDispatchEx, pTypeInfo, pClsInfo, - wFlags, &pFuncInfo, &MemId); - } - } - } - */ // This memory is no longer needed. ORexxOleFree(pszFunction); @@ -3519,7 +3640,7 @@ } size_t i; - for (i = 0; i < iArgCount; i++) + for ( i = 0; i < iArgCount; i++ ) { /* arguments are filled in from the end of the array */ VariantInit(&(pVarArgs[iArgCount - i - 1])); @@ -3556,12 +3677,12 @@ /* if we have a property put then the new property value needs to be a named * argument */ - if (wFlags == DISPATCH_PROPERTYPUT) + if ( wFlags == DISPATCH_PROPERTYPUT ) { dp.cNamedArgs = 1; dp.rgdispidNamedArgs = &PropPutDispId; // without this check, property put is hardcoded to PROPERTYPUT... ...bad. - if (fFound && pFuncInfo) + if ( fFound && pFuncInfo ) { /* use the invkind the function description contains */ wFlags = pFuncInfo->invkind; // DISPATCH_... & INVOKE_... are the same (values 2,4,8) @@ -3583,20 +3704,20 @@ ZeroMemory(&sExc, sizeof(EXCEPINFO)); pResult = &sResult; - if (pTypeInfo && pFuncInfo) + if ( pTypeInfo && pFuncInfo ) { - if (pFuncInfo->FuncVt == VT_VOID) + if ( pFuncInfo->FuncVt == VT_VOID ) { pResult = NULL; /* function has no return code! */ } - if (pFuncInfo->invkind & INVOKE_PROPERTYGET) + if ( pFuncInfo->invkind & INVOKE_PROPERTYGET ) { wFlags |= DISPATCH_PROPERTYGET; /* this might be a property get */ } } - if (pDispatchEx) + if ( pDispatchEx ) { hResult = pDispatchEx->InvokeEx(MemId, LOCALE_USER_DEFAULT, wFlags, &dp, pResult, &sExc, NULL); @@ -3608,7 +3729,7 @@ } /* maybe this is a property get with arguments */ - if ((hResult == DISP_E_MEMBERNOTFOUND) && iArgCount) + if ( (hResult == DISP_E_MEMBERNOTFOUND) && iArgCount ) { hResult = pDispatch->Invoke(MemId, IID_NULL, LOCALE_USER_DEFAULT, wFlags | DISPATCH_PROPERTYGET, &dp, @@ -3616,7 +3737,7 @@ } /* if function has no return value, try again */ - if (hResult == DISP_E_MEMBERNOTFOUND) + if ( hResult == DISP_E_MEMBERNOTFOUND ) { hResult = pDispatch->Invoke(MemId, IID_NULL, LOCALE_USER_DEFAULT, wFlags, &dp, NULL, &sExc, &uArgErr); @@ -3624,7 +3745,7 @@ // needed for instance of tests variantClass = context->FindClass("OLEVARIANT"); - for (i = 0; i < dp.cArgs; i++) + for ( i = 0; i < dp.cArgs; i++ ) { arrItem = context->ArrayAt(msgArgs, i + 1); @@ -3635,7 +3756,7 @@ RexxObjectPtr outObject; RexxObjectPtr outArray = context->GetObjectVariable("!OUTARRAY"); - if (outArray == context->Nil()) + if ( outArray == context->Nil() ) { outArray = context->NewArray(1); context->SetObjectVariable("!OUTARRAY", outArray); @@ -3652,14 +3773,14 @@ // If the arg was ommitted (arrItem), it can not be an out // parameter, but to be safe, check for NULLOBJECT. - if (arrItem != NULLOBJECT && context->IsInstanceOf(arrItem, variantClass)) + if ( arrItem != NULLOBJECT && context->IsInstanceOf(arrItem, variantClass) ) { context->SendMessage1(arrItem, "!VARVALUE_=", outObject); } // if the call changed an out parameter, we have to clear the original variant that // was overwritten - if (memcmp(&pInputParameters[iArgCount - i - 1],&pVarArgs[iArgCount - i - 1],sizeof(VARIANT))) + if ( memcmp(&pInputParameters[iArgCount - i - 1], &pVarArgs[iArgCount - i - 1], sizeof(VARIANT)) ) { dereferenceVariant(&pInputParameters[iArgCount - i - 1]); handleVariantClear(context, &pInputParameters[iArgCount - i - 1], arrItem); @@ -3681,7 +3802,7 @@ } } - if (hResult == S_OK) + if ( hResult == S_OK ) { // If Variant2Rexx() raises an exception we drop through and catch the // clean up code and are okay here. |
From: <mie...@us...> - 2013-03-19 00:11:41
|
Revision: 9117 http://sourceforge.net/p/oorexx/code-0/9117 Author: miesfeld Date: 2013-03-19 00:11:36 +0000 (Tue, 19 Mar 2013) Log Message: ----------- Feature Requests: #537 Add FIle Open Dialog to allow more options than available with the FileNameDialog See ticket [Feature-requests:#537] Modified Paths: -------------- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c Modified: main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c =================================================================== --- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-03-18 13:33:21 UTC (rev 9116) +++ main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-03-19 00:11:36 UTC (rev 9117) @@ -3561,6 +3561,7 @@ hResult = pDispatch->QueryInterface(IID_IDispatchEx, (LPVOID*)&pDispatchEx); if ( pDispatchEx != NULL ) { + printf("Have IDispatchEx interface method=%s\n", pszFunction); fFound = getDispatchIDByName(pszFunction, pDispatch, pDispatchEx, pTypeInfo, pClsInfo, &pFuncInfo, &MemId, &wFlags, iArgCount); } else @@ -3575,9 +3576,9 @@ * invkind of the function description is used. If no function description * is available, we use our "best guess"... */ - if (wFlags == 0) + if ( wFlags == 0 ) { - if (fFound && pFuncInfo) + if ( fFound && pFuncInfo ) { // Use the invkind the function description contains. Note that the // DISPATCH_XXX & INVOKE_XXX flags have the same values. @@ -3607,10 +3608,18 @@ /* replace methods '[]' and 'at' with the method 'Item' if they */ /* could not be found */ - if (!fFound && (wFlags & DISPATCH_METHOD) && + if (!fFound && (wFlags == 0 || (wFlags & DISPATCH_METHOD)) && ((stricmp(pszFunction, "AT") == 0) || (stricmp(pszFunction, "[]") == 0)) ) { + if ( wFlags == 0 ) + { + wFlags = DISPATCH_METHOD; + if ( iArgCount == 0 ) + { + wFlags |= DISPATCH_PROPERTYGET; + } + } fFound = fFindFunction("Item", pDispatch, pDispatchEx, pTypeInfo, pClsInfo, wFlags, &pFuncInfo, &MemId, iArgCount); } |
From: <mie...@us...> - 2013-07-09 23:35:52
|
Revision: 9357 http://sourceforge.net/p/oorexx/code-0/9357 Author: miesfeld Date: 2013-07-09 23:35:50 +0000 (Tue, 09 Jul 2013) Log Message: ----------- #1188 OLE failure on 4.1.3 Modified Paths: -------------- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c Modified: main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c =================================================================== --- main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-07-08 23:51:48 UTC (rev 9356) +++ main/branches/4.1/trunk/extensions/platform/windows/ole/orexxole.c 2013-07-09 23:35:50 UTC (rev 9357) @@ -1296,20 +1296,29 @@ hr = pDispatchEx->GetMemberProperties(id, which, &props); if ( FAILED(hr) ) { - // This should not be possible. - goto done_out; + // This should not be possible, unless it is IE, which advertises + // things it doesn't support. + if ( hr != E_NOTIMPL ) + { + goto done_out; + } } - if ( props & fdexPropCanGet ) flags |= DISPATCH_PROPERTYGET; - if ( props & fdexPropCanPut ) flags |= DISPATCH_PROPERTYPUT; - if ( props & fdexPropCanPutRef ) flags |= DISPATCH_PROPERTYPUTREF; - if ( props & fdexPropCanCall ) flags |= DISPATCH_METHOD; - if ( props & fdexPropCannotGet ) flags &= ~DISPATCH_PROPERTYGET; - if ( props & fdexPropCannotPut ) flags &= ~DISPATCH_PROPERTYPUT; - if ( props & fdexPropCannotPutRef ) flags &= ~DISPATCH_PROPERTYPUTREF; - if ( props & fdexPropCannotCall ) flags &= ~DISPATCH_METHOD; + if ( props != 0 ) + { + if ( props & fdexPropCanGet ) flags |= DISPATCH_PROPERTYGET; + if ( props & fdexPropCanPut ) flags |= DISPATCH_PROPERTYPUT; + if ( props & fdexPropCanPutRef ) flags |= DISPATCH_PROPERTYPUTREF; + if ( props & fdexPropCanCall ) flags |= DISPATCH_METHOD; + if ( props & fdexPropCannotGet ) flags &= ~DISPATCH_PROPERTYGET; + if ( props & fdexPropCannotPut ) flags &= ~DISPATCH_PROPERTYPUT; + if ( props & fdexPropCannotPutRef ) flags &= ~DISPATCH_PROPERTYPUTREF; + if ( props & fdexPropCannotCall ) flags &= ~DISPATCH_METHOD; + } - // If flags are 0, something is wrong ... but we just ignore this for now. + // If flags are 0, something is wrong ... but with IE at least, + // GetMemberProperties() *never* works. In this case we try to fall + // back to using the type info. if ( flags == 0 && pTypeInfo ) { POLEFUNCINFO tempFuncInfo = NULL; |