diff --git a/c/jacob/ComThread.cpp b/c/jacob/ComThread.cpp new file mode 100644 index 0000000..36b4a35 --- /dev/null +++ b/c/jacob/ComThread.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include +#include "ComThread.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoInitialize + (JNIEnv *env, jclass cls, jint mode) +{ + int threadModel = mode; + CoInitializeEx(NULL, threadModel); +} + +JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoUninitialize + (JNIEnv *env, jclass cls) +{ + CoUninitialize(); +} + +} diff --git a/c/jacob/ComThread.h b/c/jacob/ComThread.h new file mode 100644 index 0000000..84a1980 --- /dev/null +++ b/c/jacob/ComThread.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class com_jacob_com_ComThread */ + +#ifndef _Included_com_jacob_com_ComThread +#define _Included_com_jacob_com_ComThread +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_jacob_com_ComThread + * Method: doCoInitialize + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoInitialize + (JNIEnv *, jclass, jint); + +/* + * Class: com_jacob_com_ComThread + * Method: doCoUninitialize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_ComThread_doCoUninitialize + (JNIEnv *, jclass); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/Dispatch.cpp b/c/jacob/Dispatch.cpp new file mode 100644 index 0000000..ff3a83d --- /dev/null +++ b/c/jacob/Dispatch.cpp @@ -0,0 +1,582 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include +#include "Dispatch.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +#define DISP_FLD "m_pDispatch" + +// extract a IDispatch from a jobject +IDispatch *extractDispatch(JNIEnv *env, jobject arg) +{ + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, DISP_FLD, "I"); + jint anum = env->GetIntField(arg, ajf); + IDispatch *v = (IDispatch *)anum; + return v; +} + +/** + * This method finds an interface rooted on the passed in dispatch object. + * This creates a new Dispatch object so it is NOT reliable + * in the event callback thread of a JWS client where the root class loader + * does not have com.jacob.com.Dispatch in its classpath + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_QueryInterface + (JNIEnv *env, jobject _this, jstring _iid) +{ + // get the current IDispatch + IDispatch *pIDispatch = extractDispatch(env, _this); + if (!pIDispatch) return NULL; + // if we used env->GetStringChars() would that let us drop the conversion? + const char *siid = env->GetStringUTFChars(_iid, NULL); + USES_CONVERSION; + LPOLESTR bsIID = A2W(siid); + env->ReleaseStringUTFChars(_iid, siid); + IID iid; + HRESULT hr = IIDFromString(bsIID, &iid); + if (FAILED(hr)) { + ThrowComFail(env, "Can't get IID from String", hr); + return NULL; + } + + // try to call QI on the passed IID + IDispatch *disp; + hr = pIDispatch->QueryInterface(iid, (void **)&disp); + if (FAILED(hr)) { + ThrowComFail(env, "QI on IID from String Failed", hr); + return NULL; + } + + jclass autoClass = env->FindClass("com/jacob/com/Dispatch"); + jmethodID autoCons = env->GetMethodID(autoClass, "", "(I)V"); + // construct a Dispatch object to return + // I am copying the pointer to java + // jacob-msg 1817 - SF 1053871 : QueryInterface already called AddRef!! + //if (disp) disp->AddRef(); + jobject newAuto = env->NewObject(autoClass, autoCons, disp); + return newAuto; +} + +/** + * starts up a new instance of the requested program (progId) + * and connects to it. does special code if the progid + * is of the alternate format (with ":") + **/ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_createInstanceNative + (JNIEnv *env, jobject _this, jstring _progid) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I"); + + // if we used env->GetStringChars() would that let us drop the conversion? + const char *progid = env->GetStringUTFChars(_progid, NULL); + CLSID clsid; + HRESULT hr; + IUnknown *punk = NULL; + IDispatch *pIDispatch; + USES_CONVERSION; + LPOLESTR bsProgId = A2W(progid); + if (strchr(progid,':')) + { + env->ReleaseStringUTFChars(_progid, progid); + // it's a moniker + hr = CoGetObject(bsProgId, NULL, IID_IUnknown, (LPVOID *)&punk); + if (FAILED(hr)) { + ThrowComFail(env, "Can't find moniker", hr); + return; + } + IClassFactory *pIClass; + // if it was a clsid moniker, I may have a class factory + hr = punk->QueryInterface(IID_IClassFactory, (void **)&pIClass); + if (!SUCCEEDED(hr)) goto doDisp; + punk->Release(); + // try to create an instance + hr = pIClass->CreateInstance(NULL, IID_IUnknown, (void **)&punk); + if (FAILED(hr)) { + ThrowComFail(env, "Can't create moniker class instance", hr); + return; + } + pIClass->Release(); + goto doDisp; + } + env->ReleaseStringUTFChars(_progid, progid); + // Now, try to find an IDispatch interface for progid + hr = CLSIDFromProgID(bsProgId, &clsid); + if (FAILED(hr)) { + ThrowComFail(env, "Can't get object clsid from progid", hr); + return; + } + // standard creation + hr = CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,IID_IUnknown, (void **)&punk); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't co-create object", hr); + return; + } +doDisp: + + // now get an IDispatch pointer from the IUnknown + hr = punk->QueryInterface(IID_IDispatch, (void **)&pIDispatch); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't QI object for IDispatch", hr); + return; + } + // CoCreateInstance called AddRef + punk->Release(); + env->SetIntField(_this, jf, (unsigned int)pIDispatch); +} + +/** + * attempts to connect to an running instance of the requested program + * This exists solely for the factory method connectToActiveInstance. + **/ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_getActiveInstanceNative + (JNIEnv *env, jobject _this, jstring _progid) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I"); + + // if we used env->GetStringChars() would that let us drop the conversion? + const char *progid = env->GetStringUTFChars(_progid, NULL); + CLSID clsid; + HRESULT hr; + IUnknown *punk = NULL; + IDispatch *pIDispatch; + USES_CONVERSION; + LPOLESTR bsProgId = A2W(progid); + env->ReleaseStringUTFChars(_progid, progid); + // Now, try to find an IDispatch interface for progid + hr = CLSIDFromProgID(bsProgId, &clsid); + if (FAILED(hr)) { + ThrowComFail(env, "Can't get object clsid from progid", hr); + return; + } + // standard connection + //printf("trying to connect to running %ls\n",bsProgId); + hr = GetActiveObject(clsid,NULL, &punk); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't get active object", hr); + return; + } + // now get an IDispatch pointer from the IUnknown + hr = punk->QueryInterface(IID_IDispatch, (void **)&pIDispatch); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't QI object for IDispatch", hr); + return; + } + // GetActiveObject called AddRef + punk->Release(); + env->SetIntField(_this, jf, (unsigned int)pIDispatch); +} + +/** + * starts up a new instance of the requested program (progId). + * This exists solely for the factory method connectToActiveInstance. + **/ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_coCreateInstanceNative + (JNIEnv *env, jobject _this, jstring _progid) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I"); + + // if we used env->GetStringChars() would that let us drop the conversion? + const char *progid = env->GetStringUTFChars(_progid, NULL); + CLSID clsid; + HRESULT hr; + IUnknown *punk = NULL; + IDispatch *pIDispatch; + USES_CONVERSION; + LPOLESTR bsProgId = A2W(progid); + env->ReleaseStringUTFChars(_progid, progid); + // Now, try to find an IDispatch interface for progid + hr = CLSIDFromProgID(bsProgId, &clsid); + if (FAILED(hr)) { + ThrowComFail(env, "Can't get object clsid from progid", hr); + return; + } + // standard creation + hr = CoCreateInstance(clsid,NULL,CLSCTX_LOCAL_SERVER|CLSCTX_INPROC_SERVER,IID_IUnknown, (void **)&punk); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't co-create object", hr); + return; + } + // now get an IDispatch pointer from the IUnknown + hr = punk->QueryInterface(IID_IDispatch, (void **)&pIDispatch); + if (!SUCCEEDED(hr)) { + ThrowComFail(env, "Can't QI object for IDispatch", hr); + return; + } + // CoCreateInstance called AddRef + punk->Release(); + env->SetIntField(_this, jf, (unsigned int)pIDispatch); +} + +/** + * release method + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_release + (JNIEnv *env, jobject _this) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID( clazz, DISP_FLD, "I"); + jint num = env->GetIntField(_this, jf); + + IDispatch *disp = (IDispatch *)num; + if (disp) { + disp->Release(); + env->SetIntField(_this, jf, (unsigned int)0); + } +} + +static HRESULT +name2ID(IDispatch *pIDispatch, const char *prop, DISPID *dispid, long lcid) +{ + HRESULT hresult; + USES_CONVERSION; + LPOLESTR propOle = A2W(prop); + hresult = pIDispatch->GetIDsOfNames(IID_NULL,(LPOLESTR*)&propOle,1,lcid,dispid); + return hresult; +} + +JNIEXPORT jintArray JNICALL Java_com_jacob_com_Dispatch_getIDsOfNames + (JNIEnv *env, jclass clazz, jobject disp, jint lcid, jobjectArray names) +{ + IDispatch *pIDispatch = extractDispatch(env, disp); + if (!pIDispatch) return NULL; + + int l = env->GetArrayLength(names); + int i; + LPOLESTR *lps = (LPOLESTR *)CoTaskMemAlloc(l * sizeof(LPOLESTR)); + DISPID *dispid = (DISPID *)CoTaskMemAlloc(l * sizeof(DISPID)); + for(i=0;iGetObjectArrayElement(names, i); + // if we used env->GetStringChars() would that let us drop the conversion? + const char *nm = env->GetStringUTFChars(s, NULL); + LPOLESTR nmos = A2W(nm); + env->ReleaseStringUTFChars(s, nm); + lps[i] = nmos; + env->DeleteLocalRef(s); + } + HRESULT hr = pIDispatch->GetIDsOfNames(IID_NULL,lps,l,lcid,dispid); + if (FAILED(hr)) { + CoTaskMemFree(lps); + CoTaskMemFree(dispid); + char buf[1024]; + strcpy_s(buf, "Can't map names to dispid:"); + for(i=0;iGetObjectArrayElement(names, i); + const char *nm = env->GetStringUTFChars(s, NULL); + strcat_s(buf, nm); + env->ReleaseStringUTFChars(s, nm); + env->DeleteLocalRef(s); + } + ThrowComFail(env, buf, hr); + return NULL; + } + jintArray iarr = env->NewIntArray(l); + // SF 1511033 -- the 2nd parameter should be 0 and not i! + env->SetIntArrayRegion(iarr, 0, l, dispid); + CoTaskMemFree(lps); + CoTaskMemFree(dispid); + return iarr; +} + +static char* BasicToCharString(const BSTR inBasicString) +{ + char* charString = NULL; + const size_t charStrSize = ::SysStringLen(inBasicString) + 1; + if (charStrSize > 1) + { + charString = new char[charStrSize]; + size_t convertedSize; + ::wcstombs_s(&convertedSize, charString, charStrSize, inBasicString, charStrSize); + } + else + { + charString = ::_strdup(""); + } + return charString; +} + +static wchar_t* CreateErrorMsgFromResult(HRESULT inResult) +{ + wchar_t* msg = NULL; + ::FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM, NULL, inResult,MAKELANGID(LANG_NEUTRAL, + SUBLANG_DEFAULT), (LPWSTR) &msg, 0, NULL); + if (msg == NULL) + { + const wchar_t* message_text = L"An unknown COM error has occured."; + size_t bufferLength = (wcslen(message_text) + 1) * sizeof(wchar_t); + msg = (wchar_t*) ::LocalAlloc(LPTR, bufferLength); + wcscpy_s(msg, bufferLength, message_text); + } + + return msg; +} + +static wchar_t* CreateErrorMsgFromInfo(HRESULT inResult, EXCEPINFO* ioInfo, + const char* methName) +{ + wchar_t* msg = NULL; + size_t methNameWSize = 0; + + mbstowcs_s(&methNameWSize, NULL, 0, methName, _TRUNCATE); + + wchar_t* methNameW = new wchar_t[methNameWSize]; + + mbstowcs_s(NULL, methNameW, methNameWSize, methName, _TRUNCATE); + + // If this is a dispatch exception (triggered by an Invoke message), + // then we have to take some additional steps to process the error + // message. + if (inResult == DISP_E_EXCEPTION) + { + // Check to see if the server deferred filling in the exception + // information. If so, make the call to populate the structure. + if (ioInfo->pfnDeferredFillIn != NULL) + (*(ioInfo->pfnDeferredFillIn))(ioInfo); + + // Build the error message from exception information content. + int sourceLen = SysStringLen(ioInfo->bstrSource); + int descLen = SysStringLen(ioInfo->bstrDescription); + const size_t MSG_LEN = ::wcslen(methNameW) + sourceLen + descLen + 128; + msg = new wchar_t[MSG_LEN]; + ::wcsncpy_s(msg, MSG_LEN, L"Invoke of: ", wcslen(L"Invoke of: ")); + ::wcsncat_s(msg, MSG_LEN, methNameW, wcslen(methNameW)); + ::wcsncat_s(msg, MSG_LEN, L"\nSource: ", wcslen(L"\nSource: ")); + ::wcsncat_s(msg, MSG_LEN, ioInfo->bstrSource, sourceLen); + ::wcsncat_s(msg, MSG_LEN, L"\nDescription: ", wcslen(L"\nDescription: ")); + ::wcsncat_s(msg, MSG_LEN, ioInfo->bstrDescription, descLen); + ::wcsncat_s(msg, MSG_LEN, L"\n", wcslen(L"\n")); + } + else + { + wchar_t* msg2 = CreateErrorMsgFromResult(inResult); + const size_t MSG_LEN = ::wcslen(methNameW) + ::wcslen(msg2) + 256; + msg = new wchar_t[MSG_LEN]; + ::wcsncpy_s(msg, MSG_LEN, + L"A COM exception has been encountered:\nAt Invoke of: ", + wcslen(L"A COM exception has been encountered:\nAt Invoke of: ")); + ::wcsncat_s(msg, MSG_LEN, methNameW, wcslen(methNameW)); + ::wcsncat_s(msg, MSG_LEN, L"\nDescription: ", wcslen(L"\nDescription: ")); + ::wcsncat_s(msg, MSG_LEN, msg2, wcslen(msg2)); + // jacob-msg 1075 - SF 1053872 : Documentation says "use LocalFree"!! + //delete msg2; + LocalFree(msg2); + } + delete methNameW; + return msg; +} + + +#define SETDISPPARAMS(dp, numArgs, pvArgs, numNamed, pNamed) \ + {\ + (dp).cArgs = numArgs; \ + (dp).rgvarg = pvArgs; \ + (dp).cNamedArgs = numNamed; \ + (dp).rgdispidNamedArgs = pNamed; \ + } + +#define SETNOPARAMS(dp) SETDISPPARAMS(dp, 0, NULL, 0, NULL) + +JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev + (JNIEnv *env, jclass clazz, + jobject disp, jstring name, jint dispid, + jint lcid, jint wFlags, jobjectArray vArg, jintArray uArgErr) +{ + DISPPARAMS dispparams; + EXCEPINFO excepInfo; + // Sourceforge Bug Tracker 2935662 uninitialized data can be not NULL with bad results + excepInfo.pfnDeferredFillIn = NULL; + + IDispatch *pIDispatch = extractDispatch(env, disp); + if (!pIDispatch) return NULL; + + int dispID = dispid; + if (name != NULL) + { + const char *nm = env->GetStringUTFChars(name, NULL); + HRESULT hr; + if (FAILED(hr = name2ID(pIDispatch, nm, (long *)&dispID, lcid))) { + char buf[1024]; + sprintf_s(buf, 1024, "Can't map name to dispid: %s", nm); + ThrowComFail(env, buf, -1); + return NULL; + } + env->ReleaseStringUTFChars(name, nm); + } + + int num_args = env->GetArrayLength(vArg); + int i, j; + VARIANT *varr = NULL; + if (num_args) + { + varr = (VARIANT *)CoTaskMemAlloc(num_args*sizeof(VARIANT)); + /* reverse args for dispatch */ + for(i=num_args-1,j=0;0<=i;i--,j++) + { + VariantInit(&varr[j]); + jobject arg = env->GetObjectArrayElement(vArg, i); + VARIANT *v = extractVariant(env, arg); + // no escape from copy? + VariantCopy(&varr[j], v); + env->DeleteLocalRef(arg); + } + } + // prepare a new return value + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID variantCons = + env->GetMethodID(variantClass, "", "()V"); + // construct a variant to return + jobject newVariant = env->NewObject(variantClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + DISPID dispidPropertyPut = DISPID_PROPERTYPUT; + + // determine how to dispatch + switch (wFlags) + { + case DISPATCH_PROPERTYGET: // GET + case DISPATCH_METHOD: // METHOD + case DISPATCH_METHOD|DISPATCH_PROPERTYGET: + { + SETDISPPARAMS(dispparams, num_args, varr, 0, NULL); + break; + } + case DISPATCH_PROPERTYPUT: + case DISPATCH_PROPERTYPUTREF: // jacob-msg 1075 - SF 1053872 + { + SETDISPPARAMS(dispparams, num_args, varr, 1, &dispidPropertyPut); + break; + } + } + + HRESULT hr = 0; + jint count = env->GetArrayLength(uArgErr); + if ( count != 0 ) + { + jint *uAE = env->GetIntArrayElements(uArgErr, NULL); + hr = pIDispatch->Invoke(dispID,IID_NULL, + lcid,(WORD)wFlags,&dispparams,v,&excepInfo,(unsigned int *)uAE); // SF 1689061 + env->ReleaseIntArrayElements(uArgErr, uAE, 0); + } + else + { + hr = pIDispatch->Invoke(dispID,IID_NULL, + lcid,(WORD)wFlags,&dispparams,v,&excepInfo, NULL); // SF 1689061 + } + if (num_args) + { + // to account for inouts, I need to copy the inputs back to + // the java array after the method returns + // this occurs, for example, in the ADO wrappers + for(i=num_args-1,j=0;0<=i;i--,j++) + { + jobject arg = env->GetObjectArrayElement(vArg, i); + VARIANT *v = extractVariant(env, arg); + // reverse copy + VariantCopy(v, &varr[j]); + // clear out the temporary variant + VariantClear(&varr[j]); + env->DeleteLocalRef(arg); + } + } + + if (varr) CoTaskMemFree(varr); + + // check for error and display a somewhat verbose error message + if (!SUCCEEDED(hr)) { + // two buffers that may have to be freed later + wchar_t *buf = NULL; + char *dispIdAsName = NULL; + // this method can get called with a name or a dispatch id + // we need to handle both SF 1114159 + if (name != NULL){ + const char *nm = env->GetStringUTFChars(name, NULL); + buf = CreateErrorMsgFromInfo(hr, &excepInfo, nm); + env->ReleaseStringUTFChars(name, nm); + } else { + dispIdAsName = new char[256]; + // get the id string + _itoa_s (dispID, dispIdAsName, 256,10); + //continue on mostly as before + buf = CreateErrorMsgFromInfo(hr,&excepInfo,dispIdAsName); + } + + // jacob-msg 3696 - SF 1053866 + if(hr == DISP_E_EXCEPTION) + { + if(excepInfo.scode != 0) + { + hr = excepInfo.scode; + } + else + { + hr = _com_error::WCodeToHRESULT(excepInfo.wCode); + } + } + + ThrowComFailUnicode(env, buf, hr); + if (buf) delete buf; + if (dispIdAsName) delete dispIdAsName; + return NULL; + } + + return newVariant; +} + +/* + * Wait method added so folks could wait until a com server terminated + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Dispatch_hasExited + (JNIEnv *env,jclass clazz, jobject disp, jint dispid, jint lcid) { + IDispatch *pIDispatch = extractDispatch(env, disp); + if (!pIDispatch) { + // should we return 0? + return NULL; + } + ITypeInfo *v; + HRESULT hr = pIDispatch->GetTypeInfo(dispid, lcid, &v); + if (hr == RPC_E_SERVERCALL_RETRYLATER || hr == RPC_E_CALL_REJECTED || hr + == 0) { + return 0; + } else { + return 1; + } +} + +} + + diff --git a/c/jacob/Dispatch.h b/c/jacob/Dispatch.h new file mode 100644 index 0000000..d8cda4e --- /dev/null +++ b/c/jacob/Dispatch.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class Dispatch */ + +#ifndef _Included_Dispatch +#define _Included_Dispatch +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_jacob_com_Dispatch + * Method: QueryInterface + * Signature: (Ljava/lang/String;)Lcom/jacob/com/Dispatch; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_QueryInterface + (JNIEnv *, jobject, jstring); + +/* + * Class: Dispatch + * Method: createInstance + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_createInstanceNative + (JNIEnv *, jobject, jstring); + +/* + * Class: Dispatch + * Method: getActiveInstance + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_getActiveInstanceNative + (JNIEnv *, jobject, jstring); + +/* + * Class: Dispatch + * Method: coCreateInstance + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_coCreateInstanceNative + (JNIEnv *, jobject, jstring); + +/* + * Class: Dispatch + * Method: release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Dispatch_release + (JNIEnv *, jobject); + +/* + * Class: Dispatch + * Method: getIDsOfNames + * Signature: (Ljava/lang/Object;I[Ljava/lang/String;)[I + */ +JNIEXPORT jintArray JNICALL Java_com_jacob_com_Dispatch_getIDsOfNames + (JNIEnv *, jclass, jobject, jint, jobjectArray); + +/* + * Class: Dispatch + * Method: invokev + * Signature: (Ljava/lang/Object;Ljava/lang/String;III[LVariant;[I)LVariant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev + (JNIEnv *, jclass, jobject, jstring, jint, jint, jint, jobjectArray, jintArray); + +/* + * Class: Dispatch + * Method: wait + * Signature: (Ljava/lang/Object;I;)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Dispatch_hasExited + (JNIEnv *, jclass, jobject, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/DispatchEvents.cpp b/c/jacob/DispatchEvents.cpp new file mode 100644 index 0000000..3428749 --- /dev/null +++ b/c/jacob/DispatchEvents.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "DispatchEvents.h" +#include "EventProxy.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include + +#include "util.h" + +extern "C" +{ + +#define PROXY_FLD "m_pConnPtProxy" + +// defined below +BOOL GetEventIID(IUnknown*, IID*, CComBSTR **, DISPID **, int *,LPOLESTR); +BOOL GetEventIIDForTypeLib(BSTR, IID*, CComBSTR **, DISPID **, int *,LPOLESTR); +BOOL getClassInfoFromProgId(LPOLESTR bsProgId,LPTYPEINFO *pClassInfo); +BOOL MapEventIIDs(IID*, CComBSTR **, DISPID **, int *, LPOLESTR , LPTYPEINFO ); + +// extract a EventProxy* from a jobject +EventProxy *extractProxy(JNIEnv *env, jobject arg) +{ + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, PROXY_FLD, "I"); + jint anum = env->GetIntField(arg, ajf); + EventProxy *v = (EventProxy *)anum; + return v; +} + +/* + * pushes the EventProxy (*ep) into tje jobject in the PROXY_FLD location + */ +void putProxy(JNIEnv *env, jobject arg, EventProxy *ep) +{ + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, PROXY_FLD, "I"); + jint anum = env->GetIntField(arg, ajf); + env->SetIntField(arg, ajf, (jint)ep); +} + + +/* + * Class: com_jacob_com_DispatchEvents + * Method: init3 + * Signature: (Lcom/jacob/com/Dispatch;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init3 + (JNIEnv *env, + jobject _this, jobject src, + jobject sink, + jstring _progid, + jstring _typelib) +{ + USES_CONVERSION; + + if (_typelib != NULL && _progid == NULL){ + // both are required if typelib exists + ThrowComFail(env,"TypeLib was specified but no program id was",-1); + return; + } + + BSTR typeLib = NULL; + if (_typelib != NULL){ + // why is this UTF instead of unicode? Then we could probably drop the A2W + const char *typelib = env->GetStringUTFChars(_typelib, NULL); + typeLib = A2W(typelib); + // should we call env->ReleaseStringUTFChars(,) to free the memory like we do everywhere lese? + + //printf("we have a type lib %ls\n",typeLib); + } + + // find progid if any + LPOLESTR bsProgId = NULL; + if (_progid!=NULL) { + // why is this UTF instead of unicode? Then we could probably drop the A2W + const char *progid = env->GetStringUTFChars(_progid, NULL); + bsProgId = A2W(progid); + // should we call env->ReleaseStringUTFChars(,) to free the memory like we do everywhere lese? + //printf("we have an applicaton %ls\n",bsProgId); + } + + // get the IDispatch for the source object + IDispatch *pDisp = extractDispatch(env, src); + CComQIPtr pUnk(pDisp); + // see if it implements connection points + CComQIPtr pCPC(pUnk); + if (!pCPC) + { + // no events, throw something + ThrowComFail(env, "Can't find IConnectionPointContainer", -1); + return; + } + + IID eventIID; + CComBSTR *mNames; + DISPID *mIDs; + int n_EventMethods; + if (_typelib == NULL){ + if (!GetEventIID(pUnk, &eventIID, &mNames, &mIDs, &n_EventMethods,bsProgId)) { + ThrowComFail(env, "Can't find event iid", -1); + return; + } + } else { + if (!GetEventIIDForTypeLib(typeLib, &eventIID, &mNames, &mIDs, &n_EventMethods,bsProgId)) { + ThrowComFail(env, "Can't find event iid for type lib", -1); + return; + } + } + + // hook up to the default source iid + CComPtr pCP; + HRESULT hr = pCPC->FindConnectionPoint(eventIID, &pCP); + if (SUCCEEDED(hr)) + { + EventProxy *ep = new EventProxy(env, sink, pCP, eventIID, mNames, mIDs, n_EventMethods); + // need to store ep on _this, in case it gets collected + putProxy(env, _this, ep); + } else { + ThrowComFail(env, "Can't FindConnectionPoint", hr); + } +} + +/* + * Class: DispatchEvents + * Method: release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_release + (JNIEnv *env, jobject _this) +{ + EventProxy *ep = extractProxy(env, _this); + if (ep) { + // this is the line that blows up in IETest + ep->Release(); + putProxy(env, _this, NULL); + } +} + +/* + * I need a reverse map from the event interface's dispids to + * function names so that we can reflect them to java + */ +void +LoadNameCache(LPTYPEINFO pTypeInfo, LPTYPEATTR pta, + CComBSTR **mNames, DISPID **mIDs, int *nmeth) +{ + CComBSTR *names = NULL; + DISPID *ids = NULL; + int m_nCount; + + m_nCount = pta->cFuncs; + *nmeth = m_nCount; + names = m_nCount == 0 ? NULL : new CComBSTR[m_nCount]; + ids = m_nCount == 0 ? NULL : new DISPID[m_nCount]; + for (int i=0; iGetFuncDesc(i, &pfd))) + { + CComBSTR bstrName; + if (SUCCEEDED(pTypeInfo->GetDocumentation(pfd->memid, &bstrName, NULL, NULL, NULL))) + { + names[i].Attach(bstrName.Detach()); + ids[i] = pfd->memid; + /* + USES_CONVERSION; + printf("map:%d -> %s\n", ids[i], W2A((OLECHAR *)names[i])); + */ + } + pTypeInfo->ReleaseFuncDesc(pfd); + } + } + *mNames = names; + *mIDs = ids; +} + +#define IMPLTYPE_MASK \ + (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE | IMPLTYPEFLAG_FRESTRICTED) + +#define IMPLTYPE_DEFAULTSOURCE \ + (IMPLTYPEFLAG_FDEFAULT | IMPLTYPEFLAG_FSOURCE) + +BOOL GetEventIID(IUnknown *m_pObject, IID* piid, + CComBSTR **mNames, DISPID **mIDs, int *nmeth,LPOLESTR bsProgId) +{ + *piid = GUID_NULL; + ATLASSERT(m_pObject != NULL); + // I Always use IProvideClassInfo rather than IProvideClassInfo2 + // since I also need to create a mapping from dispid to name + LPPROVIDECLASSINFO pPCI = NULL; + LPTYPEINFO pClassInfo = NULL; + if (SUCCEEDED(m_pObject->QueryInterface(IID_IProvideClassInfo, (LPVOID*)&pPCI))) + { + //printf("got IProvideClassInfo\n"); + ATLASSERT(pPCI != NULL); + HRESULT hr = pPCI->GetClassInfo(&pClassInfo); + pPCI->Release(); + if (!SUCCEEDED(hr)) return false; + } + else if (getClassInfoFromProgId(bsProgId,&pClassInfo)) { + } + else { + printf("GetEventIID: couldn't get IProvideClassInfo\n"); + return false; + } + + return MapEventIIDs(piid, mNames, mIDs, nmeth, bsProgId, pClassInfo); +} + +BOOL MapEventIIDs(IID* piid, + CComBSTR **mNames, DISPID **mIDs, int *nmeth, LPOLESTR bsProgId, LPTYPEINFO pClassInfo) +{ + ATLASSERT(pClassInfo != NULL); + //printf("MapEventIIDs: got past ClassInfo assert\n"); + LPTYPEATTR pClassAttr; + if (SUCCEEDED(pClassInfo->GetTypeAttr(&pClassAttr))) + { + //printf("MapEventIIDs: got TypeAttr\n"); + ATLASSERT(pClassAttr != NULL); + ATLASSERT(pClassAttr->typekind == TKIND_COCLASS); + + // Search for typeinfo of the default events interface. + int nFlags; + HREFTYPE hRefType; + + //printf("MapEventIIDs: looking at %d class attribute impl types \n"); + for (unsigned int i = 0; i < pClassAttr->cImplTypes; i++) + { + if (SUCCEEDED(pClassInfo->GetImplTypeFlags(i, &nFlags)) && + ((nFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE)) + { + // Found it. Now look at its attributes to get IID. + LPTYPEINFO pEventInfo = NULL; + if (SUCCEEDED(pClassInfo->GetRefTypeOfImplType(i, + &hRefType)) && + SUCCEEDED(pClassInfo->GetRefTypeInfo(hRefType, + &pEventInfo))) + { + ATLASSERT(pEventInfo != NULL); + LPTYPEATTR pEventAttr; + if (SUCCEEDED(pEventInfo->GetTypeAttr(&pEventAttr))) + { + ATLASSERT(pEventAttr != NULL); + + // create a mapping from dispid to string + LoadNameCache(pEventInfo, pEventAttr, + mNames, mIDs, nmeth); + + *piid = pEventAttr->guid; + pEventInfo->ReleaseTypeAttr(pEventAttr); + } + pEventInfo->Release(); + } + break; + } + } + pClassInfo->ReleaseTypeAttr(pClassAttr); + } + pClassInfo->Release(); + + return (!IsEqualIID(*piid, GUID_NULL)); +} + +BOOL getClassInfoFromProgId(LPOLESTR bsProgId,LPTYPEINFO *pClassInfo) +{ + USES_CONVERSION; + CLSID clsid; + GUID libid; + if (FAILED(CLSIDFromProgID(bsProgId, &clsid))) return false; + if (FAILED(StringFromCLSID(clsid,&bsProgId))) return false; + HKEY keySoftware, keyClasses, keyCLSID, keyXXXX, keyTypeLib; + DWORD dwType, dwCountData=50; + BYTE abData[50]; + LONG lVal; + lVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE"),0,KEY_READ,&keySoftware); + if (lVal==ERROR_SUCCESS) { + lVal = RegOpenKeyEx(keySoftware,_T("Classes"),0,KEY_READ,&keyClasses); + if (lVal==ERROR_SUCCESS) { + lVal = RegOpenKeyEx(keyClasses,_T("CLSID"),0,KEY_READ,&keyCLSID); + if (lVal==ERROR_SUCCESS) { + _TCHAR *tsProgId = W2T(bsProgId); + lVal = RegOpenKeyEx(keyCLSID,tsProgId,0,KEY_READ,&keyXXXX); + if (lVal==ERROR_SUCCESS) { + lVal = RegOpenKeyEx(keyXXXX,_T("TypeLib"),0,KEY_READ,&keyTypeLib); + if (lVal==ERROR_SUCCESS) { + lVal = RegQueryValueExA(keyTypeLib,NULL,NULL,&dwType,abData,&dwCountData); + RegCloseKey(keyTypeLib); + } + RegCloseKey(keyXXXX); + } + RegCloseKey(keyCLSID); + } + RegCloseKey(keyClasses); + } + RegCloseKey(keySoftware); + } + if (lVal!=ERROR_SUCCESS) return false; + BSTR bsLibId = A2BSTR((char*)abData); + if (FAILED(CLSIDFromString(bsLibId,&libid))) return false; + //Try loading from registry information. + ITypeLib* pITypeLib; + if (FAILED(LoadRegTypeLib(libid,1,0, LANG_NEUTRAL, &pITypeLib))) return false; + //Find ITypeInfo for coclass. + pITypeLib->GetTypeInfoOfGuid(clsid, pClassInfo); + pITypeLib->Release(); + return true; +} + +/* + * Get the class info from the progId using the given typeLib. + */ +BOOL getClassInfoFromProgIdTypeLib(BSTR typeLib, LPOLESTR bsProgId, LPTYPEINFO *pClassInfo) +{ + USES_CONVERSION; + CLSID clsid; + + if (FAILED(CLSIDFromProgID(bsProgId, &clsid))) return false; + if (FAILED(StringFromCLSID(clsid,&bsProgId))) return false; + + ITypeLib* pITypeLib; + if (FAILED(LoadTypeLib(typeLib, &pITypeLib))) return false; + + //Find ITypeInfo for coclass. + pITypeLib->GetTypeInfoOfGuid(clsid, pClassInfo); + pITypeLib->Release(); + return true; +} + +BOOL GetEventIIDForTypeLib(BSTR typeLib, IID* piid, + CComBSTR **mNames, DISPID **mIDs, int *nmeth,LPOLESTR bsProgId) +{ + LPTYPEINFO pClassInfo = NULL; + if(getClassInfoFromProgIdTypeLib(typeLib, bsProgId,&pClassInfo)) + { + if (pClassInfo == NULL){ + printf("we had a successful return but pClassInfo is null\n"); + } + return MapEventIIDs(piid, mNames, mIDs, nmeth, bsProgId, pClassInfo); + } + else + { + printf("GetEventIIDForTypeLib: couldn't get IProvideClassInfo\n"); + return false; + } +} + +} diff --git a/c/jacob/DispatchEvents.h b/c/jacob/DispatchEvents.h new file mode 100644 index 0000000..82289ec --- /dev/null +++ b/c/jacob/DispatchEvents.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class DispatchEvents */ + +#ifndef _Included_DispatchEvents +#define _Included_DispatchEvents +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: com_jacob_com_DispatchEvents + * Method: init3 + * Signature: (Lcom/jacob/com/Dispatch;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init3 + (JNIEnv *, jobject, jobject, jobject, jstring, jstring); + +/* + * Class: DispatchEvents + * Method: release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_release + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif + + diff --git a/c/jacob/DispatchProxy.cpp b/c/jacob/DispatchProxy.cpp new file mode 100644 index 0000000..eb2dd46 --- /dev/null +++ b/c/jacob/DispatchProxy.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include +#include "ComThread.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +// extract a IStream from a jobject +IStream *extractStream(JNIEnv *env, jobject arg) +{ + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I"); + jint anum = env->GetIntField(arg, ajf); + IStream *v = (IStream *)anum; + return v; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_MarshalIntoStream + (JNIEnv *env, jobject _this, jobject disp) +{ + IDispatch *pIDispatch = extractDispatch(env, disp); + if (!pIDispatch) return; + IStream *ps; // this is the stream we will marshall into + HRESULT hr = CoMarshalInterThreadInterfaceInStream( + IID_IDispatch, pIDispatch, &ps); + if (!SUCCEEDED(hr)) + { + ThrowComFail(env, "Could not Marshal Dispatch into IStream", hr); + return; + } + // store the stream pointer on the object + jclass argClass = env->GetObjectClass(_this); + jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I"); + env->SetIntField(_this, ajf, (jint)ps); +} + +JNIEXPORT jobject JNICALL Java_com_jacob_com_DispatchProxy_MarshalFromStream + (JNIEnv *env, jobject _this) +{ + IStream *ps = extractStream(env, _this); + if (!ps) + { + ThrowComFail(env, "Could not get IStream from DispatchProxy", -1); + return NULL; + } + IDispatch *pD; + HRESULT hr = CoGetInterfaceAndReleaseStream(ps, IID_IDispatch, (void **)&pD); + // zero out the stream pointer on the object + // since the stream can only be read once + jclass argClass = env->GetObjectClass(_this); + jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I"); + env->SetIntField(_this, ajf, (unsigned int)0); + + if (!SUCCEEDED(hr)) + { + ThrowComFail(env, "Could not Marshal Dispatch from IStream", hr); + return NULL; + } + jclass autoClass = env->FindClass("com/jacob/com/Dispatch"); + jmethodID autoCons = env->GetMethodID(autoClass, "", "(I)V"); + // construct a Dispatch object to return + // I am copying the pointer to java + if (pD) pD->AddRef(); + jobject newAuto = env->NewObject(autoClass, autoCons, pD); + return newAuto; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_release + (JNIEnv *env, jobject _this) +{ + IStream *ps = extractStream(env, _this); + if (ps) { + ps->Release(); + jclass argClass = env->GetObjectClass(_this); + jfieldID ajf = env->GetFieldID( argClass, "m_pStream", "I"); + env->SetIntField(_this, ajf, (unsigned int)0); + } +} + +} diff --git a/c/jacob/DispatchProxy.h b/c/jacob/DispatchProxy.h new file mode 100644 index 0000000..aeabf43 --- /dev/null +++ b/c/jacob/DispatchProxy.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class com_jacob_com_DispatchProxy */ + +#ifndef _Included_com_jacob_com_DispatchProxy +#define _Included_com_jacob_com_DispatchProxy +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_jacob_com_DispatchProxy + * Method: MarshalIntoStream + * Signature: (Lcom/jacob/com/Dispatch;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_MarshalIntoStream + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_DispatchProxy + * Method: MarshalFromStream + * Signature: ()Lcom/jacob/com/Dispatch; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_DispatchProxy_MarshalFromStream + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_DispatchProxy + * Method: release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_DispatchProxy_release + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/EnumVariant.cpp b/c/jacob/EnumVariant.cpp new file mode 100644 index 0000000..7ff9727 --- /dev/null +++ b/c/jacob/EnumVariant.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include +#include "Dispatch.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include "util.h" + +/** + * An implementation of IEnumVariant based on code submitted by + * Thomas Hallgren (mailto:Thomas.Hallgren@eoncompany.com) + */ +extern "C" +{ + +// extract a IDispatch from a jobject +IEnumVARIANT* extractEnumVariant(JNIEnv* env, jobject arg) +{ + jfieldID FID_pIEnumVARIANT = 0; + jclass clazz = env->GetObjectClass(arg); + FID_pIEnumVARIANT = env->GetFieldID(clazz, "m_pIEnumVARIANT", "I"); + return (IEnumVARIANT*)env->GetIntField(arg, FID_pIEnumVARIANT); +} + +JNIEXPORT jint JNICALL +Java_com_jacob_com_EnumVariant_Next(JNIEnv* env, jobject _this, jobjectArray vars) +{ + IEnumVARIANT* self = extractEnumVariant(env, _this); + //printf("self=%x\n", self); + if(self == NULL) + return 0; + + ULONG count = (ULONG)env->GetArrayLength(vars); + if(count == 0) + return 0; + + VARIANT* sink = (VARIANT*)CoTaskMemAlloc(count * sizeof(VARIANT)); + ULONG fetchCount = 0; + + HRESULT hr = self->Next(count, sink, &fetchCount); + if(FAILED(hr)) + { + CoTaskMemFree(sink); + ThrowComFail(env, "IEnumVARIANT::Next", hr); + return 0; + } + + // prepare a new return value array + // + jclass clazz = env->FindClass("com/jacob/com/Variant"); + jmethodID ctor = env->GetMethodID(clazz, "", "()V"); + + for(ULONG idx = 0; idx < fetchCount; ++idx) + { + // construct a variant to return + // + jobject newVariant = env->NewObject(clazz, ctor); + VARIANT* v = extractVariant(env, newVariant); + VariantCopy(v, sink + idx); + env->SetObjectArrayElement(vars, idx, newVariant); + env->DeleteLocalRef(newVariant); + //Sourceforge-1674179 fix memory leak + // Variants received while iterating IEnumVARIANT must be cleared when no longer needed + // The variant has been copied so no longer needed + VariantClear(sink); + } + CoTaskMemFree(sink); + return (jint)fetchCount; +} + +JNIEXPORT void JNICALL +Java_com_jacob_com_EnumVariant_release(JNIEnv* env, jobject _this) +{ + IEnumVARIANT* self = extractEnumVariant(env, _this); + if(self != NULL) + { + self->Release(); + jfieldID FID_pIEnumVARIANT = 0; + jclass clazz = env->GetObjectClass(_this); + FID_pIEnumVARIANT = env->GetFieldID(clazz, "m_pIEnumVARIANT", "I"); + env->SetIntField(_this, FID_pIEnumVARIANT, (unsigned int)0); + } +} + +JNIEXPORT void JNICALL +Java_com_jacob_com_EnumVariant_Reset(JNIEnv* env, jobject _this) +{ + IEnumVARIANT* self = extractEnumVariant(env, _this); + if(self == NULL) + return; + + HRESULT hr = self->Reset(); + if(FAILED(hr)) + ThrowComFail(env, "IEnumVARIANT::Reset", hr); +} + +JNIEXPORT void JNICALL +Java_com_jacob_com_EnumVariant_Skip(JNIEnv* env, jobject _this, jint count) +{ + IEnumVARIANT* self = extractEnumVariant(env, _this); + if(self == NULL) + return; + + HRESULT hr = self->Skip((ULONG)count); + if(FAILED(hr)) + ThrowComFail(env, "IEnumVARIANT::Skip", hr); +} + +} diff --git a/c/jacob/EnumVariant.h b/c/jacob/EnumVariant.h new file mode 100644 index 0000000..3465aae --- /dev/null +++ b/c/jacob/EnumVariant.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef _Included_EnumVariant +#define _Included_EnumVariant + +#include + +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_jacob_com_EnumVariant + * Method: Next + * Signature: ([Lcom/jacob/com/Variant;)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_EnumVariant_Next + (JNIEnv *, jobject, jobjectArray); + +/* + * Class: com_jacob_com_EnumVariant + * Method: Release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_release + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_EnumVariant + * Method: Reset + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_Reset + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_EnumVariant + * Method: Skip + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_EnumVariant_Skip + (JNIEnv *, jobject, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/EventProxy.cpp b/c/jacob/EventProxy.cpp new file mode 100644 index 0000000..6cdfa59 --- /dev/null +++ b/c/jacob/EventProxy.cpp @@ -0,0 +1,870 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "EventProxy.h" +#include "Variant.h" + +// hook myself up as a listener for delegate +EventProxy::EventProxy(JNIEnv *env, + jobject aSinkObj, + CComPtr pConn, + IID eid, + CComBSTR mName[], + DISPID mID[], + int mNum) : + // initialize some variables + m_cRef(0), pCP(pConn), + eventIID(eid), MethNum(mNum), MethName(mName), + MethID(mID) +{ + // keep a pointer to the sink + javaSinkObj = env->NewGlobalRef(aSinkObj); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + + // we need this to attach to the event invocation thread + env->GetJavaVM(&jvm); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + AddRef(); + Connect(env); +} + +void EventProxy::Connect(JNIEnv *env) { + HRESULT hr = pCP->Advise(this, &dwEventCookie); + if (SUCCEEDED(hr)) { + connected = 1; + } else { + connected = 0; + ThrowComFail(env, "Advise failed", hr); + } +} + +// unhook myself up as a listener and get rid of delegate +EventProxy::~EventProxy() +{ + JNIEnv *env; + Disconnect(); + jint vmConnectionStatus = JNI_EVERSION ; + jint attachReturnStatus = -1; // AttachCurrentThread return status.. negative numbers are failure return codes. + + // attach to the current running thread -- JDK 1.4 jni.h has two param cover for 3 param call + vmConnectionStatus = jvm->GetEnv((void **)&env, JNI_VERSION_1_2); + if ((env != NULL)&& env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + if (vmConnectionStatus == JNI_EDETACHED){ + //printf("Unhook: Attaching to current thread using JNI Version 1.2 (%d)\n",vmConnectionStatus); + JavaVMAttachArgs attachmentArgs; + attachmentArgs.version = JNI_VERSION_1_2; + attachmentArgs.name = NULL; + attachmentArgs.group = NULL; + attachReturnStatus = jvm->AttachCurrentThread((void **)&env, &attachmentArgs); + if ((env != NULL) && env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + } else { + // should really look for JNI_OK versus an error because it could have been JNI_EVERSION + // started method with thread hooked to VM so no need to attach again + //printf("Unhook: No need to attach because already attached %d\n",vmConnectionStatus); + } + + // we should always have an env by this point but lets be paranoid and check + if (env != NULL){ + env->DeleteGlobalRef(javaSinkObj); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + } + if (MethNum) { + delete [] MethName; + delete [] MethID; + } + // detach from thread only if we attached to it in this function + if (attachReturnStatus == 0){ + jvm->DetachCurrentThread(); + //printf("Unhook: Detached\n"); + } else { + //printf("Unhook: No need to detatch because attached prior to method\n"); + } + //fflush(stdout); +} + +void EventProxy::Disconnect() { + if (connected) { + pCP->Unadvise(dwEventCookie); + } +} + +// I only support the eventIID interface which was passed in +// by the DispatchEvent wrapper who looked it up as the +// source object's default source interface +STDMETHODIMP EventProxy::QueryInterface(REFIID rid, void **ppv) +{ + if (rid == IID_IUnknown || rid == eventIID || rid == IID_IDispatch) + { + *ppv = this; + AddRef(); + return S_OK; + } + return E_NOINTERFACE; +} + +// This should never get called - the event source fires events +// by dispid's, not by name +STDMETHODIMP EventProxy::GetIDsOfNames(REFIID riid, + OLECHAR **rgszNames, UINT cNames, LCID lcid, DISPID *rgDispID) +{ + return E_UNEXPECTED; +} + +// The actual callback from the connection point arrives here +STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid, + LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams, + VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) +{ + const char *eventMethodName = NULL; //Sourceforge report 1394001 + JNIEnv *env = NULL; + + // map dispID to jmethodID + for(int i=0;iAttachCurrentThread((void **)&env, &attachmentArgs); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + + if (!eventMethodName) + { + // could not find this signature in list + // printf("Invoke: didn't find method name for dispatch id %d\n",dispID); + // this probably leaves a native thread attached to the vm when we don't want it + ThrowComFail(env, "Event method received was not defined as part of callback interface", -1); + + // should we detatch before returning?? We probably never get here if we ThrowComFail() + // jvm->DetachCurrentThread(); + return S_OK; + } + + // find the class of the InvocationHandler + jclass javaSinkClass = env->GetObjectClass(javaSinkObj); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + //printf("Invoke: Got sink class\n"); + jmethodID invokeMethod; + invokeMethod = env->GetMethodID(javaSinkClass, "invoke", "(Ljava/lang/String;[Lcom/jacob/com/Variant;)Lcom/jacob/com/Variant;"); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + jstring eventMethodNameAsString = env->NewStringUTF(eventMethodName); + //printf("Invoke: Got method name\n"); + // now do what we need for the variant + jmethodID getVariantMethod = env->GetMethodID(javaSinkClass, "getVariant", "()Lcom/jacob/com/Variant;"); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + //printf("Invoke: Found way too getVariant\n"); + jobject aVariantObj = env->CallObjectMethod(javaSinkObj, getVariantMethod); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + //printf("Invoke: Made Variant\n"); + jclass variantClass = env->GetObjectClass(aVariantObj); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + + // create the variant parameter array + // how many params + int numVariantParams = pDispParams->cArgs; + // make an array of them + jobjectArray varr = env->NewObjectArray(numVariantParams, variantClass, 0); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + //printf("Invoke: Created Array\n"); + int i,j; + for(i=numVariantParams-1,j=0;i>=0;i--,j++) + { + // construct a java variant holder + jobject arg = env->CallObjectMethod(javaSinkObj, getVariantMethod); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + // get the empty variant from it + VARIANT *va = extractVariant(env, arg); + // copy the value + VariantCopy(va, &pDispParams->rgvarg[i]); + // put it in the array + env->SetObjectArrayElement(varr, j, arg); + env->DeleteLocalRef(arg); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + } + //printf("Invoke: Filled Array\n"); + // Set up the return value + jobject ret; + + ret = env->CallObjectMethod(javaSinkObj, invokeMethod, + eventMethodNameAsString, varr); + //printf("Invoke: Invoked callback\n"); + if (!env->ExceptionOccurred() && ret != NULL) { + VariantCopy(pVarResult, extractVariant(env,ret)); + } + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + // don't need the first variant we created to get the class + // SF 1689061 change not accepted but put in as comment for later reminder + //Java_com_jacob_com_Variant_release(env, aVariantObj); + env->DeleteLocalRef(aVariantObj); + if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();} + + // Begin code from Jiffie team that copies parameters back from java to COM + for(i=numVariantParams-1,j=0;i>=0;i--,j++) + { + jobject arg = env->GetObjectArrayElement(varr, j); + VARIANT *java = extractVariant(env, arg); + VARIANT *com = &pDispParams->rgvarg[i]; + convertJavaVariant(java, com); + // SF 1689061 change not accepted but put in as comment for later reminder + //Java_com_jacob_com_Variant_release(env, arg); + zeroVariant(env, arg); + env->DeleteLocalRef(arg); + } + // End code from Jiffie team that copies parameters back from java to COM + // detach from thread + //printf("Invoke: Detatching\n"); + jvm->DetachCurrentThread(); + //fflush(stdout); + return S_OK; + } + return E_NOINTERFACE; +} + +void EventProxy::convertJavaVariant(VARIANT *java, VARIANT *com) { + + switch (com->vt) + { + case VT_DISPATCH: + { + switch (java->vt) + { + case VT_DISPATCH: + { + V_DISPATCH(com) = V_DISPATCH(java); + break; + } + + case VT_DISPATCH | VT_BYREF: + { + V_DISPATCH(com) = *V_DISPATCHREF(java); + break; + } + } + break; + } + + case VT_DISPATCH | VT_BYREF: + { + switch (java->vt) + { + case VT_DISPATCH: + { + *V_DISPATCHREF(com) = V_DISPATCH(java); + break; + } + + case VT_DISPATCH | VT_BYREF: + { + *V_DISPATCHREF(com) = *V_DISPATCHREF(java); + break; + } + } + break; + } + + case VT_BOOL: + { + switch (java->vt) + { + case VT_BOOL: + { + V_BOOL(com) = V_BOOL(java); + break; + } + + case VT_BOOL | VT_BYREF: + { + V_BOOL(com) = *V_BOOLREF(java); + break; + } + } + break; + } + + case VT_BOOL | VT_BYREF: + { + switch (java->vt) + { + case VT_BOOL: + { + *V_BOOLREF(com) = V_BOOL(java); + break; + } + + case VT_BOOL | VT_BYREF: + { + *V_BOOLREF(com) = *V_BOOLREF(java); + break; + } + } + break; + } + + case VT_UI1: + { + switch (java->vt) + { + case VT_UI1: + { + V_UI1(com) = V_UI1(java); + break; + } + + case VT_UI1 | VT_BYREF: + { + V_UI1(com) = *V_UI1REF(java); + break; + } + } + break; + } + + case VT_UI1 | VT_BYREF: + { + switch (java->vt) + { + case VT_UI1: + { + *V_UI1REF(com) = V_UI1(java); + break; + } + + case VT_UI1 | VT_BYREF: + { + *V_UI1REF(com) = *V_UI1REF(java); + break; + } + } + break; + } + + + case VT_I2: + { + switch (java->vt) + { + case VT_I2: + { + V_I2(com) = V_I2(java); + break; + } + + case VT_I2 | VT_BYREF: + { + V_I2(com) = *V_I2REF(java); + break; + } + } + break; + } + + case VT_I2 | VT_BYREF: + { + switch (java->vt) + { + case VT_I2: + { + *V_I2REF(com) = V_I2(java); + break; + } + + case VT_I2 | VT_BYREF: + { + *V_I2REF(com) = *V_I2REF(java); + break; + } + } + break; + } + + case VT_I4: + { + switch (java->vt) + { + case VT_I4: + { + V_I4(com) = V_I4(java); + break; + } + + case VT_I4 | VT_BYREF: + { + V_I4(com) = *V_I4REF(java); + break; + } + } + break; + } + + case VT_I4 | VT_BYREF: + { + switch (java->vt) + { + case VT_I4: + { + *V_I4REF(com) = V_I4(java); + break; + } + + case VT_I4 | VT_BYREF: + { + *V_I4REF(com) = *V_I4REF(java); + break; + } + } + break; + } + + case VT_R4: + { + switch (java->vt) + { + case VT_R4: + { + V_R4(com) = V_R4(java); + break; + } + + case VT_R4 | VT_BYREF: + { + V_R4(com) = *V_R4REF(java); + break; + } + } + break; + } + + case VT_R4 | VT_BYREF: + { + switch (java->vt) + { + case VT_R4: + { + *V_R4REF(com) = V_R4(java); + break; + } + + case VT_R4 | VT_BYREF: + { + *V_R4REF(com) = *V_R4REF(java); + break; + } + } + break; + } + + case VT_R8: + { + switch (java->vt) + { + case VT_R8: + { + V_R8(com) = V_R8(java); + break; + } + + case VT_R8 | VT_BYREF: + { + V_R8(com) = *V_R8REF(java); + break; + } + } + break; + } + + case VT_R8 | VT_BYREF: + { + switch (java->vt) + { + case VT_R8: + { + *V_R8REF(com) = V_R8(java); + break; + } + + case VT_R8 | VT_BYREF: + { + *V_R8REF(com) = *V_R8REF(java); + break; + } + } + break; + } + + case VT_I1: + { + switch (java->vt) + { + case VT_I1: + { + V_I1(com) = V_I1(java); + break; + } + + case VT_I1 | VT_BYREF: + { + V_I1(com) = *V_I1REF(java); + break; + } + } + break; + } + + case VT_I1 | VT_BYREF: + { + switch (java->vt) + { + case VT_I1: + { + *V_I1REF(com) = V_I1(java); + break; + } + + case VT_I1 | VT_BYREF: + { + *V_I1REF(com) = *V_I1REF(java); + break; + } + } + break; + } + + case VT_UI2: + { + switch (java->vt) + { + case VT_UI2: + { + V_UI2(com) = V_UI2(java); + break; + } + + case VT_UI2 | VT_BYREF: + { + V_UI2(com) = *V_UI2REF(java); + break; + } + } + break; + } + + case VT_UI2 | VT_BYREF: + { + switch (java->vt) + { + case VT_UI2: + { + *V_UI2REF(com) = V_UI2(java); + break; + } + + case VT_UI2 | VT_BYREF: + { + *V_UI2REF(com) = *V_UI2REF(java); + break; + } + } + break; + } + + case VT_UI4: + { + switch (java->vt) + { + case VT_UI4: + { + V_UI4(com) = V_UI4(java); + break; + } + + case VT_UI4 | VT_BYREF: + { + V_UI4(com) = *V_UI4REF(java); + break; + } + } + break; + } + + case VT_UI4 | VT_BYREF: + { + switch (java->vt) + { + case VT_UI4: + { + *V_UI4REF(com) = V_UI4(java); + break; + } + + case VT_UI4 | VT_BYREF: + { + *V_UI4REF(com) = *V_UI4REF(java); + break; + } + } + break; + } + + case VT_INT: + { + switch (java->vt) + { + case VT_INT: + { + V_INT(com) = V_INT(java); + break; + } + + case VT_INT | VT_BYREF: + { + V_INT(com) = *V_INTREF(java); + break; + } + } + break; + } + + case VT_INT | VT_BYREF: + { + switch (java->vt) + { + case VT_INT: + { + *V_INTREF(com) = V_INT(java); + break; + } + + case VT_INT | VT_BYREF: + { + *V_INTREF(com) = *V_INTREF(java); + break; + } + } + break; + } + + case VT_UINT: + { + switch (java->vt) + { + case VT_UINT: + { + V_UINT(com) = V_UINT(java); + break; + } + + case VT_UINT | VT_BYREF: + { + V_UINT(com) = *V_UINTREF(java); + break; + } + } + break; + } + + case VT_UINT | VT_BYREF: + { + switch (java->vt) + { + case VT_UINT: + { + *V_UINTREF(com) = V_UINT(java); + break; + } + + case VT_UINT | VT_BYREF: + { + *V_UINTREF(com) = *V_UINTREF(java); + break; + } + } + break; + } + + case VT_CY: + { + switch (java->vt) + { + case VT_CY: + { + V_CY(com) = V_CY(java); + break; + } + + case VT_CY | VT_BYREF: + { + V_CY(com) = *V_CYREF(java); + break; + } + } + break; + } + + case VT_CY | VT_BYREF: + { + switch (java->vt) + { + case VT_CY: + { + *V_CYREF(com) = V_CY(java); + break; + } + + case VT_CY | VT_BYREF: + { + *V_CYREF(com) = *V_CYREF(java); + break; + } + } + break; + } + + case VT_DATE: + { + switch (java->vt) + { + case VT_DATE: + { + V_DATE(com) = V_DATE(java); + break; + } + + case VT_DATE | VT_BYREF: + { + V_DATE(com) = *V_DATEREF(java); + break; + } + } + break; + } + + case VT_DATE | VT_BYREF: + { + switch (java->vt) + { + case VT_DATE: + { + *V_DATEREF(com) = V_DATE(java); + break; + } + + case VT_DATE | VT_BYREF: + { + *V_DATEREF(com) = *V_DATEREF(java); + break; + } + } + break; + } + + case VT_BSTR: + { + switch (java->vt) + { + case VT_BSTR: + { + V_BSTR(com) = V_BSTR(java); + break; + } + + case VT_BSTR | VT_BYREF: + { + V_BSTR(com) = *V_BSTRREF(java); + break; + } + } + break; + } + + case VT_BSTR | VT_BYREF: + { + switch (java->vt) + { + case VT_BSTR: + { + *V_BSTRREF(com) = V_BSTR(java); + break; + } + + case VT_BSTR | VT_BYREF: + { + *V_BSTRREF(com) = *V_BSTRREF(java); + break; + } + } + break; + } + + case VT_DECIMAL: + { + switch (java->vt) + { + case VT_DECIMAL: + { + V_DECIMAL(com) = V_DECIMAL(java); + break; + } + + case VT_DECIMAL | VT_BYREF: + { + V_DECIMAL(com) = *V_DECIMALREF(java); + break; + } + } + break; + } + + case VT_DECIMAL | VT_BYREF: + { + switch (java->vt) + { + case VT_DECIMAL: + { + *V_DECIMALREF(com) = V_DECIMAL(java); + break; + } + + case VT_DECIMAL | VT_BYREF: + { + *V_DECIMALREF(com) = *V_DECIMALREF(java); + break; + } + } + break; + } + + + } +} diff --git a/c/jacob/EventProxy.h b/c/jacob/EventProxy.h new file mode 100644 index 0000000..903fcb1 --- /dev/null +++ b/c/jacob/EventProxy.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include "stdafx.h" +#include "util.h" + +/* + * An instance of this class stands between a connection point + * and a java object. When it gets invoked from the cp, it reflects + * the call into the java object dynamically. The eventIID is passed + * in as are the valid dispids and the corresponding names. A map + * is created between the dispids and the java object's method in + * the constructor. For now, all the java event methods have to have + * the same signature: (Variant[]) + */ +class EventProxy : public IDispatch +{ +private: + int connected; + LONG m_cRef; // a reference counter + CComPtr pCP; // the connection point + DWORD dwEventCookie; // connection point cookie + jobject javaSinkObj; // the java object to delegate calls + + IID eventIID; // the interface iid passed in + int MethNum; // number of methods in the callback interface + CComBSTR *MethName; // Array of method names + DISPID *MethID; // Array of method ids, used to match invokations to method names + JavaVM *jvm; // The java vm we are running + void convertJavaVariant(VARIANT *java, VARIANT *com); + void Connect(JNIEnv *env); + void Disconnect(); +public: + // constuct with a global JNI ref to a sink object + // to which we will delegate event callbacks + EventProxy(JNIEnv *jenv, + jobject aSinkObj, + CComPtr pConn, + IID eventIID, + CComBSTR *mName, + DISPID *mID, + int mNum); + ~EventProxy(); + + // IUnknown methods + STDMETHODIMP_(ULONG) AddRef(void) + { + LONG res = InterlockedIncrement(&m_cRef); + return res; + } + + STDMETHODIMP_(ULONG) Release(void) + { + LONG res = InterlockedDecrement(&m_cRef); + if (res == 0) { + delete this; + } + return res; + + } + + STDMETHODIMP QueryInterface(REFIID rid, void **ppv); + + // IDispatch methods + STDMETHODIMP GetTypeInfoCount(UINT *num) + { + *num = 0; + return S_OK; + } + + STDMETHODIMP GetTypeInfo(UINT, LCID, ITypeInfo **pptInfo) + { + *pptInfo=NULL; + return E_NOTIMPL; + } + + // These are the actual supported methods + STDMETHODIMP GetIDsOfNames(REFIID, OLECHAR **, UINT, LCID , DISPID *); + STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD , DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *); +}; diff --git a/c/jacob/STA.cpp b/c/jacob/STA.cpp new file mode 100644 index 0000000..2da50b5 --- /dev/null +++ b/c/jacob/STA.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include +#include "ComThread.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +JNIEXPORT void JNICALL Java_com_jacob_com_STA_doMessagePump + (JNIEnv *env, jobject obj) +{ + // store the current thread id so we can kill it + jclass argClass = env->GetObjectClass(obj); + jfieldID ajf = env->GetFieldID( argClass, "threadID", "I"); + jint threadID = (jint)GetCurrentThreadId(); + env->SetIntField(obj, ajf, threadID); + + MSG msg; + + ZeroMemory(&msg, sizeof(msg)); + msg.wParam = S_OK; + + while (GetMessage(&msg, NULL, 0, 0)) + { + DispatchMessage(&msg); + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_STA_quitMessagePump + (JNIEnv *env, jobject obj) +{ + jclass argClass = env->GetObjectClass(obj); + jfieldID ajf = env->GetFieldID( argClass, "threadID", "I"); + jint threadID = env->GetIntField(obj, ajf); + PostThreadMessage((DWORD)threadID, WM_QUIT, 0, 0); +} + +} diff --git a/c/jacob/STA.h b/c/jacob/STA.h new file mode 100644 index 0000000..b575849 --- /dev/null +++ b/c/jacob/STA.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class STA */ + +#ifndef _Included_com_jacob_com_STA +#define _Included_com_jacob_com_STA +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: com_jacob_com_STA + * Method: doMessagePump + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_STA_doMessagePump + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_STA + * Method: quitMessagePump + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_STA_quitMessagePump + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/SafeArray.cpp b/c/jacob/SafeArray.cpp new file mode 100644 index 0000000..21a5939 --- /dev/null +++ b/c/jacob/SafeArray.cpp @@ -0,0 +1,3177 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "SafeArray.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +#define V_FLD "m_pV" + +static SAFEARRAY *makeArray(int vt, int nDims, long *lb, long *cel) +{ + if (nDims == 1) { + // no need to alloc + SAFEARRAYBOUND sab; + sab.lLbound = lb[0]; + sab.cElements = cel[0]; + SAFEARRAY *sa = SafeArrayCreate(vt,1,&sab); + return sa; + } else { + SAFEARRAYBOUND* rgsaBounds = new SAFEARRAYBOUND[nDims]; + for(int i=0;iGetObjectClass(arg); + jfieldID vf = env->GetFieldID( argClass, V_FLD, "I"); + jint vnum = env->GetIntField(arg, vf); + if (vnum != NULL) + { + // if vnum is not NULL, then there is a Variant wrapper present + VARIANT *v = (VARIANT *)vnum; + return v; + } + return NULL; +} + +// extract a SAFEARRAY from a SafeArray object +SAFEARRAY *extractSA(JNIEnv *env, jobject arg) +{ + VARIANT *v = extractWrapper(env, arg); + if (v != NULL) + { + SAFEARRAY *sa = V_ARRAY(v); + return sa; + } + return NULL; +} + +// deep copy a SAFEARRAY +SAFEARRAY *copySA(SAFEARRAY *psa) +{ + // easiest way to make a deep copy is to use VariantCopy + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + VARIANT v1, v2; + + VariantInit(&v1); + VariantInit(&v2); + V_VT(&v1) = VT_ARRAY | vt; + V_ARRAY(&v1) = psa; + VariantCopy(&v2, &v1); + SAFEARRAY *sa = V_ARRAY(&v2); + VariantInit(&v2); // make sure it's not owned by this variant + VariantClear(&v2); + VariantInit(&v1); + VariantClear(&v1); + + return sa; +} + +// create a VARIANT wrapper for the safearray +void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy) +{ + // construct a variant to hold the result + // the variant then owns the array + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, V_FLD, "I"); + jint vnum = env->GetIntField(arg, ajf); + VARIANT *v = (VARIANT *)vnum; + if (v == NULL) + { + v = new VARIANT(); + VariantInit(v); + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + V_VT(v) = VT_ARRAY | vt; + V_ARRAY(v) = copy ? copySA(sa) : sa; + env->SetIntField(arg, ajf, (unsigned int)v); +} + +/* + * Class: SafeArray + * Method: init + * Signature: (I[I[I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_init + (JNIEnv *env, jobject _this, jint vt, jintArray lb, jintArray cel) +{ + jint *lbounds = env->GetIntArrayElements(lb, NULL); + jint *celems = env->GetIntArrayElements(cel, NULL); + int nDims = env->GetArrayLength(lb); + // array lengths must match + if (nDims != env->GetArrayLength(cel)) return; + // build the sa according to params + if ( nDims > 0 ) + { + SAFEARRAY *sa = makeArray(vt, nDims, lbounds, celems); + env->ReleaseIntArrayElements(lb, lbounds, 0); + env->ReleaseIntArrayElements(cel, celems, 0); + jclass clazz = env->GetObjectClass(_this); + setSA(env, _this, sa, 0); + } +} + +/* + * Class: SafeArray + * Method: clone + * Signature: ()Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_clone + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) + { + // prepare a new return value + jclass saClass = env->GetObjectClass(_this); + jmethodID saCons = env->GetMethodID(saClass, "", "()V"); + // construct an SA to return + jobject newSA = env->NewObject(saClass, saCons); + // wrap in a Variant + setSA(env, newSA, psa, 1); + return newSA; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: destroy + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_destroy + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractWrapper(env, _this); + if (v) { + // this is the case where a Variant wrapper exists, in that + // case free the variant, but if there is just a raw SA, then + // the owning variant will free it + jclass saClass = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID(saClass, V_FLD, "I"); + VariantClear(v); + delete v; + env->SetIntField(_this, jf, (unsigned int)0); + } +} + +/* + * Class: SafeArray + * Method: getvt + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getvt + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + return (jint)vt; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: reinit + * Signature: (LSafeArray;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinit + (JNIEnv *env, jobject _this, jobject sa) +{ + // what to do here? +} + +/* + * Class: SafeArray + * Method: reinterpretType + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinterpretType + (JNIEnv *env, jobject _this, jint vt) +{ +} + +/* + * Class: SafeArray + * Method: getLBound + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__ + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + jint lb; + SafeArrayGetLBound(psa, 1, &lb); + return lb; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getLBound + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__I + (JNIEnv *env, jobject _this, jint dim) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + jint lb; + SafeArrayGetLBound(psa, dim, &lb); + return lb; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getUBound + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__ + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + jint lb; + SafeArrayGetUBound(psa, 1, &lb); + return lb; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getUBound + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__I + (JNIEnv *env, jobject _this, jint dim) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + jint lb; + SafeArrayGetUBound(psa, dim, &lb); + return lb; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getNumDim + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getNumDim + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + return SafeArrayGetDim(psa); + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getFeatures + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getFeatures + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + SafeArrayLock(psa); + jint features = psa->fFeatures; + SafeArrayUnlock(psa); + return features; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: getElemSize + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getElemSize + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (psa) { + jint siz = SafeArrayGetElemsize(psa); + return siz; + } + return NULL; +} + +static int numElements(SAFEARRAY *psa) +{ + int nDims = SafeArrayGetDim(psa); + int elems = 0; + for(int i=1;i<=nDims;i++) { + long lb, ub; + SafeArrayGetLBound(psa, i, &lb); + SafeArrayGetUBound(psa, i, &ub); + elems += ub - lb + 1; + } + return elems; +} + +/* + * Class: SafeArray + * Method: fromCharArray + * Signature: ([C)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray + (JNIEnv *env, jobject _this, jcharArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the double array - don't make a copy + jchar *arrayElements = env->GetCharArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_UI2; + for(int i=0;iReleaseCharArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromIntArray + * Signature: ([I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray + (JNIEnv *env, jobject _this, jintArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the int array - don't make a copy + jint *arrayElements = env->GetIntArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_I4; + for(int i=0;iReleaseIntArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromLongArray + * Signature: ([L)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromLongArray + (JNIEnv *env, jobject _this, jlongArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the long array - don't make a copy + jlong *arrayElements = env->GetLongArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_I8; + for(int i=0;iReleaseLongArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromShortArray + * Signature: ([S)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray + (JNIEnv *env, jobject _this, jshortArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the short array - don't make a copy + jshort *arrayElements = env->GetShortArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_I2; + for(int i=0;iReleaseShortArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromDoubleArray + * Signature: ([D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray + (JNIEnv *env, jobject _this, jdoubleArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the double array - don't make a copy + jdouble *arrayElements = env->GetDoubleArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_R8; + for(int i=0;iReleaseDoubleArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromStringArray + * Signature: ([Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromStringArray + (JNIEnv *env, jobject _this, jobjectArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BSTR; + for(int i=0;iGetObjectArrayElement(a, i); + // jacob report 1224219 should use unicode and not UTF-8 + // GetStringUTFChars() replaced with GetStringChars() + // (Variant modified in previous report) + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); // SR cast SF 1689061 + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = bs.Copy(); + long x = i; + SafeArrayPutElement(psa,&x,&v); + env->ReleaseStringChars(s, str); + VariantClear(&v); + } + } else if (vt == VT_BSTR) { + for(int i=0;iGetObjectArrayElement(a, i); + // jacob report 1224219 should use unicode and not UTF-8 + // GetStringUTFChars() replaced with GetStringChars() + // (Variant modified in previous report) + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); // SR cast SF 1689061 + BSTR bstr = bs.Detach(); + long x = i; + SafeArrayPutElement(psa,&x,bstr); + env->ReleaseStringChars(s, str); + } + } else { + ThrowComFail(env, "safearray cannot be assigned from string\n", 0); + } +} + +/* + * Class: SafeArray + * Method: fromByteArray + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray + (JNIEnv *env, jobject _this, jbyteArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the byte array - don't make a copy + jbyte *arrayElements = env->GetByteArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_UI1; + for(int i=0;iReleaseByteArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromFloatArray + * Signature: ([F)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray + (JNIEnv *env, jobject _this, jfloatArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the float array - don't make a copy + jfloat *arrayElements = env->GetFloatArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_R4; + for(int i=0;iReleaseFloatArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromBooleanArray + * Signature: ([Z)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray + (JNIEnv *env, jobject _this, jbooleanArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + // get the boolean array - don't make a copy + jboolean *arrayElements = env->GetBooleanArrayElements(a, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BOOL; + for(int i=0;iReleaseBooleanArrayElements(a, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: fromVariantArray + * Signature: ([LVariant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromVariantArray + (JNIEnv *env, jobject _this, jobjectArray a) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(a); + if (len > numElements(psa)) + { + // max size of memcpy + len = numElements(psa); + } + if (vt == VT_VARIANT) { + for(int i=0;iGetObjectArrayElement(a, i); + VARIANT *v = extractVariant(env, var); + long x = i; + if (v) SafeArrayPutElement(psa,&x,v); + } + } else { + ThrowComFail(env, "safearray cannot be assigned from variant", -1); + } +} + +/* + * Class: SafeArray + * Method: toCharArray + * Signature: ()[C + */ +JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_UI2 || vt == VT_I2) { + jcharArray arrayElements = env->NewCharArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetCharArrayRegion(arrayElements, 0, num, (jchar *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jcharArray arrayElements = env->NewCharArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_UI2))) { + return NULL; + } + jchar val = V_UI2(&v); + env->SetCharArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toIntArray + * Signature: ()[I + */ +JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_I4) { + jintArray arrayElements = env->NewIntArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetIntArrayRegion(arrayElements, 0, num, (jint *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jintArray arrayElements = env->NewIntArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_I4))) { + return NULL; + } + jint val = V_I4(&v); + env->SetIntArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + + +/* + * Class: SafeArray + * Method: toLongArray + * Signature: ()[L + */ +JNIEXPORT jlongArray JNICALL Java_com_jacob_com_SafeArray_toLongArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_I8) { + jlongArray arrayElements = env->NewLongArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetLongArrayRegion(arrayElements, 0, num, (jlong *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jlongArray arrayElements = env->NewLongArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_I8))) { + return NULL; + } + jlong val = V_I8(&v); + env->SetLongArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + + +/* + * Class: SafeArray + * Method: toShortArray + * Signature: ()[S + */ +JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_I2) { + jshortArray arrayElements = env->NewShortArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetShortArrayRegion(arrayElements, 0, num, (jshort *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jshortArray arrayElements = env->NewShortArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_I2))) { + return NULL; + } + jshort val = V_I2(&v); + env->SetShortArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toDoubleArray + * Signature: ()[D + */ +JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_R8) { + jdoubleArray arrayElements = env->NewDoubleArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetDoubleArrayRegion(arrayElements, 0, num, (jdouble *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jdoubleArray arrayElements = env->NewDoubleArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_R8))) { + return NULL; + } + jdouble val = V_R8(&v); + env->SetDoubleArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toStringArray + * Signature: ()[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) + { + jclass sClass = env->FindClass("java/lang/String"); + jobjectArray arrayElements = env->NewObjectArray(num, sClass, NULL); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) { + return NULL; + } + BSTR bs = V_BSTR(&v); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + env->SetObjectArrayElement(arrayElements, i, js); + } + return arrayElements; + } else if (vt == VT_BSTR) { + jclass sClass = env->FindClass("java/lang/String"); + jobjectArray arrayElements = env->NewObjectArray(num, sClass, NULL); + for(int i=lb;i<=ub;i++) { + BSTR bs = NULL; + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &bs); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + env->SetObjectArrayElement(arrayElements, i, js); + } + return arrayElements; + } + ThrowComFail(env, "safearray cannot be converted to string[]", 0); + return NULL; +} + +/* + * Class: SafeArray + * Method: toByteArray + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_I1 || vt == VT_UI1) { + jbyteArray arrayElements = env->NewByteArray(num); + jbyte *pData; + SafeArrayAccessData(sa, (void **)&pData); + env->SetByteArrayRegion(arrayElements, 0, num, pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jbyteArray arrayElements = env->NewByteArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb,j=0;i<=ub;i++,j++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_UI1))) { + return NULL; + } + jbyte val = V_UI1(&v); + env->SetByteArrayRegion(arrayElements, j, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toFloatArray + * Signature: ()[F + */ +JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_R4) { + jfloatArray arrayElements = env->NewFloatArray(num); + void *pData; + SafeArrayAccessData(sa, &pData); + env->SetFloatArrayRegion(arrayElements, 0, num, (jfloat *)pData); + SafeArrayUnaccessData(sa); + return arrayElements; + } else if (vt == VT_VARIANT) { + jfloatArray arrayElements = env->NewFloatArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_R4))) { + return NULL; + } + jfloat val = V_R4(&v); + env->SetFloatArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toBooleanArray + * Signature: ()[Z + */ +JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_BOOL) { + // need to loop because jboolean=1 byte and VARIANT_BOOL=2 bytes + jbooleanArray arrayElements = env->NewBooleanArray(num); + VARIANT_BOOL v; + for(int i=lb,j=0;i<=ub;i++,j++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + jboolean val = v == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE; + env->SetBooleanArrayRegion(arrayElements, j, 1, &val); + } + return arrayElements; + } else if (vt == VT_VARIANT) { + jbooleanArray arrayElements = env->NewBooleanArray(num); + VARIANT v; + VariantInit(&v); + for(int i=lb;i<=ub;i++) { + long ix = i; + SafeArrayGetElement(sa, &ix, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) { + return NULL; + } + jboolean val = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE : JNI_FALSE; + env->SetBooleanArrayRegion(arrayElements, i, 1, &val); + } + return arrayElements; + } + return NULL; +} + +/* + * Class: SafeArray + * Method: toVariantArray + * Signature: ()[LVariant; + */ +JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray + (JNIEnv *env, jobject _this) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + int num = ub - lb + 1; + jclass vClass = env->FindClass("com/jacob/com/Variant"); + // create an array of Variant's + jobjectArray varr = env->NewObjectArray(num, vClass, 0); + // fill them in + jmethodID variantCons = + env->GetMethodID(vClass, "", "()V"); + for(int i=lb;i<=ub;i++) { + long ix = i; + // construct a variant to return + jobject newVariant = env->NewObject(vClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + SafeArrayGetElement(sa, &ix, (void*) v); + // put in object array + env->SetObjectArrayElement(varr, i, newVariant); + } + return varr; +} + +// this is an ugly way to avoid copy/pasting the same code + +// returns a value extracted from a 1 dimensional SafeArray +// uses the idx variable in the object this macro is included in +#define GET1DCODE(varType, varAccess, jtyp) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; \ + } \ + if (SafeArrayGetDim(sa) != 1) { \ + ThrowComFail(env, "safearray is not 1D", -1); \ + return NULL; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + SafeArrayGetElement(sa, &idx, (void*) &v); \ + if (FAILED(VariantChangeType(&v, &v, 0, varType))) { \ + ThrowComFail(env, "VariantChangeType failed", -1); \ + return NULL; \ + } \ + return (jtyp)varAccess(&v); \ + } else if (vt == varType) { \ + jtyp jc; \ + SafeArrayGetElement(sa, &idx, (void*) &jc); \ + return jc; \ + } else { \ + return NULL; \ + } + +// returns a value extracted from a 2 dimensional SafeArray +// uses i and j from the method that this macro is included in as indexes +#define GET2DCODE(varType, varAccess, jtyp) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; \ + } \ + if (SafeArrayGetDim(sa) != 2) { \ + ThrowComFail(env, "safearray is not 2D", -1); \ + return NULL; \ + } \ + long idx[2] = {i, j}; \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + SafeArrayGetElement(sa, idx, (void*) &v); \ + if (FAILED(VariantChangeType(&v, &v, 0, varType))) { \ + ThrowComFail(env, "VariantChangeType failed", -1); \ + return NULL; \ + } \ + return (jtyp)varAccess(&v); \ + } else if (vt == varType) { \ + jtyp jc; \ + SafeArrayGetElement(sa, idx, (void*) &jc); \ + return jc; \ + } else { \ + return NULL; \ + } + + +// sets the values on a one dimensional array +#define SET1DCODE(varType, varAccess) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return; \ + } \ + if (SafeArrayGetDim(sa) != 1) { \ + ThrowComFail(env, "safearray is not 1D", -1); \ + return; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + V_VT(&v) = varType; \ + varAccess(&v) = c; \ + SafeArrayPutElement(sa,&idx,&v); \ + } else if (vt == varType) { \ + SafeArrayPutElement(sa,&idx,&c); \ + } else { \ + ThrowComFail(env, "safearray type mismatch", -1); \ + } \ + +// sets the values into a 2 dimensional array +#define SET2DCODE(varType, varAccess) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return; \ + } \ + if (SafeArrayGetDim(sa) != 2) { \ + ThrowComFail(env, "safearray is not 2D", -1); \ + return; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + long idx[2] = {i,j}; \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + V_VT(&v) = varType; \ + varAccess(&v) = c; \ + SafeArrayPutElement(sa,idx,&v); \ + } else if (vt == varType) { \ + SafeArrayPutElement(sa,idx,&c); \ + } else { \ + ThrowComFail(env, "safearray type mismatch", -1); \ + } + +#define GETARRAYCODE(varType, varType2, varAccess, jtyp, jsetArr) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == varType || vt == varType2) { \ + jtyp *pData; \ + SafeArrayAccessData(sa, (void **)&pData); \ + env->jsetArr(ja, ja_start, nelem, &pData[idx]); \ + SafeArrayUnaccessData(sa); \ + return; \ + } else if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + for(int i=idx, j=ja_start;ijsetArr(ja, j, 1, &val); \ + } \ + } + +#define SETARRAYCODE(varType, varType2, varAccess, jtyp, jgetArr, jrelArr) \ + SAFEARRAY *psa = extractSA(env, _this); \ + if (!psa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(psa, &vt); \ + jtyp *arrayElements = env->jgetArr(ja, 0); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + V_VT(&v) = varType; \ + for(int i=ja_start,j=idx;ijrelArr(ja, arrayElements, 0); + +/* + * Class: SafeArray + * Method: getChar + * Signature: (I)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_UI2, V_UI2, jchar) +} + +/* + * Class: SafeArray + * Method: getChar + * Signature: (II)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_UI2, V_UI2, jchar) +} + + +/* + * Class: SafeArray + * Method: setChar + * Signature: (IC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IC + (JNIEnv *env, jobject _this, jint idx, jchar c) +{ + SET1DCODE(VT_UI2, V_UI2); +} + +/* + * Class: SafeArray + * Method: setChar + * Signature: (IIC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IIC + (JNIEnv *env, jobject _this, jint i, jint j, jchar c) +{ + SET2DCODE(VT_UI2, V_UI2); +} + +/* + * Class: SafeArray + * Method: getChars + * Signature: (II[CI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getChars + (JNIEnv *env, jobject _this, jint idx, jint nelem, jcharArray ja, jint ja_start) +{ + GETARRAYCODE(VT_UI2, VT_I2, V_UI2, jchar, SetCharArrayRegion); +} + +/* + * Class: SafeArray + * Method: setChars + * Signature: (II[CI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars + (JNIEnv *env, jobject _this, jint idx, jint nelem, jcharArray ja, jint ja_start) +{ + SETARRAYCODE(VT_UI2, VT_I2, V_UI2, jchar, + GetCharArrayElements, ReleaseCharArrayElements); +} + +/*----------------------- INTS ----------------------------------*/ + +/* + * Class: SafeArray + * Method: getInt + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_I4, V_I4, jint) +} + +/* + * Class: SafeArray + * Method: getInt + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_I4, V_I4, jint) +} + +/* + * Class: SafeArray + * Method: setInt + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__II + (JNIEnv *env, jobject _this, jint idx, jint c) +{ + SET1DCODE(VT_I4, V_I4); +} + +/* + * Class: SafeArray + * Method: setInt + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__III + (JNIEnv *env, jobject _this, jint i, jint j, jint c) +{ + SET2DCODE(VT_I4, V_I4); +} + +/* + * Class: SafeArray + * Method: getInts + * Signature: (II[II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts + (JNIEnv *env, jobject _this, jint idx, jint nelem, jintArray ja, jint ja_start) +{ + GETARRAYCODE(VT_I4, VT_I4, V_I4, jint, SetIntArrayRegion); +} + +/* + * Class: SafeArray + * Method: setInts + * Signature: (II[II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts + (JNIEnv *env, jobject _this, jint idx, jint nelem, jintArray ja, jint ja_start) +{ + SETARRAYCODE(VT_I4, VT_I4, V_I4, jint, + GetIntArrayElements, ReleaseIntArrayElements); +} + +/*----------------------- END INTS ----------------------------------*/ +/*----------------------- LONGS ----------------------------------*/ + +/* + * Class: SafeArray + * Method: getLong + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_I8, V_I8, jlong) +} + +/* + * Class: SafeArray + * Method: getLong + * Signature: (II)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_I8, V_I8, jlong) +} + +/* + * Class: SafeArray + * Method: setLong + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IJ + (JNIEnv *env, jobject _this, jint idx, jlong c) +{ + SET1DCODE(VT_I8, V_I8); +} + +/* + * Class: SafeArray + * Method: setLong + * Signature: (IIJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IIJ + (JNIEnv *env, jobject _this, jint i, jint j, jlong c) +{ + SET2DCODE(VT_I8, V_I8); +} + +/* + * Class: SafeArray + * Method: getLongs + * Signature: (II[JI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getLongs + (JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start) +{ + GETARRAYCODE(VT_I8, VT_I8, V_I8, jlong, SetLongArrayRegion); +} + +/* + * Class: SafeArray + * Method: setLongs + * Signature: (II[JI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLongs + (JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start) +{ + SETARRAYCODE(VT_I8, VT_I8, V_I8, jlong, + GetLongArrayElements, ReleaseLongArrayElements); +} + +/*------------------------ END LONGS -----------------------------*/ + + +/* + * Class: SafeArray + * Method: getShort + * Signature: (I)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_I2, V_I2, jshort) +} + +/* + * Class: SafeArray + * Method: getShort + * Signature: (II)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_I2, V_I2, jshort) +} + +/* + * Class: SafeArray + * Method: setShort + * Signature: (IS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IS + (JNIEnv *env, jobject _this, jint idx, jshort c) +{ + SET1DCODE(VT_I2, V_I2); +} + +/* + * Class: SafeArray + * Method: setShort + * Signature: (IIS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IIS + (JNIEnv *env, jobject _this, jint i, jint j, jshort c) +{ + SET2DCODE(VT_I2, V_I2); +} + +/* + * Class: SafeArray + * Method: getShorts + * Signature: (II[SI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getShorts + (JNIEnv *env, jobject _this, jint idx, jint nelem, jshortArray ja, jint ja_start) +{ + GETARRAYCODE(VT_I2, VT_I2, V_I2, jshort, SetShortArrayRegion); +} + +/* + * Class: SafeArray + * Method: setShorts + * Signature: (II[SI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShorts + (JNIEnv *env, jobject _this, jint idx, jint nelem, jshortArray ja, jint ja_start) +{ + SETARRAYCODE(VT_I2, VT_I2, V_I2, jshort, + GetShortArrayElements, ReleaseShortArrayElements); +} + +/* + * Class: SafeArray + * Method: getDouble + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_R8, V_R8, jdouble) +} + +/* + * Class: SafeArray + * Method: getDouble + * Signature: (II)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_R8, V_R8, jdouble) +} + +/* + * Class: SafeArray + * Method: setDouble + * Signature: (ID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__ID + (JNIEnv *env, jobject _this, jint idx, jdouble c) +{ + SET1DCODE(VT_R8, V_R8); +} + +/* + * Class: SafeArray + * Method: setDouble + * Signature: (IID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__IID + (JNIEnv *env, jobject _this, jint i, jint j, jdouble c) +{ + SET2DCODE(VT_R8, V_R8); +} + +/* + * Class: SafeArray + * Method: getDoubles + * Signature: (II[DI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getDoubles + (JNIEnv *env, jobject _this, jint idx, jint nelem, jdoubleArray ja, jint ja_start) +{ + GETARRAYCODE(VT_R8, VT_R8, V_R8, jdouble, SetDoubleArrayRegion); +} + +/* + * Class: SafeArray + * Method: setDoubles + * Signature: (II[DI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDoubles + (JNIEnv *env, jobject _this, jint idx, jint nelem, jdoubleArray ja, jint ja_start) +{ + SETARRAYCODE(VT_R8, VT_R8, V_R8, jdouble, + GetDoubleArrayElements, ReleaseDoubleArrayElements); +} + +/* + * Class: SafeArray + * Method: getString + * Signature: (I)Ljava/lang/String; + * + * There is supposed to be a leak in here, SourceForge 1224219 + * that should be fixed with a call to + * "StrFree, Release or VariantClear to release the memory" + * waiting on the actual patch the submitter used before modifying this + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__I + (JNIEnv *env, jobject _this, jint idx) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + SafeArrayGetElement(psa, &idx, &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) { + return NULL; + } + BSTR bs = V_BSTR(&v); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + // jacob report 1224219 + // SafeArrayGetElement memory must be freed http://www.canaimasoft.com/f90VB/OnlineManuals/Reference/TH_31.htm + VariantClear(&v); + return js; + } else if (vt == VT_BSTR) { + BSTR bs = NULL; + SafeArrayGetElement(psa, &idx, &bs); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + // jacob report 1224219 + // SafeArrayGetElement memory must be freed http://www.canaimasoft.com/f90VB/OnlineManuals/Reference/TH_31.htm + if (bs) SysFreeString(bs); + return js; + } + ThrowComFail(env, "safearray cannot get string", 0); + return NULL; +} + +/* + * Class: SafeArray + * Method: getString + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + long idx[2] = {i, j}; + SafeArrayGetElement(psa, idx, &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) { + return NULL; + } + BSTR bs = V_BSTR(&v); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + return js; + } else if (vt == VT_BSTR) { + long idx[2] = {i, j}; + BSTR bs = NULL; + SafeArrayGetElement(psa, idx, &bs); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + return js; + } + ThrowComFail(env, "safearray cannot get string", 0); + return NULL; +} + +/* + * Class: SafeArray + * Method: setString + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__ILjava_lang_String_2 + (JNIEnv *env, jobject _this, jint idx, jstring s) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); \ + return; + } + if (SafeArrayGetDim(sa) != 1) { + ThrowComFail(env, "safearray not 1D", -1); \ + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = bs.Copy(); + SafeArrayPutElement(sa,&idx,&v); \ + env->ReleaseStringChars(s, str); + VariantClear(&v); + } else if (vt == VT_BSTR) { + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + SafeArrayPutElement(sa,&idx,bs.Detach()); + env->ReleaseStringChars(s, str); + } else { + ThrowComFail(env, "safearray cannot set string", 0); + } +} + +/* + * Class: SafeArray + * Method: setString + * Signature: (IILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__IILjava_lang_String_2 + (JNIEnv *env, jobject _this, jint i, jint j, jstring s) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + if (SafeArrayGetDim(sa) != 2) { + ThrowComFail(env, "safearray is not 2D", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = bs.Copy(); + long idx[2] = {i,j}; + SafeArrayPutElement(sa,idx,&v); + env->ReleaseStringChars(s, str); + VariantClear(&v); + } else if (vt == VT_BSTR) { + long idx[2] = {i,j}; + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + SafeArrayPutElement(sa,idx,bs.Detach()); + env->ReleaseStringChars(s, str); + } else { + ThrowComFail(env, "safearray cannot set string", 0); + } +} + +/* + * Class: SafeArray + * Method: getStrings + * Signature: (II[Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getStrings + (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) + { + VARIANT v; + for(int i=idx, j=ja_start;iNewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + env->SetObjectArrayElement(ja, j, js); + VariantClear(&v); + } + } + else if (vt == VT_BSTR) + { + BSTR bs = NULL; + for(int i=idx, j=ja_start;iNewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + env->SetObjectArrayElement(ja, j, js); + } + } else { + ThrowComFail(env, "safearray cannot get strings", 0); + } +} + +/* + * Class: SafeArray + * Method: setStrings + * Signature: (II[Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setStrings + (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(ja); + if (len > numElements(psa)) + { + len = numElements(psa); + } + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i); + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = bs.Copy(); + long x = j; + SafeArrayPutElement(psa,&x,&v); + VariantClear(&v); + env->ReleaseStringChars(s, str); + } + } else if (vt == VT_BSTR) { + for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i); + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + long x = j; + SafeArrayPutElement(psa,&x,bs.Detach()); + env->ReleaseStringChars(s, str); + } + } else { + ThrowComFail(env, "safearray cannot set strings", 0); + } +} + +/* + * Class: SafeArray + * Method: getByte + * Signature: (I)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_UI1, V_UI1, jbyte) +} + +/* + * Class: SafeArray + * Method: getByte + * Signature: (II)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_UI1, V_UI1, jbyte) +} + +/* + * Class: SafeArray + * Method: setByte + * Signature: (IB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IB + (JNIEnv *env, jobject _this, jint idx, jbyte c) +{ + SET1DCODE(VT_UI1, V_UI1); +} + +/* + * Class: SafeArray + * Method: setByte + * Signature: (IIB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IIB + (JNIEnv *env, jobject _this, jint i, jint j, jbyte c) +{ + SET2DCODE(VT_UI1, V_UI1); +} + +/* + * Class: SafeArray + * Method: getBytes + * Signature: (II[BI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBytes + (JNIEnv *env, jobject _this, jint idx, jint nelem, jbyteArray ja, jint ja_start) +{ + GETARRAYCODE(VT_UI1, VT_I1, V_UI1, jbyte, SetByteArrayRegion); +} + +/* + * Class: SafeArray + * Method: setBytes + * Signature: (II[BI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBytes + (JNIEnv *env, jobject _this, jint idx, jint nelem, jbyteArray ja, jint ja_start) +{ + SETARRAYCODE(VT_UI1, VT_I1, V_UI1, jbyte, + GetByteArrayElements, ReleaseByteArrayElements); +} + +/* + * Class: SafeArray + * Method: getFloat + * Signature: (I)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__I + (JNIEnv *env, jobject _this, jint idx) +{ + GET1DCODE(VT_R4, V_R4, jfloat) +} + +/* + * Class: SafeArray + * Method: getFloat + * Signature: (II)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + GET2DCODE(VT_R4, V_R4, jfloat) +} + +/* + * Class: SafeArray + * Method: setFloat + * Signature: (IF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IF + (JNIEnv *env, jobject _this, jint idx, jfloat c) +{ + SET1DCODE(VT_R4, V_R4); +} + +/* + * Class: SafeArray + * Method: setFloat + * Signature: (IIF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IIF + (JNIEnv *env, jobject _this, jint i, jint j, jfloat c) +{ + SET2DCODE(VT_R4, V_R4); +} + +/* + * Class: SafeArray + * Method: getFloats + * Signature: (II[FI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getFloats + (JNIEnv *env, jobject _this, jint idx, jint nelem, jfloatArray ja, jint ja_start) +{ + GETARRAYCODE(VT_R4, VT_R4, V_R4, jfloat, SetFloatArrayRegion); +} + +/* + * Class: SafeArray + * Method: setFloats + * Signature: (II[FI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloats + (JNIEnv *env, jobject _this, jint idx, jint nelem, jfloatArray ja, jint ja_start) +{ + SETARRAYCODE(VT_R4, VT_R4, V_R4, jfloat, + GetFloatArrayElements, ReleaseFloatArrayElements); +} + +/* + * Class: SafeArray + * Method: getBoolean + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__I + (JNIEnv *env, jobject _this, jint idx) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + if (SafeArrayGetDim(sa) != 1) { + ThrowComFail(env, "safearray not 1D", -1); \ + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + SafeArrayGetElement(sa, &idx, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) { + ThrowComFail(env, "safearray change type failed", -1); \ + return NULL; + } + jboolean jb = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb; + SafeArrayGetElement(sa, &idx, (void*) &vb); + jboolean jb = vb == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else { + return NULL; + } +} + +/* + * Class: SafeArray + * Method: getBoolean + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + if (SafeArrayGetDim(sa) != 2) { + ThrowComFail(env, "safearray is not 2D", -1); + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + long idx[2] = {i,j}; + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + SafeArrayGetElement(sa, idx, (void*) &v); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) { + ThrowComFail(env, "safearray change type failed", -1); + return NULL; + } + jboolean jb = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb; + SafeArrayGetElement(sa, idx, (void*) &vb); + jboolean jb = vb == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else { + return NULL; + } +} + +/* + * Class: SafeArray + * Method: setBoolean + * Signature: (IZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IZ + (JNIEnv *env, jobject _this, jint idx, jboolean c) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + if (SafeArrayGetDim(sa) != 1) { + ThrowComFail(env, "safearray is not 1D", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BOOL; + V_BOOL(&v) = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,&idx,&v); + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,&idx,&vb); + } else { + ThrowComFail(env, "safearray type mismatch", -1); + } +} + +/* + * Class: SafeArray + * Method: setBoolean + * Signature: (IIZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IIZ + (JNIEnv *env, jobject _this, jint i, jint j, jboolean c) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + if (SafeArrayGetDim(sa) != 2) { + ThrowComFail(env, "safearray is not 2D", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + long idx[2] = {i,j}; + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BOOL; + V_BOOL(&v) = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,idx,&v); + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,idx,&vb); + } else { + ThrowComFail(env, "safearray type mismatch", -1); + } +} + +/* + * Class: SafeArray + * Method: getBooleans + * Signature: (II[ZI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBooleans + (JNIEnv *env, jobject _this, jint idx, jint nelem, jbooleanArray ja, jint ja_start) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_BOOL) { + VARIANT_BOOL v; + for(int i=idx, j=ja_start;iSetBooleanArrayRegion(ja, j, 1, &val); + } + } else if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + for(int i=idx, j=ja_start;iSetBooleanArrayRegion(ja, j, 1, &val); + } + } +} + +/* + * Class: SafeArray + * Method: setBooleans + * Signature: (II[ZI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans + (JNIEnv *env, jobject _this, jint idx, jint nelem, jbooleanArray ja, jint ja_start) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(ja); + if (len > numElements(psa)) + { + len = numElements(psa); + } + jboolean *arrayElements = env->GetBooleanArrayElements(ja, 0); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BOOL; + for(int i=ja_start,j=idx;iReleaseBooleanArrayElements(ja, arrayElements, 0); +} + +/* + * Class: SafeArray + * Method: getVariant + * Signature: (I)LVariant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__I + (JNIEnv *env, jobject _this, jint idx) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + // prepare a new return value + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID variantCons = + env->GetMethodID(variantClass, "", "()V"); + // construct a variant to return + jobject newVariant = env->NewObject(variantClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + if (vt == VT_VARIANT) { + SafeArrayGetElement(psa, &idx, v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + IDispatch *disp; + SafeArrayGetElement(psa, &idx, (void *)&disp); + VariantClear(v); // whatever was there before + V_VT(v) = VT_DISPATCH; + V_DISPATCH(v) = disp; + // I am handing the pointer to COM + disp->AddRef(); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } + return newVariant; +} + +/* + * Class: SafeArray + * Method: getVariant + * Signature: (II)LVariant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__II + (JNIEnv *env, jobject _this, jint i, jint j) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + // prepare a new return value + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID variantCons = + env->GetMethodID(variantClass, "", "()V"); + // construct a variant to return + jobject newVariant = env->NewObject(variantClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + long idx[2] = {i,j}; + if (vt == VT_VARIANT) { + SafeArrayGetElement(psa, idx, v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + IDispatch *disp; + SafeArrayGetElement(psa, idx, (void *)&disp); + VariantClear(v); // whatever was there before + V_VT(v) = VT_DISPATCH; + V_DISPATCH(v) = disp; + // I am handing the pointer to COM + disp->AddRef(); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } + return newVariant; +} + +/* + * Class: SafeArray + * Method: setVariant + * Signature: (ILVariant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__ILcom_jacob_com_Variant_2 + (JNIEnv *env, jobject _this, jint idx, jobject s) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + if (SafeArrayGetDim(sa) != 1) { + ThrowComFail(env, "safearray is not 1D", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + VARIANT *v = extractVariant(env, s); + if (vt == VT_VARIANT) { + SafeArrayPutElement(sa,&idx,v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + if (V_VT(v) != VT_DISPATCH) { + ThrowComFail(env, "variant is not dispatch", -1); + return; + } + IDispatch *disp = V_DISPATCH(v); + disp->AddRef(); + SafeArrayPutElement(sa,&idx,disp); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } +} + +/* + * Class: SafeArray + * Method: setVariant + * Signature: (IILVariant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__IILcom_jacob_com_Variant_2 + (JNIEnv *env, jobject _this, jint i, jint j, jobject s) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + if (SafeArrayGetDim(sa) != 2) { + ThrowComFail(env, "safearray is not 2D", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + long idx[2] = {i, j}; + if (vt == VT_VARIANT) { + VARIANT *v = extractVariant(env, s); + SafeArrayPutElement(sa,idx,v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + VARIANT *v = extractVariant(env, s); + if (V_VT(v) != VT_DISPATCH) { + ThrowComFail(env, "variant is not dispatch", -1); + return; + } + IDispatch *disp = V_DISPATCH(v); + SafeArrayPutElement(sa,idx,disp); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } +} + +/* + * Class: SafeArray + * Method: getVariants + * Signature: (II[LVariant;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getVariants + (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + long lb, ub; + SafeArrayGetLBound(sa, 1, &lb); + SafeArrayGetUBound(sa, 1, &ub); + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) + { + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID variantCons = + env->GetMethodID(variantClass, "", "()V"); + for(int i=idx, j=ja_start;iNewObject(variantClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + SafeArrayGetElement(sa, &ix, (void*) v); + env->SetObjectArrayElement(ja, j, newVariant); + } + } else { + ThrowComFail(env, "safearray type is not variant", -1); + } +} + +/* + * Class: SafeArray + * Method: setVariants + * Signature: (II[LVariant;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariants + (JNIEnv *env, jobject _this, jint idx, jint nelem, jobjectArray ja, jint ja_start) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + int len = env->GetArrayLength(ja); + if (len > numElements(psa)) + { + len = numElements(psa); + } + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + for(int i=ja_start,j=idx;iGetObjectArrayElement(ja, i); + VARIANT *v = extractVariant(env, var); + long x = j; + SafeArrayPutElement(psa,&x,v); + } + } else { + ThrowComFail(env, "safearray type is not variant", -1); + } +} + +/* PLEASE NOTE THE LINE: + jint *jIndices = env->GetIntArrayElements(indices, NULL); + which I added to replace "long idx[2] = {i,j};" from the 2D case. + Not sure if this is correct. Also, check that I am doing the null test and + dimension test correctly. + Would really like to call env->ReleaseIntArrayElements(indices, jIndices, NULL); + in here but I can't get it to work +*/ + +#define GETNDCODE(varType, varAccess, jtyp) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; \ + } \ + jint *jIndices = env->GetIntArrayElements(indices, NULL); \ + if (!jIndices) { \ + ThrowComFail(env, "null indices array", -1); \ + return NULL; \ + } \ + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { \ + ThrowComFail(env, "safearray and indices array have different dimensions", -1); \ + return NULL; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + SafeArrayGetElement(sa, jIndices, (void*) &v); \ + if (FAILED(VariantChangeType(&v, &v, 0, varType))) { \ + ThrowComFail(env, "VariantChangeType failed", -1); \ + return NULL; \ + } \ + return (jtyp)varAccess(&v); \ + } else if (vt == varType) { \ + jtyp jc; \ + SafeArrayGetElement(sa, jIndices, (void*) &jc); \ + return jc; \ + } else { \ + return NULL; \ + } + + +//--------------------------------- + +/* PLEASE NOTE THE LINE: + jint *jIndices = env->GetIntArrayElements(indices, NULL); + which I added to replace "long idx[2] = {i,j};" from the 2D case. + Not sure if this is correct. Also, check that I am doing the null test and + dimension test correctly. + Would really like to call env->ReleaseIntArrayElements(indices, jIndices, NULL); + in here but I can't get it to work + */ + +#define SETNDCODE(varType, varAccess) \ + SAFEARRAY *sa = extractSA(env, _this); \ + if (!sa) { \ + ThrowComFail(env, "safearray object corrupted", -1); \ + return; \ + } \ + jint *jIndices = env->GetIntArrayElements(indices, NULL); \ + if (!jIndices) { \ + ThrowComFail(env, "null indices array", -1); \ + return; \ + } \ + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { \ + ThrowComFail(env, "safearray and indices array have different dimensions", -1); \ + return; \ + } \ + VARTYPE vt; \ + SafeArrayGetVartype(sa, &vt); \ + if (vt == VT_VARIANT) { \ + VARIANT v; \ + VariantInit(&v); \ + V_VT(&v) = varType; \ + varAccess(&v) = c; \ + SafeArrayPutElement(sa,jIndices,&v); \ + } else if (vt == varType) { \ + SafeArrayPutElement(sa, jIndices,&c); \ + } else { \ + ThrowComFail(env, "safearray type mismatch", -1); \ + } + +/* + * Class: com_jacob_com_SafeArray + * Method: getVariant + * Signature: ([I)Lcom/jacob/com/Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return NULL; + } + if (SafeArrayGetDim(psa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return NULL; + } + + + // prepare a new return value + jclass variantClass = env->FindClass("com/jacob/com/Variant"); + jmethodID variantCons = + env->GetMethodID(variantClass, "", "()V"); + // construct a variant to return + jobject newVariant = env->NewObject(variantClass, variantCons); + // get the VARIANT from the newVariant + VARIANT *v = extractVariant(env, newVariant); + if (vt == VT_VARIANT) { + SafeArrayGetElement(psa, jIndices, v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + IDispatch *disp; + SafeArrayGetElement(psa, jIndices, (void *)&disp); + VariantClear(v); // whatever was there before + V_VT(v) = VT_DISPATCH; + V_DISPATCH(v) = disp; + // I am handing the pointer to COM + disp->AddRef(); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } + env->ReleaseIntArrayElements(indices, jIndices, NULL); + return newVariant; +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setVariant + * Signature: ([ILcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant___3ILcom_jacob_com_Variant_2 + (JNIEnv *env, jobject _this, jintArray indices, jobject s) +{ + + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return; + } + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return; + } + + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + + if (vt == VT_VARIANT) { + VARIANT *v = extractVariant(env, s); + SafeArrayPutElement(sa, jIndices, v); + } else if (vt == VT_DISPATCH || vt == VT_UNKNOWN) { + VARIANT *v = extractVariant(env, s); + if (V_VT(v) != VT_DISPATCH) { + ThrowComFail(env, "variant is not dispatch", -1); + return; + } + IDispatch *disp = V_DISPATCH(v); + SafeArrayPutElement(sa, jIndices, disp); + } else { + ThrowComFail(env, "safearray type is not variant/dispatch", -1); + } + env->ReleaseIntArrayElements(indices, jIndices, NULL); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getChar + * Signature: ([I)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_UI2, V_UI2, jchar) +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setChar + * Signature: ([IC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar___3IC + (JNIEnv *env, jobject _this, jintArray indices, jchar c) +{ + SETNDCODE(VT_UI2, V_UI2); +} + +/*----------------------- INTS ----------------------------------*/ + +/* + * Class: com_jacob_com_SafeArray + * Method: getInt + * Signature: ([I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_I4, V_I4, jint) +} + + +/* + * Class: com_jacob_com_SafeArray + * Method: setInt + * Signature: ([II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II + (JNIEnv *env, jobject _this, jintArray indices, jint c) +{ + SETNDCODE(VT_I4, V_I4); +} + +/*----------------------- END INTS ----------------------------------*/ +/*----------------------- LONGS ----------------------------------*/ + +/* + * Class: com_jacob_com_SafeArray + * Method: getLong + * Signature: ([I)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_I8, V_I8, jlong) +} + + +/* + * Class: com_jacob_com_SafeArray + * Method: setLong + * Signature: ([IJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong___3IJ + (JNIEnv *env, jobject _this, jintArray indices, jlong c) +{ + SETNDCODE(VT_I8, V_I8); +} + +/*----------------------- END LONGS ----------------------------------*/ + +/* + * Class: com_jacob_com_SafeArray + * Method: getShort + * Signature: ([I)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_I2, V_I2, jshort) +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setShort + * Signature: ([IS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort___3IS + (JNIEnv *env, jobject _this, jintArray indices, jshort c) +{ + SETNDCODE(VT_I2, V_I2); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getDouble + * Signature: ([I)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_R8, V_R8, jdouble) +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setDouble + * Signature: ([ID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble___3ID + (JNIEnv *env, jobject _this, jintArray indices, jdouble c) +{ + SETNDCODE(VT_R8, V_R8); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getString + * Signature: ([I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + SAFEARRAY *psa = extractSA(env, _this); + if (!psa) { + ThrowComFail(env, "safearray object corrupted", -1); \ + return NULL; + } + + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return NULL; + } + if (SafeArrayGetDim(psa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return NULL; + } + + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + SafeArrayGetElement(psa, jIndices, &v); + env->ReleaseIntArrayElements(indices, jIndices, NULL); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BSTR))) { + return NULL; + } + BSTR bs = V_BSTR(&v); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + return js; + } else if (vt == VT_BSTR) { + BSTR bs = NULL; + SafeArrayGetElement(psa, jIndices, &bs); + env->ReleaseIntArrayElements(indices, jIndices, NULL); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs)); // SR cast SF 1689061 + return js; + } else { + ThrowComFail(env, "safearray cannot get string", 0); + env->ReleaseIntArrayElements(indices, jIndices, NULL); + return NULL; + } +} + + +/* + * Class: com_jacob_com_SafeArray + * Method: setStringjIndices, NULL);ILjava/lang/String;)V + * + * This method has a leak in it somewhere. + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString___3ILjava_lang_String_2 + (JNIEnv *env, jobject _this, jintArray indices, jstring s) +{ + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + // could have individually retrieved the indicies + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return; + } + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return; + } + + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + V_VT(&v) = VT_BSTR; + V_BSTR(&v) = bs.Copy(); + SafeArrayPutElement(sa, jIndices,&v); + env->ReleaseStringChars(s, str); + VariantClear(&v); + } else if (vt == VT_BSTR) { + // SF 2847577 support unicode move from GetStringUTFChars() to GetStringChars() + const jchar *str = env->GetStringChars(s, NULL); + CComBSTR bs((LPCOLESTR)str); + SafeArrayPutElement(sa, jIndices,bs.Detach()); + env->ReleaseStringChars(s, str); + } else { + ThrowComFail(env, "safearray cannot set string", 0); + } + // need to unpin the copied array SF: 1775889 + env->ReleaseIntArrayElements(indices, jIndices, NULL); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getByte + * Signature: ([I)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_UI1, V_UI1, jbyte) +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setByte + * Signature: ([IB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte___3IB + (JNIEnv *env, jobject _this, jintArray indices, jbyte c) +{ + SETNDCODE(VT_UI1, V_UI1); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getFloat + * Signature: ([I)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + GETNDCODE(VT_R4, V_R4, jfloat) +} + + +/* + * Class: com_jacob_com_SafeArray + * Method: setFloat + * Signature: ([IF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat___3IF + (JNIEnv *env, jobject _this, jintArray indices, jfloat c) +{ + SETNDCODE(VT_R4, V_R4); +} + +/* + * Class: com_jacob_com_SafeArray + * Method: getBoolean + * Signature: ([I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean___3I + (JNIEnv *env, jobject _this, jintArray indices) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return NULL; + } + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return NULL; + } + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return NULL; + } + + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + SafeArrayGetElement(sa, jIndices, (void*) &v); + env->ReleaseIntArrayElements(indices, jIndices, NULL); + if (FAILED(VariantChangeType(&v, &v, 0, VT_BOOL))) { + ThrowComFail(env, "safearray change type failed", -1); + return NULL; + } + jboolean jb = V_BOOL(&v) == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb; + SafeArrayGetElement(sa, jIndices, (void*) &vb); + env->ReleaseIntArrayElements(indices, jIndices, NULL); + jboolean jb = vb == VARIANT_TRUE ? JNI_TRUE: JNI_FALSE; + return jb; + } else { + env->ReleaseIntArrayElements(indices, jIndices, NULL); + return NULL; + } +} + +/* + * Class: com_jacob_com_SafeArray + * Method: setBoolean + * Signature: ([IZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean___3IZ + (JNIEnv *env, jobject _this, jintArray indices, jboolean c) +{ + // code is inline because of size mismatch + SAFEARRAY *sa = extractSA(env, _this); + if (!sa) { + ThrowComFail(env, "safearray object corrupted", -1); + return; + } + // ??? Not sure if this is correct type for call to SafeArrayGetElement() + jint *jIndices = env->GetIntArrayElements(indices, NULL); + + if (!jIndices) { + ThrowComFail(env, "null indices array", -1); + return; + } + if (SafeArrayGetDim(sa) != env->GetArrayLength(indices)) { + ThrowComFail(env, "safearray and indices array have different dimensions", -1); + return; + } + + VARTYPE vt; + SafeArrayGetVartype(sa, &vt); + if (vt == VT_VARIANT) { + VARIANT v; + VariantInit(&v); + V_VT(&v) = VT_BOOL; + V_BOOL(&v) = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,jIndices,&v); + } else if (vt == VT_BOOL) { + VARIANT_BOOL vb = c == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + SafeArrayPutElement(sa,jIndices,&vb); + } else { + ThrowComFail(env, "safearray type mismatch", -1); + } + env->ReleaseIntArrayElements(indices, jIndices, NULL); +} + + +} diff --git a/c/jacob/SafeArray.h b/c/jacob/SafeArray.h new file mode 100644 index 0000000..8695d56 --- /dev/null +++ b/c/jacob/SafeArray.h @@ -0,0 +1,940 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class com_jacob_com_SafeArray */ + +#ifndef _Included_com_jacob_com_SafeArray +#define _Included_com_jacob_com_SafeArray +#ifdef __cplusplus +extern "C" { +#endif +/* Inaccessible static: buildVersion */ +/* Inaccessible static: buildDate */ +/* Inaccessible static: DEBUG */ +/* Inaccessible static: class_00024com_00024jacob_00024com_00024JacobObject */ +/* + * Class: com_jacob_com_SafeArray + * Method: init + * Signature: (I[I[I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_init + (JNIEnv *, jobject, jint, jintArray, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: clone + * Signature: ()Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_clone + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: destroy + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_destroy + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getvt + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getvt + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: reinit + * Signature: (Lcom/jacob/com/SafeArray;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinit + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: reinterpretType + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_reinterpretType + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getLBound + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__ + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getLBound + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getLBound__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getUBound + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__ + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getUBound + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getUBound__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getNumDim + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getNumDim + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getFeatures + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getFeatures + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getElemSize + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getElemSize + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromCharArray + * Signature: ([C)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromCharArray + (JNIEnv *, jobject, jcharArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromIntArray + * Signature: ([I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromIntArray + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromLongArray + * Signature: ([L)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromLongArray + (JNIEnv *, jobject, jlongArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromShortArray + * Signature: ([S)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromShortArray + (JNIEnv *, jobject, jshortArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromDoubleArray + * Signature: ([D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromDoubleArray + (JNIEnv *, jobject, jdoubleArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromStringArray + * Signature: ([Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromStringArray + (JNIEnv *, jobject, jobjectArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromByteArray + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromByteArray + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromFloatArray + * Signature: ([F)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromFloatArray + (JNIEnv *, jobject, jfloatArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromBooleanArray + * Signature: ([Z)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromBooleanArray + (JNIEnv *, jobject, jbooleanArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: fromVariantArray + * Signature: ([Lcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_fromVariantArray + (JNIEnv *, jobject, jobjectArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: toCharArray + * Signature: ()[C + */ +JNIEXPORT jcharArray JNICALL Java_com_jacob_com_SafeArray_toCharArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toIntArray + * Signature: ()[I + */ +JNIEXPORT jintArray JNICALL Java_com_jacob_com_SafeArray_toIntArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toLongArray + * Signature: ()[L + */ +JNIEXPORT jlongArray JNICALL Java_com_jacob_com_SafeArray_toLongArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toShortArray + * Signature: ()[S + */ +JNIEXPORT jshortArray JNICALL Java_com_jacob_com_SafeArray_toShortArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toDoubleArray + * Signature: ()[D + */ +JNIEXPORT jdoubleArray JNICALL Java_com_jacob_com_SafeArray_toDoubleArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toStringArray + * Signature: ()[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toStringArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toByteArray + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_SafeArray_toByteArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toFloatArray + * Signature: ()[F + */ +JNIEXPORT jfloatArray JNICALL Java_com_jacob_com_SafeArray_toFloatArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toBooleanArray + * Signature: ()[Z + */ +JNIEXPORT jbooleanArray JNICALL Java_com_jacob_com_SafeArray_toBooleanArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: toVariantArray + * Signature: ()[Lcom/jacob/com/Variant; + */ +JNIEXPORT jobjectArray JNICALL Java_com_jacob_com_SafeArray_toVariantArray + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getChar + * Signature: (I)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getChar + * Signature: (II)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setChar + * Signature: (IC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IC + (JNIEnv *, jobject, jint, jchar); + +/* + * Class: com_jacob_com_SafeArray + * Method: setChar + * Signature: (IIC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar__IIC + (JNIEnv *, jobject, jint, jint, jchar); + +/* + * Class: com_jacob_com_SafeArray + * Method: getChars + * Signature: (II[CI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getChars + (JNIEnv *, jobject, jint, jint, jcharArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setChars + * Signature: (II[CI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChars + (JNIEnv *, jobject, jint, jint, jcharArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getInt + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getInt + * Signature: (II)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setInt + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setInt + * Signature: (III)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt__III + (JNIEnv *, jobject, jint, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getInts + * Signature: (II[II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getInts + (JNIEnv *, jobject, jint, jint, jintArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setInts + * Signature: (II[II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInts + (JNIEnv *, jobject, jint, jint, jintArray, jint); + +/* + * Class: SafeArray + * Method: getLong + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__I + (JNIEnv *env, jobject _this, jint idx); + +/* + * Class: SafeArray + * Method: getLong + * Signature: (II)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong__II + (JNIEnv *env, jobject _this, jint i, jint j); + +/* + * Class: SafeArray + * Method: setLong + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IJ + (JNIEnv *env, jobject _this, jint idx, jlong c); + +/* + * Class: SafeArray + * Method: setLong + * Signature: (IIJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong__IIJ + (JNIEnv *env, jobject _this, jint i, jint j, jlong c); + +/* + * Class: SafeArray + * Method: getLongs + * Signature: (II[JI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getLongs + (JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start); + +/* + * Class: SafeArray + * Method: setLongs + * Signature: (II[JI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLongs + (JNIEnv *env, jobject _this, jint idx, jint nelem, jlongArray ja, jint ja_start); + +/* + * Class: com_jacob_com_SafeArray + * Method: getShort + * Signature: (I)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getShort + * Signature: (II)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setShort + * Signature: (IS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IS + (JNIEnv *, jobject, jint, jshort); + +/* + * Class: com_jacob_com_SafeArray + * Method: setShort + * Signature: (IIS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort__IIS + (JNIEnv *, jobject, jint, jint, jshort); + +/* + * Class: com_jacob_com_SafeArray + * Method: getShorts + * Signature: (II[SI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getShorts + (JNIEnv *, jobject, jint, jint, jshortArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setShorts + * Signature: (II[SI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShorts + (JNIEnv *, jobject, jint, jint, jshortArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getDouble + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getDouble + * Signature: (II)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setDouble + * Signature: (ID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__ID + (JNIEnv *, jobject, jint, jdouble); + +/* + * Class: com_jacob_com_SafeArray + * Method: setDouble + * Signature: (IID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble__IID + (JNIEnv *, jobject, jint, jint, jdouble); + +/* + * Class: com_jacob_com_SafeArray + * Method: getDoubles + * Signature: (II[DI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getDoubles + (JNIEnv *, jobject, jint, jint, jdoubleArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setDoubles + * Signature: (II[DI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDoubles + (JNIEnv *, jobject, jint, jint, jdoubleArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getString + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getString + * Signature: (II)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setString + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__ILjava_lang_String_2 + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: com_jacob_com_SafeArray + * Method: setString + * Signature: (IILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__IILjava_lang_String_2 + (JNIEnv *, jobject, jint, jint, jstring); + +/* + * Class: com_jacob_com_SafeArray + * Method: getStrings + * Signature: (II[Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getStrings + (JNIEnv *, jobject, jint, jint, jobjectArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setStrings + * Signature: (II[Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setStrings + (JNIEnv *, jobject, jint, jint, jobjectArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getByte + * Signature: (I)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getByte + * Signature: (II)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setByte + * Signature: (IB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IB + (JNIEnv *, jobject, jint, jbyte); + +/* + * Class: com_jacob_com_SafeArray + * Method: setByte + * Signature: (IIB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte__IIB + (JNIEnv *, jobject, jint, jint, jbyte); + +/* + * Class: com_jacob_com_SafeArray + * Method: getBytes + * Signature: (II[BI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBytes + (JNIEnv *, jobject, jint, jint, jbyteArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setBytes + * Signature: (II[BI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBytes + (JNIEnv *, jobject, jint, jint, jbyteArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getFloat + * Signature: (I)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getFloat + * Signature: (II)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setFloat + * Signature: (IF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IF + (JNIEnv *, jobject, jint, jfloat); + +/* + * Class: com_jacob_com_SafeArray + * Method: setFloat + * Signature: (IIF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat__IIF + (JNIEnv *, jobject, jint, jint, jfloat); + +/* + * Class: com_jacob_com_SafeArray + * Method: getFloats + * Signature: (II[FI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getFloats + (JNIEnv *, jobject, jint, jint, jfloatArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setFloats + * Signature: (II[FI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloats + (JNIEnv *, jobject, jint, jint, jfloatArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getBoolean + * Signature: (I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getBoolean + * Signature: (II)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setBoolean + * Signature: (IZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IZ + (JNIEnv *, jobject, jint, jboolean); + +/* + * Class: com_jacob_com_SafeArray + * Method: setBoolean + * Signature: (IIZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IIZ + (JNIEnv *, jobject, jint, jint, jboolean); + +/* + * Class: com_jacob_com_SafeArray + * Method: getBooleans + * Signature: (II[ZI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getBooleans + (JNIEnv *, jobject, jint, jint, jbooleanArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setBooleans + * Signature: (II[ZI)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBooleans + (JNIEnv *, jobject, jint, jint, jbooleanArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getVariant + * Signature: (I)Lcom/jacob/com/Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__I + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getVariant + * Signature: (II)Lcom/jacob/com/Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setVariant + * Signature: (ILcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__ILcom_jacob_com_Variant_2 + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: setVariant + * Signature: (IILcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant__IILcom_jacob_com_Variant_2 + (JNIEnv *, jobject, jint, jint, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getVariants + * Signature: (II[Lcom/jacob/com/Variant;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_getVariants + (JNIEnv *, jobject, jint, jint, jobjectArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: setVariants + * Signature: (II[Lcom/jacob/com/Variant;I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariants + (JNIEnv *, jobject, jint, jint, jobjectArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getVariant + * Signature: ([I)Lcom/jacob/com/Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_SafeArray_getVariant___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setVariant + * Signature: ([ILcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setVariant___3ILcom_jacob_com_Variant_2 + (JNIEnv *, jobject, jintArray, jobject); + +/* + * Class: com_jacob_com_SafeArray + * Method: getChar + * Signature: ([I)C + */ +JNIEXPORT jchar JNICALL Java_com_jacob_com_SafeArray_getChar___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setChar + * Signature: ([IC)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setChar___3IC + (JNIEnv *, jobject, jintArray, jchar); + +/* + * Class: com_jacob_com_SafeArray + * Method: getInt + * Signature: ([I)I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_SafeArray_getInt___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setInt + * Signature: ([II)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setInt___3II + (JNIEnv *, jobject, jintArray, jint); + +/* + * Class: com_jacob_com_SafeArray + * Method: getLong + * Signature: ([I)J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_SafeArray_getLong___3I + (JNIEnv *env, jobject _this, jintArray indices); + +/* + * Class: com_jacob_com_SafeArray + * Method: setLong + * Signature: ([IJ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setLong___3IJ + (JNIEnv *env, jobject _this, jintArray indices, jlong c); + + +/* + * Class: com_jacob_com_SafeArray + * Method: getShort + * Signature: ([I)S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_SafeArray_getShort___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setShort + * Signature: ([IS)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setShort___3IS + (JNIEnv *, jobject, jintArray, jshort); + +/* + * Class: com_jacob_com_SafeArray + * Method: getDouble + * Signature: ([I)D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_SafeArray_getDouble___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setDouble + * Signature: ([ID)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setDouble___3ID + (JNIEnv *, jobject, jintArray, jdouble); + +/* + * Class: com_jacob_com_SafeArray + * Method: getString + * Signature: ([I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_SafeArray_getString___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setString + * Signature: ([ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString___3ILjava_lang_String_2 + (JNIEnv *, jobject, jintArray, jstring); + +/* + * Class: com_jacob_com_SafeArray + * Method: getByte + * Signature: ([I)B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_SafeArray_getByte___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setByte + * Signature: ([IB)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setByte___3IB + (JNIEnv *, jobject, jintArray, jbyte); + +/* + * Class: com_jacob_com_SafeArray + * Method: getFloat + * Signature: ([I)F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_SafeArray_getFloat___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setFloat + * Signature: ([IF)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setFloat___3IF + (JNIEnv *, jobject, jintArray, jfloat); + +/* + * Class: com_jacob_com_SafeArray + * Method: getBoolean + * Signature: ([I)Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean___3I + (JNIEnv *, jobject, jintArray); + +/* + * Class: com_jacob_com_SafeArray + * Method: setBoolean + * Signature: ([IZ)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean___3IZ + (JNIEnv *, jobject, jintArray, jboolean); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/StdAfx.h b/c/jacob/StdAfx.h new file mode 100644 index 0000000..9d3d322 --- /dev/null +++ b/c/jacob/StdAfx.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, +// but are changed infrequently + +#if !defined(AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED_) +#define AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef STRICT +#define STRICT +#endif +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0400 +#endif +//#define _ATL_APARTMENT_THREADED +#include +#include +#include +#include +//You may derive a class from CComModule and use it if you want to override +//something, but do not change the name of _Module +extern CComModule _Module; +//#include + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__9988E984_6789_11D3_A646_000000000000__INCLUDED) diff --git a/c/jacob/Variant.cpp b/c/jacob/Variant.cpp new file mode 100644 index 0000000..6b20d09 --- /dev/null +++ b/c/jacob/Variant.cpp @@ -0,0 +1,1274 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "stdafx.h" +#include "Variant.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +#define VARIANT_FLD "m_pVariant" + +// extract a VARIANT from a Variant object +VARIANT *extractVariant(JNIEnv *env, jobject arg) +{ + jclass argClass = env->GetObjectClass(arg); + jfieldID ajf = env->GetFieldID( argClass, VARIANT_FLD, "I"); + jint anum = env->GetIntField(arg, ajf); + VARIANT *v = (VARIANT *)anum; + return v; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_release + (JNIEnv *env, jobject _this) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I"); + VARIANT *v = extractVariant(env, _this); + if (v) { + // fix byref leak + if (V_VT(v) & VT_BYREF) // is this a reference + { + void *pMem = V_BSTRREF(v); // get allocated memory + if (pMem) + { + if (V_VT(v) == (VT_BYREF|VT_BSTR)) + { + BSTR *pBstr = (BSTR*)pMem; + if (*pBstr) + SysFreeString(*pBstr);// release bstr + } + CoTaskMemFree(pMem); + } + } + VariantClear(v); + delete v; + env->SetIntField(_this, jf, (unsigned int)0); + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init + (JNIEnv *env, jobject _this) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID( clazz, VARIANT_FLD, "I"); + VARIANT *v = new VARIANT(); + VariantInit(v); + env->SetIntField(_this, jf, (unsigned int)v); +} + + +/* + * Class: com_jacob_com_Variant + * Method: zeroVariant + * Signature: ()V + * + * This should only be used on variant objects created by the + * com layer as part of a call through EventProxy. + * This zeros out the variant pointer in the Variant object + * so that the calling COM program can free the memory. + * instead of both the COM program and the Java GC doing it. + */ +void zeroVariant(JNIEnv *env, jobject _this) +{ + jclass clazz = env->GetObjectClass(_this); + jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I"); + env->SetIntField(_this, jf, (unsigned int)0); +} + + +/** + * This is the core of the old Save method. + * It copies this variant to a byte stream. + * The unmarshalling part of this doesn't work but it was left in + * with the hope that someone will want to fix this later + **/ +JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_Variant_SerializationWriteToBytes + (JNIEnv *env, jobject _this){ + VARIANT *v = extractVariant(env, _this); + if (v) + { + DWORD flags = MSHCTX_LOCAL; + jint size = VARIANT_UserSize(&flags, 0L, v); + // allocate a byte array of the right length + jbyte* pBuf = new jbyte[size]; + // clear it out + ZeroMemory(pBuf, size); + // marshall the Variant into the buffer + VARIANT_UserMarshal(&flags, (unsigned char *)pBuf, v); + // need to convert the buffer to a java byte ba[] + jbyteArray ba = env->NewByteArray(size); + env->SetByteArrayRegion(ba, 0, size, pBuf); + // and delete the original memory + delete [] pBuf; + return ba; + } else { + jbyteArray ba = env->NewByteArray(0); + return ba; + } + } + +/** + * This is the core of the old Load method. It is broken because the + * unmarshalling code doesn't work under 2000/XP. + * + * It probably needs a custom handler. + **/ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_SerializationReadFromBytes + (JNIEnv *env, jobject _this, jbyteArray ba){ + + VARIANT *v = extractVariant(env, _this); + if (v){ + // get a buffer from it + jbyte *pBuf = env->GetByteArrayElements(ba, 0); + // unmarshall the Variant from the buffer + DWORD flags = MSHCTX_LOCAL; + printf("about to unmarshall array elements\n"); + VARIANT_UserUnmarshal(&flags, (unsigned char *)pBuf, v); + // release the byte array + printf("about to release array elements\n"); + env->ReleaseByteArrayElements(ba, pBuf, 0); + } + } + +/** + * Converts the data to a Enum Variant object and then returns it as a Dispatch + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toEnumVariant + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) + { + HRESULT hr; + if (FAILED(hr = VariantChangeType(v, v, 0, VT_UNKNOWN))) { + ThrowComFail(env, "VariantChangeType failed", hr); + return NULL; + } + jclass autoClass = env->FindClass("com/jacob/com/EnumVariant"); + jmethodID autoCons = + env->GetMethodID(autoClass, "", "(I)V"); + // construct an Unknown object to return + IUnknown *unk = V_UNKNOWN(v); + IEnumVARIANT *ie; + hr = unk->QueryInterface(IID_IEnumVARIANT, (void **)&ie); + if (FAILED(hr)) { + ThrowComFail(env, "[toEnumVariant]: Object does not implement IEnumVariant", hr); + return NULL; + } + // I am copying the pointer to java + // SF-1674179 fix EnumVariants memory leak + // AJ: yes, but the QueryInterface call above already incremented the reference + //if (ie) ie->AddRef(); + jobject newAuto = env->NewObject(autoClass, autoCons, ie); + return newAuto; + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNull + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_NULL; + } +} + +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_cloneIndirect + (JNIEnv *env, jobject _this) +{ + return NULL; +} + + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShortRef + (JNIEnv *env, jobject _this, jshort s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + short *ps = (short *)CoTaskMemAlloc(sizeof(short)); + *ps = s; + V_VT(v) = VT_I2|VT_BYREF; + V_I2REF(v) = ps; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantIntRef + (JNIEnv *env, jobject _this, jint s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + long *ps = (long *)CoTaskMemAlloc(sizeof(long)); + *ps = s; + V_VT(v) = VT_I4|VT_BYREF; + V_I4REF(v) = ps; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDoubleRef + (JNIEnv *env, jobject _this, jdouble s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + double *ps = (double *)CoTaskMemAlloc(sizeof(double)); + *ps = s; + V_VT(v) = VT_R8|VT_BYREF; + V_R8REF(v) = ps; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDateRef + (JNIEnv *env, jobject _this, jdouble s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + double *ps = (double *)CoTaskMemAlloc(sizeof(double)); + *ps = s; + V_VT(v) = VT_DATE|VT_BYREF; + V_DATEREF(v) = ps; + } +} + +// SF 1065533 added unicode support +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantStringRef + (JNIEnv *env, jobject _this, jstring s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + + const jchar *cStr = env->GetStringChars(s,NULL); + // SF 1314116 + // DBeck: 2005-09-23: changed CComBSTR c-tor to accept + // Unicode string (no terminating NULL) provided by GetStringChars + const jsize numChars = env->GetStringLength(s); + //CComBSTR bs(cStr); + CComBSTR bs( numChars, (LPCOLESTR)cStr ); // SR cast SF 1689061 + + BSTR *pbs = (BSTR *)CoTaskMemAlloc(sizeof(BSTR)); + bs.CopyTo(pbs); + V_VT(v) = VT_BSTR|VT_BYREF; + V_BSTRREF(v) = pbs; + + env->ReleaseStringChars(s,cStr); } +} + +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShortRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_I2|VT_BYREF)) { + return NULL; + } + return (jshort)*V_I2REF(v); + } + return NULL; +} + +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantIntRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_I4|VT_BYREF)) { + return NULL; + } + return (jint)*V_I4REF(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShort + (JNIEnv *env, jobject _this, jshort s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_I2; + V_I2(v) = (short)s; + } +} + +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShort + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_I2) { + return NULL; + } + return (jshort)V_I2(v); + } + return NULL; +} + +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDoubleRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_R8|VT_BYREF)) { + return NULL; + } + return (jdouble)*V_R8REF(v); + } + return NULL; +} + +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDateRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_DATE|VT_BYREF)) { + return NULL; + } + return (jdouble)*V_DATEREF(v); + } + return NULL; +} + +JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantStringRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_BSTR|VT_BYREF)) { + return NULL; + } + BSTR *bs = V_BSTRREF(v); + jstring js = env->NewString((jchar*)*bs, SysStringLen(*bs)); // SR cast SF 1689061 + return js; + } + return NULL; +} + +/** + * cover for underlying C VariantClear function + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_VariantClear + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); + } +} + +/** + * Converts the data to a Dispatch object and then returns it as a Dispatch + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantDispatch + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + HRESULT hr; + if (FAILED(hr = VariantChangeType(v, v, 0, VT_DISPATCH))) { + ThrowComFail(env, "VariantChangeType failed", hr); + return NULL; + } + jclass autoClass = env->FindClass("com/jacob/com/Dispatch"); + jmethodID autoCons = + env->GetMethodID(autoClass, "", "(I)V"); + // construct a Dispatch object to return + IDispatch *disp = V_DISPATCH(v); + // I am copying the pointer to java + if (disp) disp->AddRef(); + jobject newAuto = env->NewObject(autoClass, autoCons, disp); + return newAuto; + } + return NULL; +} + +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_clone + (JNIEnv *env, jobject _this) +{ + return NULL; +} + +/** + * Returns the value of this int as a Boolea if it is of that type. + * Otherwise it will return null (no conversion done) + */ + +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantInt + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_I4) { + return NULL; + } + return (jint)V_I4(v); + } + return NULL; +} + +/** + * Returns the value of this Date as a Boolea if it is of that type. + * Otherwise it will return null (no conversion done) + */ + +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDate + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_DATE) { + return NULL; + } + return (jdouble)V_DATE(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantInt + (JNIEnv *env, jobject _this, jint i) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_I4; + V_I4(v) = (int)i; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDate + (JNIEnv *env, jobject _this, jdouble date) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_DATE; + V_DATE(v) = date; + } +} + +/** + * Returns the value of this Variant as a Boolea if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBoolean + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_BOOL)) { + return NULL; + } + return (jboolean)V_BOOL(v); + } + return NULL; +} + +/** + * Returns the value of this Variant as a Byte if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByte + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_UI1)) { + return NULL; + } + return (jbyte)V_UI1(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBoolean + (JNIEnv *env, jobject _this, jboolean b) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_BOOL; + V_BOOL(v) = b == JNI_TRUE ? VARIANT_TRUE : VARIANT_FALSE; + } + else ThrowComFail(env, "putVariantBoolean failed", -1); +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByte + (JNIEnv *env, jobject _this, jbyte b) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_UI1; + V_UI1(v) = b; + } + else ThrowComFail(env, "putVariantByte failed", -1); +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantEmpty + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_EMPTY; + } +} + +/** + * Sets the variant type to dispatch with no value object + **/ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNothing + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_DISPATCH; + } +} + +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantError + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_ERROR) { + return NULL; + } + return (jint)V_ERROR(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantError + (JNIEnv *env, jobject _this, jint i) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_ERROR; + V_ERROR(v) = (int)i; + } +} + + +/** + * Returns the value of this Variant as a double if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDouble + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_R8) { + return NULL; + } + return (jdouble)V_R8(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency + (JNIEnv *env, jobject _this, jlong cur) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + CY pf; + pf.int64 = (LONGLONG)cur; + V_VT(v) = VT_CY; + V_CY(v) = pf; + } else ThrowComFail(env, "putVariantCurrency failed", -1); +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLong + (JNIEnv *env, jobject _this, jlong longValue) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_I8; + V_I8(v) = (LONGLONG)longValue; + } else ThrowComFail(env, "putVariantLong failed", -1); +} + +/** + * Accepts a dispatch object and sets the type to VT_DISPATCH. + * There is currently no way to pass NULL into this method + * to create something like "NOTHING" from VB + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDispatch + (JNIEnv *env, jobject _this, jobject _that) +{ + VARIANT *v = extractVariant(env, _this); + IDispatch *disp = extractDispatch(env, _that); + if (disp && v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_DISPATCH; + V_DISPATCH(v) = disp; + // I am handing the pointer to COM + disp->AddRef(); + } else ThrowComFail(env, "putObject failed", -1); +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDouble + (JNIEnv *env, jobject _this, jdouble d) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_R8; + V_R8(v) = (double)d; + } +} + +/** + * Returns the value of this Variant as a long if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_CY) { + return NULL; + } + CY cy; + cy = V_CY(v); + jlong jl; + memcpy(&jl, &cy, sizeof(jl)); // was 64. should be sizeof(x) SF 1690420 + return jl; + } + return NULL; +} + +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLong + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_I8) { + return NULL; + } + return (jlong)V_I8(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef + (JNIEnv *env, jobject _this, jfloat val) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + float *pf = (float *)CoTaskMemAlloc(sizeof(float)); + *pf = val; + V_VT(v) = VT_R4|VT_BYREF; + V_R4REF(v) = pf; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef + (JNIEnv *env, jobject _this, jlong cur) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + CY *pf = (CY *)CoTaskMemAlloc(sizeof(CY)); + memcpy(pf, &cur, sizeof(*pf)); // was 64. should be sizeof(x) SF 1690420 + V_VT(v) = VT_BYREF|VT_CY; + V_CYREF(v) = pf; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLongRef + (JNIEnv *env, jobject _this, jlong longValue) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + LONGLONG *ps = (LONGLONG *)CoTaskMemAlloc(sizeof(LONGLONG)); + *ps = longValue; + V_VT(v) = VT_I8|VT_BYREF; + V_I8REF(v) = ps; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantErrorRef + (JNIEnv *env, jobject _this, jint i) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_ERROR|VT_BYREF; + V_ERROR(v) = (int)i; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBooleanRef + (JNIEnv *env, jobject _this, jboolean b) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + VARIANT_BOOL *br = (VARIANT_BOOL *)CoTaskMemAlloc(sizeof(VARIANT_BOOL)); + *br = b ? VARIANT_TRUE : VARIANT_FALSE; + V_VT(v) = VT_BOOL|VT_BYREF; + V_BOOLREF(v) = br; + } +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByteRef + (JNIEnv *env, jobject _this, jbyte b) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + unsigned char *br = (unsigned char *)CoTaskMemAlloc(sizeof(char)); + *br = b; + V_VT(v) = VT_UI1|VT_BYREF; + V_UI1REF(v) = br; + } +} + +/** + * Returns the value of this Variant as a String if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantString + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_BSTR) { + return NULL; + } + BSTR bs = V_BSTR(v); + jstring js = env->NewString((jchar*)bs, SysStringLen(bs));// SR cast SF 1689061 + return js; + } + return NULL; +} + +/** + * SF 1065533 added unicode support + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantString + (JNIEnv *env, jobject _this, jstring s) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_BSTR; + + const jchar *cStr = env->GetStringChars(s,NULL); + // SF 1314116 + // DBeck: 2005-09-23: changed CComBSTR c-tor to accept + // Unicode string (no terminating NULL) provided by GetStringChars + const jsize numChars = env->GetStringLength(s); + //CComBSTR bs(cStr); + CComBSTR bs( numChars, (LPCOLESTR)cStr ); // SR cast SF 1689061 + + V_VT(v) = VT_BSTR; + V_BSTR(v) = bs.Copy(); + + env->ReleaseStringChars(s,cStr); + } +} + +JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloatRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_R4|VT_BYREF)) { + return NULL; + } + return (jfloat)*V_R4REF(v); + } + return NULL; +} + +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_CY|VT_BYREF)) { + return NULL; + } + CY *cy; + cy = V_CYREF(v); + jlong jl; + memcpy(&jl, cy, sizeof(jl)); // was 64. should be sizeof(x) SF 1690420 + return jl; + } + return NULL; +} + +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLongRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_I8|VT_BYREF)) { + return NULL; + } + return (jlong)*V_I8REF(v); + } + return NULL; +} + +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantErrorRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_ERROR|VT_BYREF)) { + return NULL; + } + return (jint)V_ERROR(v); + } + return NULL; +} + +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBooleanRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_BOOL|VT_BYREF)) { + return NULL; + } + return (jboolean)*V_BOOLREF(v); + } + return NULL; +} + + +JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByteRef + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_UI1|VT_BYREF)) { + return NULL; + } + return (jbyte)*V_UI1REF(v); + } + return NULL; +} + +/** + * Converts the data to a Safe Array object and then returns it as a Dispatch + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantSafeArray + (JNIEnv *env, jobject _this, jboolean deepCopy) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if ((V_VT(v) & VT_ARRAY) == 0) + { + ThrowComFail(env, "Variant not array", -1); + return NULL; + } + // prepare a new sa obj + jclass saClass = env->FindClass("com/jacob/com/SafeArray"); + jmethodID saCons = env->GetMethodID(saClass, "", "()V"); + // construct an SA to return + jobject newSA = env->NewObject(saClass, saCons); + // pass in the deep copy indicator + setSA(env, newSA, V_ARRAY(v), deepCopy == JNI_TRUE ? 1 : 0); + return newSA; + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantSafeArrayRef + (JNIEnv *env, jobject _this, jobject sa) +{ + SAFEARRAY *psa = extractSA(env, sa); + if (psa) + { + VARIANT *v = extractVariant(env, _this); + if (v) { + VARTYPE vt; + SAFEARRAY **sa = (SAFEARRAY **)CoTaskMemAlloc(sizeof(SAFEARRAY*)); + *sa = psa; + SafeArrayGetVartype(psa, &vt); + V_VT(v) = VT_ARRAY | vt | VT_BYREF; + V_ARRAYREF(v) = sa; + return; + } + ThrowComFail(env, "Can't get variant pointer", -1); + return; + } + ThrowComFail(env, "Can't get sa pointer", -1); + return; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantSafeArray + (JNIEnv *env, jobject _this, jobject sa) +{ + SAFEARRAY *psa = extractSA(env, sa); + if (psa) + { + VARIANT *v = extractVariant(env, _this); + if (v) { + VARTYPE vt; + SafeArrayGetVartype(psa, &vt); + V_VT(v) = VT_ARRAY | vt; + V_ARRAY(v) = copySA(psa); + return; + } + ThrowComFail(env, "Can't get variant pointer", -1); + return; + } + ThrowComFail(env, "Can't get sa pointer", -1); + return; +} + +/** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNoParam + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + V_VT(v) = VT_ERROR; + V_ERROR(v) = DISP_E_PARAMNOTFOUND; + } +} + +/** + * Returns the value of this Variant as a Float if it is of that type. + * Otherwise it will return null (no conversion done) + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloat + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_R4)) { + return NULL; + } + return (jfloat)V_R4(v); + } + return NULL; +} + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloat + (JNIEnv *env, jobject _this, jfloat val) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + V_VT(v) = VT_R4; + V_R4(v) = val; + } +} + +/** + * changes the type of the underlying variant data + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeVariantType + (JNIEnv *env, jobject _this, jshort t) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantChangeType(v, v, 0, t); + } +} + +/** + * returns the variant type if it is set, otherwise + * returns null + * */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantType + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (v) { + return (jshort)V_VT(v); + } + return NULL; +} + +// removed Java_com_jacob_com_Variant_putSafeArrayRefHelper + +/** + * this is a big cover method that returns TRUE if + * the variant type is + * VT_EMPTY, VT_NULL, VT_ERROR or VT_DISPATCH with no dispatch object + * */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isVariantConsideredNull + (JNIEnv *env, jobject _this) +{ + VARIANT *v = extractVariant(env, _this); + if (!v) return JNI_TRUE; + if ((V_VT(v) & VT_ARRAY)) + { + // is it a null safearray + // prior to 4 Dec 2005 the squiggle brackets were missing + // so this did the wrong thing for the else statement + if ((V_VT(v) & VT_BYREF)) { + if (!V_ARRAYREF(v)) return JNI_TRUE; + } else { + if (!V_ARRAY(v)) return JNI_TRUE; + } + } + switch (V_VT(v)) + { + case VT_EMPTY: + case VT_NULL: + case VT_ERROR: + return JNI_TRUE; + // is it a null dispatch (Nothing in VB) + case VT_DISPATCH: + if (!V_DISPATCH(v)) return JNI_TRUE; + } + return JNI_FALSE; +} + +/** + * Puts a variant into a the Variant as its data and sets the type + * to VT_VARIANT|VT_BYREF. + * Added 1.12 pre 6 + * + * */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantVariant + (JNIEnv *env, jobject _this, jobject var) +{ + + VARIANT *vVar = extractVariant(env, var); + VARIANT *v = extractVariant(env, _this); + + if (v) { + VariantClear(v); // whatever was there before + + V_VT(v) = VT_VARIANT|VT_BYREF; + V_VARIANTREF(v) = vVar; + } + +} + +/** + * retrieves the enclosed variant when they are of type VT_VARIANT + * Added 1.12 pre 6 + * + * */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant +(JNIEnv *env, jobject _this) +{ + + VARIANT *v = extractVariant(env, _this); + if (v) { + + if (V_VT(v) != (VT_VARIANT|VT_BYREF)) { + return NULL; + } + + VARIANT *refVar = V_VARIANTREF(v); + + // we could have made a copy of refV here but we aren't every going to free + // it outside of the scope of the enclosing context so we will just used the + // enclosed. This relies on the java layer to zero out its ref to this + // enclosed variant before the gc can come along and free the memory out from + // under this enclosing variant. + return (unsigned int)refVar; + } + + return NULL; +} + + /** + * puts a VT_DECIMAL by reference + * Added 1.13M4 + * */ + JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDecRef + (JNIEnv *env, jobject _this, jint signum, jbyte scale, jint lo, jint mid, jint hi) + { + VARIANT *v = extractVariant(env, _this); + if (v) { + VariantClear(v); // whatever was there before + DECIMAL *pd = (DECIMAL *)CoTaskMemAlloc(sizeof(DECIMAL)); + pd->scale = scale; + if (signum == 1 || signum == 0){ + pd->sign = 0; + } else { + pd->sign = 0x80; + } + pd->Hi32 = hi; + pd->Mid32 = mid; + pd->Lo32 = lo; + V_VT(v) = VT_DECIMAL | VT_BYREF; + V_DECIMALREF(v) = pd; + } + } + + + /** + * puts a VT_DECIMAL + * Added 1.13M4 + * */ + JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDec + (JNIEnv *env, jobject _this, jint signum, jbyte scale, jint lo, jint mid, jint hi) + { + VARIANT *v = extractVariant(env, _this); + DECIMAL *d; + if (v) { + VariantClear(v); // whatever was there before + d = (DECIMAL*)v; + d->scale = scale; + if (signum == 1 || signum == 0){ + d->sign = 0; + } else { + d->sign = 0x80; + } + d->Hi32 = hi; + d->Mid32 = mid; + d->Lo32 = lo; + V_VT(v) = VT_DECIMAL; + } + } + +/** + * utility method used by the getVariantXXX() methods to convert VT_DECIMAL to BigDecimal + * */ +jobject extractDecimal + (JNIEnv *env, DECIMAL* d) + { + jclass bigIntegerClass; + jclass bigDecimalClass; + jobject integer; + jmethodID bigIntegerConstructor; + jmethodID bigDecimalConstructor; + jbyteArray bArray; + jobject result = NULL; + jbyte* buffer; + + bigIntegerClass = env->FindClass("java/math/BigInteger"); + if (bigIntegerClass == NULL) + return NULL; + bigDecimalClass = env->FindClass("java/math/BigDecimal"); + if (bigDecimalClass == NULL) { + env->DeleteLocalRef(bigIntegerClass); + return NULL; + } + + bigIntegerConstructor = env->GetMethodID(bigIntegerClass, "", "(I[B)V"); + if (bigIntegerConstructor == NULL) { + env->DeleteLocalRef(bigIntegerClass); + env->DeleteLocalRef(bigDecimalClass); + return NULL; + } + bigDecimalConstructor = env->GetMethodID(bigDecimalClass, "", "(Ljava/math/BigInteger;I)V"); + if (bigIntegerConstructor == NULL) { + env->DeleteLocalRef(bigIntegerClass); + env->DeleteLocalRef(bigDecimalClass); + return NULL; + } + bArray = env->NewByteArray(12); + if (bArray == NULL) { + env->DeleteLocalRef(bigIntegerClass); + env->DeleteLocalRef(bigDecimalClass); + return NULL; + } + /* Unfortunately the byte ordering is completely wrong, so we remap it into buffer */ + buffer = (jbyte*)malloc(12); + buffer[11] = (byte)(d->Lo32 & 255); + buffer[10] = (byte)((d->Lo32 >> 8) & 255); + buffer[9] = (byte)((d->Lo32 >> 16) & 255); + buffer[8] = (byte)((d->Lo32 >> 24) & 255); + buffer[7] = (byte)((d->Mid32) & 255); + buffer[6] = (byte)((d->Mid32 >> 8) & 255); + buffer[5] = (byte)((d->Mid32 >> 16) & 255); + buffer[4] = (byte)((d->Mid32 >> 24) & 255); + buffer[3] = (byte)((d->Hi32) & 255); + buffer[2] = (byte)((d->Hi32 >> 8) & 255); + buffer[1] = (byte)((d->Hi32 >> 16) & 255); + buffer[0] = (byte)((d->Hi32 >> 24) & 255); + /* Load buffer into the actual array */ + env->SetByteArrayRegion(bArray, 0, 12, buffer); + /* then clean up the C array */ + free(buffer); + + /* instantiate the BigInteger */ + integer = env->NewObject(bigIntegerClass, bigIntegerConstructor, d->sign == 0x80?-1:1, bArray); + + result = env->NewObject(bigDecimalClass, bigDecimalConstructor, integer, (jint)(d->scale)); + + /* Clean up the Java global references */ + env->DeleteLocalRef(bArray); + env->DeleteLocalRef(integer); + env->DeleteLocalRef(bigIntegerClass); + return result; + } + +/** + * gets a VT_DECIMAL by ref as a BigDecimal + * Added 1.13M4 + * */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDecRef + (JNIEnv *env, jobject _this) + { + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != (VT_DECIMAL|VT_BYREF)) { + return NULL; + } + return extractDecimal(env, v->pdecVal); + } + return NULL; + } + +/** + * gets a VT_DECIMAL as a BigDecimal + * Added 1.13M4 + * */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDec + (JNIEnv *env, jobject _this) + { + VARIANT *v = extractVariant(env, _this); + if (v) { + if (V_VT(v) != VT_DECIMAL) { + return NULL; + } + return extractDecimal(env, (DECIMAL*)v); + } + return NULL; + } + +} diff --git a/c/jacob/Variant.h b/c/jacob/Variant.h new file mode 100644 index 0000000..d2293c2 --- /dev/null +++ b/c/jacob/Variant.h @@ -0,0 +1,605 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +/* Header for class com_jacob_com_Variant */ + +#ifndef _Included_com_jacob_com_Variant +#define _Included_com_jacob_com_Variant +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: com_jacob_com_Variant + * Method: toEnumVariant + * Signature: ()Lcom/jacob/com/EnumVariant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toEnumVariant + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantNull + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNull + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: cloneIndirect + * Signature: ()Lcom_jacob_com_Variant; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_cloneIndirect + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantShortRef + * Signature: (S)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShortRef + (JNIEnv *, jobject, jshort); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantIntRef + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantIntRef + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDoubleRef + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDoubleRef + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDateRef + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDateRef + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantStringRef + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantStringRef + (JNIEnv *, jobject, jstring); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantShortRef + * Signature: ()S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShortRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantIntRef + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantIntRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantShort + * Signature: (S)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantShort + (JNIEnv *, jobject, jshort); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantShort + * Signature: ()S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantShort + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDoubleRef + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDoubleRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDateRef + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDateRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getStringRef + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantStringRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: com_jacob_com_VariantClear + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_VariantClear + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: toDispatch + * Signature: ()LDispatch; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantDispatch + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: clone + * Signature: ()Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_clone + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantInt + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantInt + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDate + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDate + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantInt + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantInt + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDate + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDate + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantBoolean + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBoolean + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantByte + * Signature: ()B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByte + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantBoolean + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBoolean + (JNIEnv *, jobject, jboolean); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantByte + * Signature: (B)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByte + (JNIEnv *, jobject, jbyte); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantEmpty + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantEmpty + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantNothing + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNothing + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantError + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantError + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantError + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantError + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDouble + * Signature: ()D + */ +JNIEXPORT jdouble JNICALL Java_com_jacob_com_Variant_getVariantDouble + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantCurrency + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrency + (JNIEnv *, jobject, jlong); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantLong + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLong + (JNIEnv *, jobject, jlong); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDispatch + * Signature: (Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDispatch + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDouble + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDouble + (JNIEnv *, jobject, jdouble); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantCurrency + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrency + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantLong + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLong + (JNIEnv *, jobject); +/* + * Class: com_jacob_com_Variant + * Method: putVariantFloatRef + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloatRef + (JNIEnv *, jobject, jfloat); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantCurrencyRef + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantCurrencyRef + (JNIEnv *, jobject, jlong); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantLongRef + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantLongRef + (JNIEnv *, jobject, jlong); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantErrorRef + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantErrorRef + (JNIEnv *, jobject, jint); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantBooleanRef + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantBooleanRef + (JNIEnv *, jobject, jboolean); + +/* + * Class: com_jacob_com_Variant + * Method: putObjectRef + * Signature: (Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putObjectRef + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantByteRef + * Signature: (B)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantByteRef + (JNIEnv *, jobject, jbyte); + +/* + * Class: com_jacob_com_Variant + * Method: getString + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getVariantString + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantString + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantString + (JNIEnv *, jobject, jstring); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantFloatRef + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloatRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantCurrencyRef + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantCurrencyRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantLongRef + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_jacob_com_Variant_getVariantLongRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantErrorRef + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantErrorRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantBooleanRef + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_getVariantBooleanRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantByteRef + * Signature: ()B + */ +JNIEXPORT jbyte JNICALL Java_com_jacob_com_Variant_getVariantByteRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: toVariantSafeArray + * Signature: (Z)Lcom/jacob/com/SafeArray; + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_toVariantSafeArray + (JNIEnv *, jobject, jboolean); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantSafeArrayRef + * Signature: (LSafeArray;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantSafeArrayRef + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantSafeArray + * Signature: (LSafeArray;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantSafeArray + (JNIEnv *, jobject, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantNoParam + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantNoParam + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantFloat + * Signature: ()F + */ +JNIEXPORT jfloat JNICALL Java_com_jacob_com_Variant_getVariantFloat + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantFloat + * Signature: (F)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantFloat + (JNIEnv *, jobject, jfloat); + +/* + * Class: com_jacob_com_Variant + * Method: changeVariantType + * Signature: (S)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_changeVariantType + (JNIEnv *, jobject, jshort); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantType + * Signature: ()S + */ +JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getVariantType + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: release + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_release + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init + (JNIEnv *, jobject); + +JNIEXPORT jbyteArray JNICALL Java_com_jacob_com_Variant_SerializationWriteToBytes + (JNIEnv *, jobject); + +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_SerializationReadFromBytes + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantVariant + * Signature: (Lcom/jacob/com/Variant;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantVariant + (JNIEnv *, jobject, jobject); + + +/* + * Class: com_jacob_com_Variant + * Method: getVariantVariant + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_com_jacob_com_Variant_getVariantVariant + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDecRef + * Signature: (Ljava.math.BigDecimal;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDecRef + (JNIEnv *env, jobject _this, jint signum, jbyte scale, jint lo, jint mid, jint hi); + + +/* + * Class: com_jacob_com_Variant + * Method: putVariantDec + * Signature: (Ljava.math.BigDecimal;)V + */ +JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putVariantDec + (JNIEnv *env, jobject _this, jint signum, jbyte scale, jint lo, jint mid, jint hi); + + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDecRef + * Signature: ()Ljava.math.BigDecimal + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDecRef + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: getVariantDec + * Signature: ()Ljava.math.BigDecimal + */ +JNIEXPORT jobject JNICALL Java_com_jacob_com_Variant_getVariantDec + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: isVariantConsideredNull + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isVariantConsideredNull + (JNIEnv *, jobject); + +/* + * Class: com_jacob_com_Variant + * Method: zeroVariant + * Signature: ()V + * + * This should only be used on variant objects created by the + * com layer as part of a call through EventProxy. + * This zeros out the variant pointer in the Variant object + * so that the calling COM program can free the memory. + * instead of both the COM program and the Java GC doing it. + */ +void zeroVariant (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/jacob/include/atlalloc.h b/c/jacob/include/atlalloc.h new file mode 100644 index 0000000..8bd1006 --- /dev/null +++ b/c/jacob/include/atlalloc.h @@ -0,0 +1,764 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#pragma once +#ifndef __ATLALLOC_H__ +#define __ATLALLOC_H__ +#endif + +#include +#include + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ + +/* +This is more than a little unsatisfying. /Wp64 warns when we convert a size_t to an int +because it knows such a conversion won't port. +But, when we have overloaded templates, there may well exist both conversions and we need +to fool the warning into not firing on 32 bit builds +*/ +#if !defined(_ATL_W64) +#if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) +#define _ATL_W64 __w64 +#else +#define _ATL_W64 +#endif +#endif + +/* Can't use ::std::numeric_limits here because we don't want to introduce a new + deprendency of this code on SCL +*/ + +template +class AtlLimits; + +template<> +class AtlLimits +{ +public: + static const int _Min=INT_MIN; + static const int _Max=INT_MAX; +}; + +template<> +class AtlLimits +{ +public: + static const unsigned int _Min=0; + static const unsigned int _Max=UINT_MAX; +}; + +template<> +class AtlLimits +{ +public: + static const long _Min=LONG_MIN; + static const long _Max=LONG_MAX; +}; + +template<> +class AtlLimits +{ +public: + static const unsigned long _Min=0; + static const unsigned long _Max=ULONG_MAX; +}; + +template<> +class AtlLimits +{ +public: + static const long long _Min=LLONG_MIN; + static const long long _Max=LLONG_MAX; +}; + +template<> +class AtlLimits +{ +public: + static const unsigned long long _Min=0; + static const unsigned long long _Max=ULLONG_MAX; +}; + +/* generic version */ +template +inline HRESULT AtlAdd(T* ptResult, T tLeft, T tRight) +{ + if(::ATL::AtlLimits::_Max-tLeft < tRight) + { + return E_INVALIDARG; + } + *ptResult= tLeft + tRight; + return S_OK; +} + +/* generic but compariatively slow version */ +template +inline HRESULT AtlMultiply(T* ptResult, T tLeft, T tRight) +{ + /* avoid divide 0 */ + if(tLeft==0) + { + *ptResult=0; + return S_OK; + } + if(::ATL::AtlLimits::_Max/tLeft < tRight) + { + return E_INVALIDARG; + } + *ptResult= tLeft * tRight; + return S_OK; +} + +/* fast version for 32 bit integers */ +template<> +inline HRESULT AtlMultiply(int _ATL_W64 *piResult, int _ATL_W64 iLeft, int _ATL_W64 iRight) +{ + __int64 i64Result=static_cast<__int64>(iLeft) * static_cast<__int64>(iRight); + if(i64Result>INT_MAX || i64Result < INT_MIN) + { + return E_INVALIDARG; + } + *piResult=static_cast(i64Result); + return S_OK; +} + +template<> +inline HRESULT AtlMultiply(unsigned int _ATL_W64 *piResult, unsigned int _ATL_W64 iLeft, unsigned int _ATL_W64 iRight) +{ + unsigned __int64 i64Result=static_cast(iLeft) * static_cast(iRight); + if(i64Result>UINT_MAX) + { + return E_INVALIDARG; + } + *piResult=static_cast(i64Result); + return S_OK; +} + +template<> +inline HRESULT AtlMultiply(long _ATL_W64 *piResult, long _ATL_W64 iLeft, long _ATL_W64 iRight) +{ + __int64 i64Result=static_cast<__int64>(iLeft) * static_cast<__int64>(iRight); + if(i64Result>LONG_MAX || i64Result < LONG_MIN) + { + return E_INVALIDARG; + } + *piResult=static_cast(i64Result); + return S_OK; +} + +template<> +inline HRESULT AtlMultiply(unsigned long _ATL_W64 *piResult, unsigned long _ATL_W64 iLeft, unsigned long _ATL_W64 iRight) +{ + unsigned __int64 i64Result=static_cast(iLeft) * static_cast(iRight); + if(i64Result>ULONG_MAX) + { + return E_INVALIDARG; + } + *piResult=static_cast(i64Result); + return S_OK; +} + +template +inline T AtlMultiplyThrow(T tLeft, T tRight) +{ + T tResult; + HRESULT hr=AtlMultiply(&tResult, tLeft, tRight); + if(FAILED(hr)) + { + AtlThrow(hr); + } + return tResult; +} + +template +inline T AtlAddThrow(T tLeft, T tRight) +{ + T tResult; + HRESULT hr=AtlAdd(&tResult, tLeft, tRight); + if(FAILED(hr)) + { + AtlThrow(hr); + } + return tResult; +} + +inline LPVOID AtlCoTaskMemCAlloc(ULONG nCount, ULONG nSize) +{ + HRESULT hr; + ULONG nBytes=0; + if( FAILED(hr=::ATL::AtlMultiply(&nBytes, nCount, nSize))) + { + return NULL; + } + return ::CoTaskMemAlloc(nBytes); +} + +inline LPVOID AtlCoTaskMemRecalloc(void *pvMemory, ULONG nCount, ULONG nSize) +{ + HRESULT hr; + ULONG nBytes=0; + if( FAILED(hr=::ATL::AtlMultiply(&nBytes, nCount, nSize))) + { + return NULL; + } + return ::CoTaskMemRealloc(pvMemory, nBytes); +} + +} // namespace ATL +#pragma pack(pop) + +#pragma pack(push,8) +namespace ATL +{ +// forward declaration of Checked::memcpy_s + +namespace Checked +{ + void __cdecl memcpy_s(__out_bcount_part(s1max,n) void *s1, __in size_t s1max, __in_bcount(n) const void *s2, __in size_t n); +} + +///////////////////////////////////////////////////////////////////////////// +// Allocation helpers + +class CCRTAllocator +{ +public: + static void* Reallocate(void* p, size_t nBytes) throw() + { + return realloc(p, nBytes); + } + + static void* Allocate(size_t nBytes) throw() + { + return malloc(nBytes); + } + + static void Free(void* p) throw() + { + free(p); + } +}; + +class CLocalAllocator +{ +public: + static void* Allocate(size_t nBytes) throw() + { + return ::LocalAlloc(LMEM_FIXED, nBytes); + } + static void* Reallocate(void* p, size_t nBytes) throw() + { + if (p==NULL){ + return ( Allocate(nBytes) ); + + } + if (nBytes==0){ + Free(p); + return NULL; + } + return ::LocalReAlloc(p, nBytes, 0); + + } + static void Free(void* p) throw() + { + ::LocalFree(p); + } +}; + +class CGlobalAllocator +{ +public: + static void* Allocate(size_t nBytes) throw() + { + return ::GlobalAlloc(GMEM_FIXED, nBytes); + } + static void* Reallocate(void* p, size_t nBytes) throw() + { + if (p==NULL){ + return ( Allocate(nBytes) ); + + } + if (nBytes==0){ + Free(p); + return NULL; + } + return ( ::GlobalReAlloc(p, nBytes, 0) ); + } + static void Free(void* p) throw() + { + ::GlobalFree(p); + } +}; + +template +class CHeapPtrBase +{ +protected: + CHeapPtrBase() throw() : + m_pData(NULL) + { + } + CHeapPtrBase(CHeapPtrBase& p) throw() + { + m_pData = p.Detach(); // Transfer ownership + } + explicit CHeapPtrBase(T* pData) throw() : + m_pData(pData) + { + } + +public: + ~CHeapPtrBase() throw() + { + Free(); + } + +protected: + CHeapPtrBase& operator=(CHeapPtrBase& p) throw() + { + if(m_pData != p.m_pData) + Attach(p.Detach()); // Transfer ownership + return *this; + } + +public: + operator T*() const throw() + { + return m_pData; + } + + T* operator->() const throw() + { + ATLASSERT(m_pData != NULL); + return m_pData; + } + + T** operator&() throw() + { +#if defined(ATLASSUME) + ATLASSUME(m_pData == NULL); +#endif + return &m_pData; + } + + // Allocate a buffer with the given number of bytes + bool AllocateBytes(size_t nBytes) throw() + { + ATLASSERT(m_pData == NULL); + m_pData = static_cast(Allocator::Allocate(nBytes)); + if (m_pData == NULL) + return false; + + return true; + } + + // Attach to an existing pointer (takes ownership) + void Attach(T* pData) throw() + { + Allocator::Free(m_pData); + m_pData = pData; + } + + // Detach the pointer (releases ownership) + T* Detach() throw() + { + T* pTemp = m_pData; + m_pData = NULL; + return pTemp; + } + + // Free the memory pointed to, and set the pointer to NULL + void Free() throw() + { + Allocator::Free(m_pData); + m_pData = NULL; + } + + // Reallocate the buffer to hold a given number of bytes + bool ReallocateBytes(size_t nBytes) throw() + { + T* pNew; + + pNew = static_cast(Allocator::Reallocate(m_pData, nBytes)); + if (pNew == NULL) + return false; + m_pData = pNew; + + return true; + } + +public: + T* m_pData; +}; + +template +class CHeapPtr : + public CHeapPtrBase +{ +public: + CHeapPtr() throw() + { + } + CHeapPtr(CHeapPtr& p) throw() : + CHeapPtrBase(p) + { + } + explicit CHeapPtr(T* p) throw() : + CHeapPtrBase(p) + { + } + + CHeapPtr& operator=(CHeapPtr& p) throw() + { + CHeapPtrBase::operator=(p); + + return *this; + } + + // Allocate a buffer with the given number of elements + bool Allocate(size_t nElements = 1) throw() + { + size_t nBytes=0; + if(FAILED(::ATL::AtlMultiply(&nBytes, nElements, sizeof(T)))) + { + return false; + } + return AllocateBytes(nBytes); + } + + // Reallocate the buffer to hold a given number of elements + bool Reallocate(size_t nElements) throw() + { + size_t nBytes=0; + if(FAILED(::ATL::AtlMultiply(&nBytes, nElements, sizeof(T)))) + { + return false; + } + return ReallocateBytes(nBytes); + } +}; + +template< typename T, int t_nFixedBytes = 128, class Allocator = CCRTAllocator > +class CTempBuffer +{ +public: + CTempBuffer() throw() : + m_p( NULL ) + { + } + CTempBuffer( size_t nElements ) throw( ... ) : + m_p( NULL ) + { + Allocate( nElements ); + } + + ~CTempBuffer() throw() + { + if( m_p != reinterpret_cast< T* >( m_abFixedBuffer ) ) + { + FreeHeap(); + } + } + + operator T*() const throw() + { + return( m_p ); + } + T* operator->() const throw() + { + ATLASSERT( m_p != NULL ); + return( m_p ); + } + + T* Allocate( size_t nElements ) throw( ... ) + { + return( AllocateBytes( ::ATL::AtlMultiplyThrow(nElements,sizeof( T )) ) ); + } + + T* Reallocate( size_t nElements ) throw( ... ) + { + ATLENSURE(nElements < size_t(-1)/sizeof(T) ); + size_t nNewSize = nElements*sizeof( T ) ; + + if (m_p == NULL) + return AllocateBytes(nNewSize); + + if (nNewSize > t_nFixedBytes) + { + if( m_p == reinterpret_cast< T* >( m_abFixedBuffer ) ) + { + // We have to allocate from the heap and copy the contents into the new buffer + AllocateHeap(nNewSize); + Checked::memcpy_s(m_p, nNewSize, m_abFixedBuffer, t_nFixedBytes); + } + else + { + ReAllocateHeap( nNewSize ); + } + } + else + { + m_p = reinterpret_cast< T* >( m_abFixedBuffer ); + } + + return m_p; + } + + T* AllocateBytes( size_t nBytes ) + { + ATLASSERT( m_p == NULL ); + if( nBytes > t_nFixedBytes ) + { + AllocateHeap( nBytes ); + } + else + { + m_p = reinterpret_cast< T* >( m_abFixedBuffer ); + } + + return( m_p ); + } + +private: + ATL_NOINLINE void AllocateHeap( size_t nBytes ) + { + T* p = static_cast< T* >( Allocator::Allocate( nBytes ) ); + if( p == NULL ) + { + AtlThrow( E_OUTOFMEMORY ); + } + m_p = p; + } + + ATL_NOINLINE void ReAllocateHeap( size_t nNewSize) + { + T* p = static_cast< T* >( Allocator::Reallocate(m_p, nNewSize) ); + if ( p == NULL ) + { + AtlThrow( E_OUTOFMEMORY ); + } + m_p = p; + } + + ATL_NOINLINE void FreeHeap() throw() + { + Allocator::Free( m_p ); + } + +private: + T* m_p; + BYTE m_abFixedBuffer[t_nFixedBytes]; +}; + + +// Allocating memory on the stack without causing stack overflow. +// Only use these through the _ATL_SAFE_ALLOCA_* macros +namespace _ATL_SAFE_ALLOCA_IMPL +{ + +#ifndef _ATL_STACK_MARGIN +#if defined(_M_IX86) +#define _ATL_STACK_MARGIN 0x2000 // Minimum stack available after call to _ATL_SAFE_ALLOCA +#else //_M_AMD64 _M_IA64 +#define _ATL_STACK_MARGIN 0x4000 +#endif +#endif //_ATL_STACK_MARGIN + +//Verifies if sufficient space is available on the stack. +//Note: This function should never be inlined, because the stack allocation +//may not be freed until the end of the calling function (instead of the end of _AtlVerifyStackAvailable). +//The use of __try/__except preverts inlining in this case. +#if (_ATL_VER > 0x0301) +inline bool _AtlVerifyStackAvailable(SIZE_T Size) +{ + bool bStackAvailable = true; + + __try + { + SIZE_T size=0; + HRESULT hrAdd=::ATL::AtlAdd(&size, Size, static_cast(_ATL_STACK_MARGIN)); + if(FAILED(hrAdd)) + { + ATLASSERT(FALSE); + bStackAvailable = false; + } + else + { + PVOID p = _alloca(size); + if (p) + { + (p); + } + } + } + __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) + { + bStackAvailable = false; + _resetstkoflw(); + } + return bStackAvailable; +} + + +// Helper Classes to manage heap buffers for _ATL_SAFE_ALLOCA +template < class Allocator> +class CAtlSafeAllocBufferManager +{ +private : + struct CAtlSafeAllocBufferNode + { + CAtlSafeAllocBufferNode* m_pNext; +#if defined(_M_IX86) + BYTE _pad[4]; +#elif defined(_M_IA64) + BYTE _pad[8]; +#elif defined(_M_AMD64) + BYTE _pad[8]; +#else + #error Only supported for X86, AMD64 and IA64 +#endif + void* GetData() + { + return (this + 1); + } + }; + + CAtlSafeAllocBufferNode* m_pHead; +public : + + CAtlSafeAllocBufferManager() : m_pHead(NULL) {}; + void* Allocate(SIZE_T nRequestedSize) + { + CAtlSafeAllocBufferNode *p = (CAtlSafeAllocBufferNode*)Allocator::Allocate(::ATL::AtlAddThrow(nRequestedSize, static_cast(sizeof(CAtlSafeAllocBufferNode)))); + if (p == NULL) + return NULL; + + // Add buffer to the list + p->m_pNext = m_pHead; + m_pHead = p; + + return p->GetData(); + } + ~CAtlSafeAllocBufferManager() + { + // Walk the list and free the buffers + while (m_pHead != NULL) + { + CAtlSafeAllocBufferNode* p = m_pHead; + m_pHead = m_pHead->m_pNext; + Allocator::Free(p); + } + } +}; +#endif + +} // namespace _ATL_SAFE_ALLOCA_IMPL + +} // namespace ATL + #pragma pack(pop) + +// Use one of the following macros before using _ATL_SAFE_ALLOCA +// EX version allows specifying a different heap allocator +#define USES_ATL_SAFE_ALLOCA_EX(x) ATL::_ATL_SAFE_ALLOCA_IMPL::CAtlSafeAllocBufferManager _AtlSafeAllocaManager + +#ifndef USES_ATL_SAFE_ALLOCA +#define USES_ATL_SAFE_ALLOCA USES_ATL_SAFE_ALLOCA_EX(ATL::CCRTAllocator) +#endif + +// nRequestedSize - requested size in bytes +// nThreshold - size in bytes beyond which memory is allocated from the heap. + +#if (_ATL_VER > 0x0301) + +// Defining _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE always allocates the size specified +// for threshold if the stack space is available irrespective of requested size. +// This available for testing purposes. It will help determine the max stack usage due to _alloca's +// Disable _alloca not within try-except prefast warning since we verify stack space is available before. +#ifdef _ATL_SAFE_ALLOCA_ALWAYS_ALLOCATE_THRESHOLD_SIZE +#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ + __pragma(warning(push))\ + __pragma(warning(disable:4616))\ + __pragma(warning(disable:6255))\ + ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold) ) ? \ + _alloca(nThreshold) : \ + ((ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nThreshold)) ? _alloca(nThreshold) : 0), \ + _AtlSafeAllocaManager.Allocate(nRequestedSize))\ + __pragma(warning(pop)) +#else +#define _ATL_SAFE_ALLOCA(nRequestedSize, nThreshold) \ + __pragma(warning(push))\ + __pragma(warning(disable:4616))\ + __pragma(warning(disable:6255))\ + ((nRequestedSize <= nThreshold && ATL::_ATL_SAFE_ALLOCA_IMPL::_AtlVerifyStackAvailable(nRequestedSize) ) ? \ + _alloca(nRequestedSize) : \ + _AtlSafeAllocaManager.Allocate(nRequestedSize))\ + __pragma(warning(pop)) +#endif + +#endif + +// Use 1024 bytes as the default threshold in ATL +#ifndef _ATL_SAFE_ALLOCA_DEF_THRESHOLD +#define _ATL_SAFE_ALLOCA_DEF_THRESHOLD 1024 +#endif + +#if (_ATL_VER <= 0x0301) // from atlbase.h + +class CComAllocator +{ +public: + static void* Reallocate(void* p, size_t nBytes) throw() + { +#ifdef _WIN64 + if( nBytes > INT_MAX ) + { + return( NULL ); + } +#endif + return ::CoTaskMemRealloc(p, ULONG(nBytes)); + } + static void* Allocate(size_t nBytes) throw() + { +#ifdef _WIN64 + if( nBytes > INT_MAX ) + { + return( NULL ); + } +#endif + return ::CoTaskMemAlloc(ULONG(nBytes)); + } + static void Free(void* p) throw() + { + ::CoTaskMemFree(p); + } +}; + +template +class CComHeapPtr : + public CHeapPtr +{ +public: + CComHeapPtr() throw() + { + } + + explicit CComHeapPtr(T* pData) throw() : + CHeapPtr(pData) + { + } +}; + +#endif + diff --git a/c/jacob/include/atlbase.h b/c/jacob/include/atlbase.h new file mode 100644 index 0000000..a0e61a0 --- /dev/null +++ b/c/jacob/include/atlbase.h @@ -0,0 +1,7410 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLBASE_H__ +#define __ATLBASE_H__ + +#pragma once + +// Warnings outside of the push/pop sequence will be disabled for all user +// projects. The only warnings that should be disabled outside the push/pop +// are warnings that are a) benign and b) will show up in user projects +// without being directly caused by the user + +#pragma warning(disable: 4505) // unreferenced local function has been removed +#pragma warning(disable: 4710) // function couldn't be inlined +#pragma warning(disable: 4514) // unreferenced inlines are common + +// These two warnings will occur in any class that contains or derives from a +// class with a private copy constructor or copy assignment operator. +#pragma warning(disable: 4511) // copy constructor could not be generated +#pragma warning(disable: 4512) // assignment operator could not be generated + +// This is a very common pattern for us +#pragma warning(disable: 4355) // 'this' : used in base member initializer list + +// Warning 4702 is generated based on compiler backend data flow analysis. This means that for +// some specific instantiations of a template it can be generated even when the code branch is +// required for other instantiations. In future we should find a way to be more selective about this +#pragma warning(disable: 4702) // Unreachable code + +// +// [pfx_parse] - workaround for old PREfix/PREfast parser +// +#if (defined(_PREFIX_) || defined(_PREFAST_)) && (_MSC_VER < 1400) +#pragma warning (push) +#pragma warning(disable: 4081) // expected 'newline' +#endif // old PREfast parser + +#ifdef _ATL_ALL_WARNINGS +#pragma warning( push ) +#endif + +#pragma warning(disable : 4668) // is not defined as a preprocessor macro, replacing with '0' for '#if/#elif +#pragma warning(disable : 4820) // padding added after member +#pragma warning(disable : 4917) // a GUID can only be associated with a class, interface or namespace + +#pragma warning(disable : 4217) // member template functions cannot be used for copy-assignment or copy-construction + +#pragma warning(disable: 4127) // constant expression +#pragma warning(disable: 4097) // typedef name used as synonym for class-name +#pragma warning(disable: 4786) // identifier was truncated in the debug information +#pragma warning(disable: 4291) // allow placement new +#pragma warning(disable: 4201) // nameless unions are part of C++ +#pragma warning(disable: 4103) // pragma pack +#pragma warning(disable: 4268) // const static/global data initialized to zeros + +#pragma warning (push) +#pragma warning(disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif +#ifndef ATL_NO_LEAN_AND_MEAN +#define ATL_NO_LEAN_AND_MEAN +#endif + +#include + +#ifndef _WINSOCKAPI_ +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#if !defined(_ATL_MIN_CRT) & defined(_MT) +#include +#include // for _beginthreadex, _endthreadex +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#define _ATL_TYPELIB_INDEX_LENGTH 10 +#define _ATL_QUOTES_SPACE 2 + +#pragma pack(push, _ATL_PACKING) + +#ifndef _ATL_NO_DEFAULT_LIBS + +#if defined(_ATL_DLL) + #pragma comment(lib, "atl.lib") + +#if !defined(_ATL_NOFORCE_MANIFEST) && !defined(_VC_NODEFAULTLIB) + +#include + +#endif // !defined(_ATL_NOFORCE_MANIFEST) && !defined(_VC_NODEFAULTLIB) + +#endif // _ATL_DLL + +#ifdef _DEBUG + #pragma comment(lib, "atlsd.lib") +#else + #pragma comment(lib, "atls.lib") +#ifdef _ATL_MIN_CRT + #pragma comment(lib, "atlmincrt.lib") +#endif +#endif + +#endif // !_ATL_NO_DEFAULT_LIBS + +#if defined(_ATL_DLL) + // Pull in obj file with manifest directive for ATL dll + #if defined(_M_IX86) + #pragma comment(linker, "/include:__forceAtlDllManifest") + #else + #pragma comment(linker, "/include:_forceAtlDllManifest") + #endif +#endif + +extern "C" const __declspec(selectany) GUID LIBID_ATLLib = {0x44EC0535,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; +extern "C" const __declspec(selectany) CLSID CLSID_Registrar = {0x44EC053A,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; +extern "C" const __declspec(selectany) IID IID_IRegistrar = {0x44EC053B,0x400F,0x11D0,{0x9D,0xCD,0x00,0xA0,0xC9,0x03,0x91,0xD3}}; +extern "C" const __declspec(selectany) IID IID_IAxWinHostWindow = {0xb6ea2050,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; +extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatch = {0xb6ea2051,0x048a,0x11d1,{0x82,0xb9,0x00,0xc0,0x4f,0xb9,0x94,0x2e}}; +extern "C" const __declspec(selectany) IID IID_IInternalConnection = {0x72AD0770,0x6A9F,0x11d1,{0xBC,0xEC,0x00,0x60,0x08,0x8F,0x44,0x4E}}; +extern "C" const __declspec(selectany) IID IID_IDocHostUIHandlerDispatch = {0x425B5AF0,0x65F1,0x11d1,{0x96,0x11,0x00,0x00,0xF8,0x1E,0x0D,0x0D}}; +extern "C" const __declspec(selectany) IID IID_IAxWinHostWindowLic = {0x3935BDA8,0x4ED9,0x495c,{0x86,0x50,0xE0,0x1F,0xC1,0xE3,0x8A,0x4B}}; +extern "C" const __declspec(selectany) IID IID_IAxWinAmbientDispatchEx = {0xB2D0778B,0xAC99,0x4c58,{0xA5,0xC8,0xE7,0x72,0x4E,0x53,0x16,0xB5}}; + +// REVIEW: Temp until it gets back into UUID.LIB +extern "C" const __declspec(selectany) CLSID CLSID_StdGlobalInterfaceTable = {0x00000323,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; + +#ifndef _delayimp_h +extern "C" IMAGE_DOS_HEADER __ImageBase; +#endif + +#ifdef _AFX +void AFXAPI AfxOleLockApp(); +void AFXAPI AfxOleUnlockApp(); +#endif // _AFX + + + +namespace ATL +{ + +struct _ATL_CATMAP_ENTRY +{ + int iType; + const CATID* pcatid; +}; + +#define _ATL_CATMAP_ENTRY_END 0 +#define _ATL_CATMAP_ENTRY_IMPLEMENTED 1 +#define _ATL_CATMAP_ENTRY_REQUIRED 2 + +typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void* pv, REFIID riid, LPVOID* ppv); +typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void* pv, REFIID riid, LPVOID* ppv, DWORD_PTR dw); +typedef HRESULT (WINAPI _ATL_MODULEFUNC)(DWORD_PTR dw); +typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)(); +typedef const struct _ATL_CATMAP_ENTRY* (_ATL_CATMAPFUNC)(); +typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw); + +struct _ATL_TERMFUNC_ELEM +{ + _ATL_TERMFUNC* pFunc; + DWORD_PTR dw; + _ATL_TERMFUNC_ELEM* pNext; +}; + +/* +struct _ATL_OBJMAP_ENTRY20 +{ + const CLSID* pclsid; + HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); + _ATL_CREATORFUNC* pfnGetClassObject; + _ATL_CREATORFUNC* pfnCreateInstance; + IUnknown* pCF; + DWORD dwRegister; + _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; +}; +*/ + +// Can't inherit from _ATL_OBJMAP_ENTRY20 +// because it messes up the OBJECT_MAP macros +struct _ATL_OBJMAP_ENTRY30 +{ + const CLSID* pclsid; + HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); + _ATL_CREATORFUNC* pfnGetClassObject; + _ATL_CREATORFUNC* pfnCreateInstance; + IUnknown* pCF; + DWORD dwRegister; + _ATL_DESCRIPTIONFUNC* pfnGetObjectDescription; + _ATL_CATMAPFUNC* pfnGetCategoryMap; + HRESULT WINAPI RevokeClassObject() + { + if (dwRegister == 0) + return S_OK; + return CoRevokeClassObject(dwRegister); + } + HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags) + { + IUnknown* p = NULL; + if (pfnGetClassObject == NULL) + return S_OK; + HRESULT hRes = pfnGetClassObject(pfnCreateInstance, __uuidof(IUnknown), (LPVOID*) &p); + if (SUCCEEDED(hRes)) + hRes = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister); + if (p != NULL) + p->Release(); + return hRes; + } +// Added in ATL 3.0 + void (WINAPI *pfnObjectMain)(bool bStarting); +}; + +typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY; + +// Auto Object Map + +#if defined(_M_IA64) || defined(_M_IX86) || defined (_M_AMD64) + +#pragma section("ATL$__a", read, shared) +#pragma section("ATL$__z", read, shared) +#pragma section("ATL$__m", read, shared) +extern "C" +{ +__declspec(selectany) __declspec(allocate("ATL$__a")) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; +__declspec(selectany) __declspec(allocate("ATL$__z")) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; +} + +#if !defined(_M_IA64) +#pragma comment(linker, "/merge:ATL=.rdata") +#endif + +#else + +extern "C" +{ +__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryFirst = NULL; +__declspec(selectany) _ATL_OBJMAP_ENTRY* __pobjMapEntryLast = NULL; +} + +#endif // defined(_M_IA64) || defined(_M_IX86) + +struct _ATL_REGMAP_ENTRY +{ + LPCOLESTR szKey; + LPCOLESTR szData; +}; + +struct _AtlCreateWndData +{ + void* m_pThis; + DWORD m_dwThreadID; + _AtlCreateWndData* m_pNext; +}; + + +// perfmon registration/unregistration function definitions +typedef HRESULT (*_ATL_PERFREGFUNC)(HINSTANCE hDllInstance); +typedef HRESULT (*_ATL_PERFUNREGFUNC)(); +__declspec(selectany) _ATL_PERFREGFUNC _pPerfRegFunc = NULL; +__declspec(selectany) _ATL_PERFUNREGFUNC _pPerfUnRegFunc = NULL; + +///////////////////////////////////////////////////////////////////////////// +// Threading Model Support + +template< class TLock > +class CComCritSecLock +{ +public: + CComCritSecLock( TLock& cs, bool bInitialLock = true ); + ~CComCritSecLock() throw(); + + HRESULT Lock() throw(); + void Unlock() throw(); + +// Implementation +private: + TLock& m_cs; + bool m_bLocked; + +// Private to avoid accidental use + CComCritSecLock( const CComCritSecLock& ) throw(); + CComCritSecLock& operator=( const CComCritSecLock& ) throw(); +}; + +template< class TLock > +inline CComCritSecLock< TLock >::CComCritSecLock( TLock& cs, bool bInitialLock ) : + m_cs( cs ), + m_bLocked( false ) +{ + if( bInitialLock ) + { + HRESULT hr; + + hr = Lock(); + if( FAILED( hr ) ) + { + AtlThrow( hr ); + } + } +} + +template< class TLock > +inline CComCritSecLock< TLock >::~CComCritSecLock() throw() +{ + if( m_bLocked ) + { + Unlock(); + } +} + +template< class TLock > +inline HRESULT CComCritSecLock< TLock >::Lock() throw() +{ + HRESULT hr; + + ATLASSERT( !m_bLocked ); + hr = m_cs.Lock(); + if( FAILED( hr ) ) + { + return( hr ); + } + m_bLocked = true; + + return( S_OK ); +} + +template< class TLock > +inline void CComCritSecLock< TLock >::Unlock() throw() +{ + ATLASSUME( m_bLocked ); + m_cs.Unlock(); + m_bLocked = false; +} + +class CComMultiThreadModelNoCS +{ +public: + static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} + static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} + typedef CComFakeCriticalSection AutoCriticalSection; + typedef CComFakeCriticalSection AutoDeleteCriticalSection; + typedef CComFakeCriticalSection CriticalSection; + typedef CComMultiThreadModelNoCS ThreadModelNoCS; +}; + +class CComMultiThreadModel +{ +public: + static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);} + static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);} + typedef CComAutoCriticalSection AutoCriticalSection; + typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection; + typedef CComCriticalSection CriticalSection; + typedef CComMultiThreadModelNoCS ThreadModelNoCS; +}; + +class CComSingleThreadModel +{ +public: + static ULONG WINAPI Increment(LPLONG p) throw() {return ++(*p);} + static ULONG WINAPI Decrement(LPLONG p) throw() {return --(*p);} + typedef CComFakeCriticalSection AutoCriticalSection; + typedef CComFakeCriticalSection AutoDeleteCriticalSection; + typedef CComFakeCriticalSection CriticalSection; + typedef CComSingleThreadModel ThreadModelNoCS; +}; + +#if defined(_ATL_SINGLE_THREADED) + +#if defined(_ATL_APARTMENT_THREADED) || defined(_ATL_FREE_THREADED) +#pragma message ("More than one global threading model defined.") +#endif + + typedef CComSingleThreadModel CComObjectThreadModel; + typedef CComSingleThreadModel CComGlobalsThreadModel; + +#elif defined(_ATL_APARTMENT_THREADED) + +#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_FREE_THREADED) +#pragma message ("More than one global threading model defined.") +#endif + + typedef CComSingleThreadModel CComObjectThreadModel; + typedef CComMultiThreadModel CComGlobalsThreadModel; + +#elif defined(_ATL_FREE_THREADED) + +#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_APARTMENT_THREADED) +#pragma message ("More than one global threading model defined.") +#endif + + typedef CComMultiThreadModel CComObjectThreadModel; + typedef CComMultiThreadModel CComGlobalsThreadModel; + +#else +#pragma message ("No global threading model defined") +#endif + +///////////////////////////////////////////////////////////////////////////// +// Module + + +// Used by COM related code in ATL +struct _ATL_COM_MODULE70 +{ + UINT cbSize; + HINSTANCE m_hInstTypeLib; + _ATL_OBJMAP_ENTRY** m_ppAutoObjMapFirst; + _ATL_OBJMAP_ENTRY** m_ppAutoObjMapLast; + CComCriticalSection m_csObjMap; +}; +typedef _ATL_COM_MODULE70 _ATL_COM_MODULE; + + +// Used by Windowing code in ATL +struct _ATL_WIN_MODULE70 +{ + UINT cbSize; + CComCriticalSection m_csWindowCreate; + _AtlCreateWndData* m_pCreateWndList; + CSimpleArray m_rgWindowClassAtoms; +}; +typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE; + + +struct _ATL_MODULE70 +{ + UINT cbSize; + LONG m_nLockCnt; + _ATL_TERMFUNC_ELEM* m_pTermFuncs; + CComCriticalSection m_csStaticDataInitAndTypeInfo; +}; +typedef _ATL_MODULE70 _ATL_MODULE; + + +///////////////////////////////////////////////////////////////////////////// +//This define makes debugging asserts easier. +#define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC*)1) + +struct _ATL_INTMAP_ENTRY +{ + const IID* piid; // the interface id (IID) + DWORD_PTR dw; + _ATL_CREATORARGFUNC* pFunc; //NULL:end, 1:offset, n:ptr +}; + +///////////////////////////////////////////////////////////////////////////// +// Global Functions + +///////////////////////////////////////////////////////////////////////////// +// QI Support + +ATLAPI AtlInternalQueryInterface(void* pThis, + const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject); + +///////////////////////////////////////////////////////////////////////////// +// Inproc Marshaling helpers + +ATLAPI AtlFreeMarshalStream(IStream* pStream); +ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream); +ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk); + +ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent); + +///////////////////////////////////////////////////////////////////////////// +// Connection Point Helpers + +ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw); +ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw); + +///////////////////////////////////////////////////////////////////////////// +// IDispatch Error handling + +ATLAPI AtlSetErrorInfo(const CLSID& clsid, LPCOLESTR lpszDesc, + DWORD dwHelpID, LPCOLESTR lpszHelpFile, const IID& iid, HRESULT hRes, + HINSTANCE hInst); + +///////////////////////////////////////////////////////////////////////////// +// Module + +ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags); +ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule); + +ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv); + +ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID = NULL); +ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL); + +ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ); + +ATLAPI AtlUpdateRegistryFromResourceD(HINSTANCE hInst, LPCOLESTR lpszRes, + BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL); + +ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); +ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex); +ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib); + +ATLAPI_(DWORD) AtlGetVersion(void* pReserved); + +ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw); +ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule); + +ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule); +ATLAPIINL AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst); + +ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject); +ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule); + +///////////////////////////////////////////////////////////////////////////// +// Get Registrar object from ATL DLL. + +#if !defined(_ATL_STATIC_REGISTRY) +#ifdef _ATL_DLL_IMPL +extern "C" HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); +#else +extern "C" __declspec(dllimport) HRESULT __stdcall AtlCreateRegistrar(IRegistrar** ppReg); +#endif +#endif + +///////////////////////////////////////////////////////////////////////////// +// GUID comparison +inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1) +{ + return ( + ((PLONG) &rguid1)[0] == 0 && + ((PLONG) &rguid1)[1] == 0 && +#ifdef _ATL_BYTESWAP + ((PLONG) &rguid1)[2] == 0xC0000000 && + ((PLONG) &rguid1)[3] == 0x00000046); +#else + ((PLONG) &rguid1)[2] == 0x000000C0 && + ((PLONG) &rguid1)[3] == 0x46000000); +#endif +} + + + +template +LPCTSTR AtlDebugGetClassName(T*) +{ +#ifdef _DEBUG + const _ATL_INTMAP_ENTRY* pEntries = T::_GetEntries(); + return (LPCTSTR)pEntries[-1].dw; +#else + return NULL; +#endif +} + +// Validation macro for OUT pointer +// Used in QI and CreateInstance +#define _ATL_VALIDATE_OUT_POINTER(x)\ + do { \ + ATLASSERT(x != NULL); \ + if (x == NULL) \ + return E_POINTER; \ + *x = NULL; \ + } while(0) + +///////////////////////////////////////////////////////////////////////////// +// Win32 libraries + +#ifndef _ATL_NO_DEFAULT_LIBS +#pragma comment(lib, "kernel32.lib") +#pragma comment(lib, "user32.lib") +#pragma comment(lib, "advapi32.lib") +#pragma comment(lib, "ole32.lib") +#pragma comment(lib, "shell32.lib") +#pragma comment(lib, "oleaut32.lib") +#pragma comment(lib, "uuid.lib") +#pragma comment(lib, "shlwapi.lib") +#endif // !_ATL_NO_DEFAULT_LIBS + +template< typename T > +class CAutoVectorPtr +{ +public: + CAutoVectorPtr() throw() : + m_p( NULL ) + { + } + CAutoVectorPtr( CAutoVectorPtr< T >& p ) throw() + { + m_p = p.Detach(); // Transfer ownership + } + explicit CAutoVectorPtr( T* p ) throw() : + m_p( p ) + { + } + ~CAutoVectorPtr() throw() + { + Free(); + } + + operator T*() const throw() + { + return( m_p ); + } + + CAutoVectorPtr< T >& operator=( CAutoVectorPtr< T >& p ) throw() + { + if(*this==p) + { + if(this!=&p) + { + // If this assert fires, it means you attempted to assign one CAutoVectorPtr to another when they both contained + // a pointer to the same underlying vector. This means a bug in your code, since your vector will get + // double-deleted. + ATLASSERT(FALSE); + + // For safety, we are going to detach the other CAutoVectorPtr to avoid a double-free. Your code still + // has a bug, though. + p.Detach(); + } + else + { + // Alternatively, this branch means that you are assigning a CAutoVectorPtr to itself, which is + // pointless but permissible + + // nothing to do + } + } + else + { + Free(); + Attach( p.Detach() ); // Transfer ownership + } + return( *this ); + } + + // basic comparison operators + bool operator!=(CAutoVectorPtr& p) const + { + return !operator==(p); + } + + bool operator==(CAutoVectorPtr& p) const + { + return m_p==p.m_p; + } + + // Allocate the vector + bool Allocate( size_t nElements ) throw() + { + ATLASSUME( m_p == NULL ); + ATLTRY( m_p = new T[nElements] ); + if( m_p == NULL ) + { + return( false ); + } + + return( true ); + } + // Attach to an existing pointer (takes ownership) + void Attach( T* p ) throw() + { + ATLASSUME( m_p == NULL ); + m_p = p; + } + // Detach the pointer (releases ownership) + T* Detach() throw() + { + T* p; + + p = m_p; + m_p = NULL; + + return( p ); + } + // Delete the vector pointed to, and set the pointer to NULL + void Free() throw() + { + delete[] m_p; + m_p = NULL; + } + +public: + T* m_p; +}; + +template< typename T > +class CAutoPtr +{ +public: + CAutoPtr() throw() : + m_p( NULL ) + { + } + template< typename TSrc > + CAutoPtr( CAutoPtr< TSrc >& p ) throw() + { + m_p = p.Detach(); // Transfer ownership + } +// +// [pfx_parse] - workaround for PREfix parse problems +// +#if (!defined(_PREFIX_)) && (!defined(_PREFAST_)) + CAutoPtr( CAutoPtr< T >& p ) throw() + { + m_p = p.Detach(); // Transfer ownership + } +#endif // !_PREFIX_ + explicit CAutoPtr( T* p ) throw() : + m_p( p ) + { + } + ~CAutoPtr() throw() + { + Free(); + } + + // Templated version to allow pBase = pDerived + template< typename TSrc > + CAutoPtr< T >& operator=( CAutoPtr< TSrc >& p ) throw() + { + if(m_p==p.m_p) + { + // This means that two CAutoPtrs of two different types had the same m_p in them + // which is never correct + ATLASSERT(FALSE); + } + else + { + Free(); + Attach( p.Detach() ); // Transfer ownership + } + return( *this ); + } + CAutoPtr< T >& operator=( CAutoPtr< T >& p ) throw() + { + if(*this==p) + { + if(this!=&p) + { + // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained + // a pointer to the same underlying object. This means a bug in your code, since your object will get + // double-deleted. +#ifdef ATL_AUTOPTR_ASSIGNMENT_ASSERT + ATLASSERT(FALSE); +#endif + + // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still + // has a bug, though. + p.Detach(); + } + else + { + // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is + // pointless but permissible + + // nothing to do + } + } + else + { + Free(); + Attach( p.Detach() ); // Transfer ownership + } + return( *this ); + } + + // basic comparison operators + bool operator!=(CAutoPtr& p) const + { + return !operator==(p); + } + + bool operator==(CAutoPtr& p) const + { + return m_p==p.m_p; + } + + operator T*() const throw() + { + return( m_p ); + } + T* operator->() const throw() + { + ATLASSUME( m_p != NULL ); + return( m_p ); + } + + // Attach to an existing pointer (takes ownership) + void Attach( T* p ) throw() + { + ATLASSUME( m_p == NULL ); + m_p = p; + } + // Detach the pointer (releases ownership) + T* Detach() throw() + { + T* p; + + p = m_p; + m_p = NULL; + + return( p ); + } + // Delete the object pointed to, and set the pointer to NULL + void Free() throw() + { + delete m_p; + m_p = NULL; + } + +public: + T* m_p; +}; + +/* Automatic cleanup for _malloca objects */ +template< typename T > +class CAutoStackPtr +{ +public: + CAutoStackPtr() throw() : + m_p( NULL ) + { + } + template< typename TSrc > + CAutoStackPtr( CAutoStackPtr< TSrc >& p ) throw() + { + m_p = p.Detach(); // Transfer ownership + } + CAutoStackPtr( CAutoStackPtr< T >& p ) throw() + { + m_p = p.Detach(); // Transfer ownership + } + explicit CAutoStackPtr( T* p ) throw() : + m_p( p ) + { + } + ~CAutoStackPtr() throw() + { + Free(); + } + + // Templated version to allow pBase = pDerived + template< typename TSrc > + CAutoStackPtr< T >& operator=( CAutoStackPtr< TSrc >& p ) throw() + { + if(m_p==p.m_p) + { + // This means that two CAutoPtrs of two different types had the same m_p in them + // which is never correct + ATLASSERT(FALSE); + } + else + { + Free(); + Attach( p.Detach() ); // Transfer ownership + } + return( *this ); + } + CAutoStackPtr< T >& operator=( CAutoStackPtr< T >& p ) throw() + { + if(*this==p) + { + if(this!=&p) + { + // If this assert fires, it means you attempted to assign one CAutoPtr to another when they both contained + // a pointer to the same underlying object. This means a bug in your code, since your object will get + // double-deleted. + ATLASSERT(FALSE); + + // For safety, we are going to detach the other CAutoPtr to avoid a double-free. Your code still + // has a bug, though. + p.Detach(); + } + else + { + // Alternatively, this branch means that you are assigning a CAutoPtr to itself, which is + // pointless but permissible + + // nothing to do + } + } + else + { + Free(); + Attach( p.Detach() ); // Transfer ownership + } + return( *this ); + } + + // basic comparison operators + bool operator!=(CAutoStackPtr& p) const + { + return !operator==(p); + } + + bool operator==(CAutoStackPtr& p) const + { + return m_p==p.m_p; + } + + operator T*() const throw() + { + return( m_p ); + } + T* operator->() const throw() + { + ATLASSUME( m_p != NULL ); + return( m_p ); + } + + // Attach to an existing pointer (takes ownership) + void Attach( T* p ) throw() + { + ATLASSUME( m_p == NULL ); + m_p = p; + } + // Detach the pointer (releases ownership) + T* Detach() throw() + { + T* p; + + p = m_p; + m_p = NULL; + + return( p ); + } + // Delete the object pointed to, and set the pointer to NULL + void Free() throw() + { + /* Note: _freea only actually does anything if m_p was heap allocated + If m_p was from the stack, it wouldn't be possible to actually free it here + [wrong function] unless we got inlined. But really all we do if m_p is + stack-based is ignore it and let its alloca storage disappear at the end + of the outer function. + */ + _freea(m_p); + m_p = NULL; + } + +public: + T* m_p; +}; + +// static_cast_auto template functions. Used like static_cast, only they work on CAutoPtr objects +template< class Dest, class Src > +Dest* static_cast_auto( const CAutoPtr< Src >& pSrc ) throw() +{ + return( static_cast< Dest* >( static_cast< Src* >( pSrc ) ) ); +} + + +class CComAllocator +{ +public: + static void* Reallocate(void* p, size_t nBytes) throw() + { +#ifdef _WIN64 + if( nBytes > INT_MAX ) + { + return( NULL ); + } +#endif + return ::CoTaskMemRealloc(p, ULONG(nBytes)); + } + static void* Allocate(size_t nBytes) throw() + { +#ifdef _WIN64 + if( nBytes > INT_MAX ) + { + return( NULL ); + } +#endif + return ::CoTaskMemAlloc(ULONG(nBytes)); + } + static void Free(void* p) throw() + { + ::CoTaskMemFree(p); + } +}; + +template +class CComHeapPtr : + public CHeapPtr +{ +public: + CComHeapPtr() throw() + { + } + + explicit CComHeapPtr(T* pData) throw() : + CHeapPtr(pData) + { + } +}; + +template +T* AtlSafeRealloc(T* pT, size_t cEls) throw() +{ + T* pTemp; + + size_t nBytes=0; + if(FAILED(::ATL::AtlMultiply(&nBytes, cEls, sizeof(T)))) + { + return NULL; + } + pTemp = static_cast(Reallocator::Reallocate(pT, nBytes)); + if (pTemp == NULL) + { + Reallocator::Free(pT); + return NULL; + } + pT = pTemp; + return pTemp; +} + +class CHandle +{ +public: + CHandle() throw(); + CHandle( CHandle& h ) throw(); + explicit CHandle( HANDLE h ) throw(); + ~CHandle() throw(); + + CHandle& operator=( CHandle& h ) throw(); + + operator HANDLE() const throw(); + + // Attach to an existing handle (takes ownership). + void Attach( HANDLE h ) throw(); + // Detach the handle from the object (releases ownership). + HANDLE Detach() throw(); + + // Close the handle. + void Close() throw(); + +public: + HANDLE m_h; +}; + +inline CHandle::CHandle() throw() : + m_h( NULL ) +{ +} + +inline CHandle::CHandle( CHandle& h ) throw() : + m_h( NULL ) +{ + Attach( h.Detach() ); +} + +inline CHandle::CHandle( HANDLE h ) throw() : + m_h( h ) +{ +} + +inline CHandle::~CHandle() throw() +{ + if( m_h != NULL ) + { + Close(); + } +} + +inline CHandle& CHandle::operator=( CHandle& h ) throw() +{ + if( this != &h ) + { + if( m_h != NULL ) + { + Close(); + } + Attach( h.Detach() ); + } + + return( *this ); +} + +inline CHandle::operator HANDLE() const throw() +{ + return( m_h ); +} + +inline void CHandle::Attach( HANDLE h ) throw() +{ + ATLASSUME( m_h == NULL ); + m_h = h; // Take ownership +} + +inline HANDLE CHandle::Detach() throw() +{ + HANDLE h; + + h = m_h; // Release ownership + m_h = NULL; + + return( h ); +} + +inline void CHandle::Close() throw() +{ + if( m_h != NULL ) + { + ::CloseHandle( m_h ); + m_h = NULL; + } +} + +class CCritSecLock +{ +public: + CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock = true ); + ~CCritSecLock() throw(); + + void Lock(); + void Unlock() throw(); + +// Implementation +private: + CRITICAL_SECTION& m_cs; + bool m_bLocked; + +// Private to avoid accidental use + CCritSecLock( const CCritSecLock& ) throw(); + CCritSecLock& operator=( const CCritSecLock& ) throw(); +}; + +inline CCritSecLock::CCritSecLock( CRITICAL_SECTION& cs, bool bInitialLock ) : + m_cs( cs ), + m_bLocked( false ) +{ + if( bInitialLock ) + { + Lock(); + } +} + +inline CCritSecLock::~CCritSecLock() throw() +{ + if( m_bLocked ) + { + Unlock(); + } +} + +inline void CCritSecLock::Lock() +{ + ATLASSERT( !m_bLocked ); + __try + { + ::EnterCriticalSection( &m_cs ); + } + __except( STATUS_NO_MEMORY == GetExceptionCode() ) + { + AtlThrow( E_OUTOFMEMORY ); + } + m_bLocked = true; +} + +inline void CCritSecLock::Unlock() throw() +{ + ATLASSUME( m_bLocked ); + ::LeaveCriticalSection( &m_cs ); + m_bLocked = false; +} + +///////////////////////////////////////////////////////////////////////////// +// Interface debugging +#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) +HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw(); +#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI + +#ifdef _ATL_DEBUG_INTERFACES + +struct _QIThunk +{ + STDMETHOD(QueryInterface)(REFIID iid, void** pp) + { + ATLASSUME(m_dwRef >= 0); + ATLASSUME(m_pUnk != NULL); + return m_pUnk->QueryInterface(iid, pp); + } + STDMETHOD_(ULONG, AddRef)() + { + ATLASSUME(m_pUnk != NULL); + if (m_bBreak) + DebugBreak(); + m_pUnk->AddRef(); + return InternalAddRef(); + } + ULONG InternalAddRef() + { + ATLASSUME(m_pUnk != NULL); + if (m_bBreak) + DebugBreak(); + ATLASSUME(m_dwRef >= 0); + long l = InterlockedIncrement(&m_dwRef); + + TCHAR buf[512+1]; +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) + _stprintf_s(buf, _countof(buf), _T("QIThunk - %-10d\tAddRef :\tObject = 0x%p\tRefcount = %d\t"), + m_nIndex, m_pUnk, m_dwRef); +#else +#pragma warning(push) +#pragma warning(disable:4995) // wsprintf is deprecated + wsprintf(buf, _T("QIThunk - %-10d\tAddRef :\tObject = 0x%p\tRefcount = %d\t"), m_nIndex, m_pUnk, m_dwRef); +#pragma warning(pop) +#endif + buf[_countof(buf)-1] = 0; + OutputDebugString(buf); + AtlDumpIID(m_iid, m_lpszClassName, S_OK); + + if (l > m_dwMaxRef) + m_dwMaxRef = l; + return l; + } + STDMETHOD_(ULONG, Release)(); + + STDMETHOD(f3)(); + STDMETHOD(f4)(); + STDMETHOD(f5)(); + STDMETHOD(f6)(); + STDMETHOD(f7)(); + STDMETHOD(f8)(); + STDMETHOD(f9)(); + STDMETHOD(f10)(); + STDMETHOD(f11)(); + STDMETHOD(f12)(); + STDMETHOD(f13)(); + STDMETHOD(f14)(); + STDMETHOD(f15)(); + STDMETHOD(f16)(); + STDMETHOD(f17)(); + STDMETHOD(f18)(); + STDMETHOD(f19)(); + STDMETHOD(f20)(); + STDMETHOD(f21)(); + STDMETHOD(f22)(); + STDMETHOD(f23)(); + STDMETHOD(f24)(); + STDMETHOD(f25)(); + STDMETHOD(f26)(); + STDMETHOD(f27)(); + STDMETHOD(f28)(); + STDMETHOD(f29)(); + STDMETHOD(f30)(); + STDMETHOD(f31)(); + STDMETHOD(f32)(); + STDMETHOD(f33)(); + STDMETHOD(f34)(); + STDMETHOD(f35)(); + STDMETHOD(f36)(); + STDMETHOD(f37)(); + STDMETHOD(f38)(); + STDMETHOD(f39)(); + STDMETHOD(f40)(); + STDMETHOD(f41)(); + STDMETHOD(f42)(); + STDMETHOD(f43)(); + STDMETHOD(f44)(); + STDMETHOD(f45)(); + STDMETHOD(f46)(); + STDMETHOD(f47)(); + STDMETHOD(f48)(); + STDMETHOD(f49)(); + STDMETHOD(f50)(); + STDMETHOD(f51)(); + STDMETHOD(f52)(); + STDMETHOD(f53)(); + STDMETHOD(f54)(); + STDMETHOD(f55)(); + STDMETHOD(f56)(); + STDMETHOD(f57)(); + STDMETHOD(f58)(); + STDMETHOD(f59)(); + STDMETHOD(f60)(); + STDMETHOD(f61)(); + STDMETHOD(f62)(); + STDMETHOD(f63)(); + STDMETHOD(f64)(); + STDMETHOD(f65)(); + STDMETHOD(f66)(); + STDMETHOD(f67)(); + STDMETHOD(f68)(); + STDMETHOD(f69)(); + STDMETHOD(f70)(); + STDMETHOD(f71)(); + STDMETHOD(f72)(); + STDMETHOD(f73)(); + STDMETHOD(f74)(); + STDMETHOD(f75)(); + STDMETHOD(f76)(); + STDMETHOD(f77)(); + STDMETHOD(f78)(); + STDMETHOD(f79)(); + STDMETHOD(f80)(); + STDMETHOD(f81)(); + STDMETHOD(f82)(); + STDMETHOD(f83)(); + STDMETHOD(f84)(); + STDMETHOD(f85)(); + STDMETHOD(f86)(); + STDMETHOD(f87)(); + STDMETHOD(f88)(); + STDMETHOD(f89)(); + STDMETHOD(f90)(); + STDMETHOD(f91)(); + STDMETHOD(f92)(); + STDMETHOD(f93)(); + STDMETHOD(f94)(); + STDMETHOD(f95)(); + STDMETHOD(f96)(); + STDMETHOD(f97)(); + STDMETHOD(f98)(); + STDMETHOD(f99)(); + STDMETHOD(f100)(); + STDMETHOD(f101)(); + STDMETHOD(f102)(); + STDMETHOD(f103)(); + STDMETHOD(f104)(); + STDMETHOD(f105)(); + STDMETHOD(f106)(); + STDMETHOD(f107)(); + STDMETHOD(f108)(); + STDMETHOD(f109)(); + STDMETHOD(f110)(); + STDMETHOD(f111)(); + STDMETHOD(f112)(); + STDMETHOD(f113)(); + STDMETHOD(f114)(); + STDMETHOD(f115)(); + STDMETHOD(f116)(); + STDMETHOD(f117)(); + STDMETHOD(f118)(); + STDMETHOD(f119)(); + STDMETHOD(f120)(); + STDMETHOD(f121)(); + STDMETHOD(f122)(); + STDMETHOD(f123)(); + STDMETHOD(f124)(); + STDMETHOD(f125)(); + STDMETHOD(f126)(); + STDMETHOD(f127)(); + STDMETHOD(f128)(); + STDMETHOD(f129)(); + STDMETHOD(f130)(); + STDMETHOD(f131)(); + STDMETHOD(f132)(); + STDMETHOD(f133)(); + STDMETHOD(f134)(); + STDMETHOD(f135)(); + STDMETHOD(f136)(); + STDMETHOD(f137)(); + STDMETHOD(f138)(); + STDMETHOD(f139)(); + STDMETHOD(f140)(); + STDMETHOD(f141)(); + STDMETHOD(f142)(); + STDMETHOD(f143)(); + STDMETHOD(f144)(); + STDMETHOD(f145)(); + STDMETHOD(f146)(); + STDMETHOD(f147)(); + STDMETHOD(f148)(); + STDMETHOD(f149)(); + STDMETHOD(f150)(); + STDMETHOD(f151)(); + STDMETHOD(f152)(); + STDMETHOD(f153)(); + STDMETHOD(f154)(); + STDMETHOD(f155)(); + STDMETHOD(f156)(); + STDMETHOD(f157)(); + STDMETHOD(f158)(); + STDMETHOD(f159)(); + STDMETHOD(f160)(); + STDMETHOD(f161)(); + STDMETHOD(f162)(); + STDMETHOD(f163)(); + STDMETHOD(f164)(); + STDMETHOD(f165)(); + STDMETHOD(f166)(); + STDMETHOD(f167)(); + STDMETHOD(f168)(); + STDMETHOD(f169)(); + STDMETHOD(f170)(); + STDMETHOD(f171)(); + STDMETHOD(f172)(); + STDMETHOD(f173)(); + STDMETHOD(f174)(); + STDMETHOD(f175)(); + STDMETHOD(f176)(); + STDMETHOD(f177)(); + STDMETHOD(f178)(); + STDMETHOD(f179)(); + STDMETHOD(f180)(); + STDMETHOD(f181)(); + STDMETHOD(f182)(); + STDMETHOD(f183)(); + STDMETHOD(f184)(); + STDMETHOD(f185)(); + STDMETHOD(f186)(); + STDMETHOD(f187)(); + STDMETHOD(f188)(); + STDMETHOD(f189)(); + STDMETHOD(f190)(); + STDMETHOD(f191)(); + STDMETHOD(f192)(); + STDMETHOD(f193)(); + STDMETHOD(f194)(); + STDMETHOD(f195)(); + STDMETHOD(f196)(); + STDMETHOD(f197)(); + STDMETHOD(f198)(); + STDMETHOD(f199)(); + STDMETHOD(f200)(); + STDMETHOD(f201)(); + STDMETHOD(f202)(); + STDMETHOD(f203)(); + STDMETHOD(f204)(); + STDMETHOD(f205)(); + STDMETHOD(f206)(); + STDMETHOD(f207)(); + STDMETHOD(f208)(); + STDMETHOD(f209)(); + STDMETHOD(f210)(); + STDMETHOD(f211)(); + STDMETHOD(f212)(); + STDMETHOD(f213)(); + STDMETHOD(f214)(); + STDMETHOD(f215)(); + STDMETHOD(f216)(); + STDMETHOD(f217)(); + STDMETHOD(f218)(); + STDMETHOD(f219)(); + STDMETHOD(f220)(); + STDMETHOD(f221)(); + STDMETHOD(f222)(); + STDMETHOD(f223)(); + STDMETHOD(f224)(); + STDMETHOD(f225)(); + STDMETHOD(f226)(); + STDMETHOD(f227)(); + STDMETHOD(f228)(); + STDMETHOD(f229)(); + STDMETHOD(f230)(); + STDMETHOD(f231)(); + STDMETHOD(f232)(); + STDMETHOD(f233)(); + STDMETHOD(f234)(); + STDMETHOD(f235)(); + STDMETHOD(f236)(); + STDMETHOD(f237)(); + STDMETHOD(f238)(); + STDMETHOD(f239)(); + STDMETHOD(f240)(); + STDMETHOD(f241)(); + STDMETHOD(f242)(); + STDMETHOD(f243)(); + STDMETHOD(f244)(); + STDMETHOD(f245)(); + STDMETHOD(f246)(); + STDMETHOD(f247)(); + STDMETHOD(f248)(); + STDMETHOD(f249)(); + STDMETHOD(f250)(); + STDMETHOD(f251)(); + STDMETHOD(f252)(); + STDMETHOD(f253)(); + STDMETHOD(f254)(); + STDMETHOD(f255)(); + STDMETHOD(f256)(); + STDMETHOD(f257)(); + STDMETHOD(f258)(); + STDMETHOD(f259)(); + STDMETHOD(f260)(); + STDMETHOD(f261)(); + STDMETHOD(f262)(); + STDMETHOD(f263)(); + STDMETHOD(f264)(); + STDMETHOD(f265)(); + STDMETHOD(f266)(); + STDMETHOD(f267)(); + STDMETHOD(f268)(); + STDMETHOD(f269)(); + STDMETHOD(f270)(); + STDMETHOD(f271)(); + STDMETHOD(f272)(); + STDMETHOD(f273)(); + STDMETHOD(f274)(); + STDMETHOD(f275)(); + STDMETHOD(f276)(); + STDMETHOD(f277)(); + STDMETHOD(f278)(); + STDMETHOD(f279)(); + STDMETHOD(f280)(); + STDMETHOD(f281)(); + STDMETHOD(f282)(); + STDMETHOD(f283)(); + STDMETHOD(f284)(); + STDMETHOD(f285)(); + STDMETHOD(f286)(); + STDMETHOD(f287)(); + STDMETHOD(f288)(); + STDMETHOD(f289)(); + STDMETHOD(f290)(); + STDMETHOD(f291)(); + STDMETHOD(f292)(); + STDMETHOD(f293)(); + STDMETHOD(f294)(); + STDMETHOD(f295)(); + STDMETHOD(f296)(); + STDMETHOD(f297)(); + STDMETHOD(f298)(); + STDMETHOD(f299)(); + STDMETHOD(f300)(); + STDMETHOD(f301)(); + STDMETHOD(f302)(); + STDMETHOD(f303)(); + STDMETHOD(f304)(); + STDMETHOD(f305)(); + STDMETHOD(f306)(); + STDMETHOD(f307)(); + STDMETHOD(f308)(); + STDMETHOD(f309)(); + STDMETHOD(f310)(); + STDMETHOD(f311)(); + STDMETHOD(f312)(); + STDMETHOD(f313)(); + STDMETHOD(f314)(); + STDMETHOD(f315)(); + STDMETHOD(f316)(); + STDMETHOD(f317)(); + STDMETHOD(f318)(); + STDMETHOD(f319)(); + STDMETHOD(f320)(); + STDMETHOD(f321)(); + STDMETHOD(f322)(); + STDMETHOD(f323)(); + STDMETHOD(f324)(); + STDMETHOD(f325)(); + STDMETHOD(f326)(); + STDMETHOD(f327)(); + STDMETHOD(f328)(); + STDMETHOD(f329)(); + STDMETHOD(f330)(); + STDMETHOD(f331)(); + STDMETHOD(f332)(); + STDMETHOD(f333)(); + STDMETHOD(f334)(); + STDMETHOD(f335)(); + STDMETHOD(f336)(); + STDMETHOD(f337)(); + STDMETHOD(f338)(); + STDMETHOD(f339)(); + STDMETHOD(f340)(); + STDMETHOD(f341)(); + STDMETHOD(f342)(); + STDMETHOD(f343)(); + STDMETHOD(f344)(); + STDMETHOD(f345)(); + STDMETHOD(f346)(); + STDMETHOD(f347)(); + STDMETHOD(f348)(); + STDMETHOD(f349)(); + STDMETHOD(f350)(); + STDMETHOD(f351)(); + STDMETHOD(f352)(); + STDMETHOD(f353)(); + STDMETHOD(f354)(); + STDMETHOD(f355)(); + STDMETHOD(f356)(); + STDMETHOD(f357)(); + STDMETHOD(f358)(); + STDMETHOD(f359)(); + STDMETHOD(f360)(); + STDMETHOD(f361)(); + STDMETHOD(f362)(); + STDMETHOD(f363)(); + STDMETHOD(f364)(); + STDMETHOD(f365)(); + STDMETHOD(f366)(); + STDMETHOD(f367)(); + STDMETHOD(f368)(); + STDMETHOD(f369)(); + STDMETHOD(f370)(); + STDMETHOD(f371)(); + STDMETHOD(f372)(); + STDMETHOD(f373)(); + STDMETHOD(f374)(); + STDMETHOD(f375)(); + STDMETHOD(f376)(); + STDMETHOD(f377)(); + STDMETHOD(f378)(); + STDMETHOD(f379)(); + STDMETHOD(f380)(); + STDMETHOD(f381)(); + STDMETHOD(f382)(); + STDMETHOD(f383)(); + STDMETHOD(f384)(); + STDMETHOD(f385)(); + STDMETHOD(f386)(); + STDMETHOD(f387)(); + STDMETHOD(f388)(); + STDMETHOD(f389)(); + STDMETHOD(f390)(); + STDMETHOD(f391)(); + STDMETHOD(f392)(); + STDMETHOD(f393)(); + STDMETHOD(f394)(); + STDMETHOD(f395)(); + STDMETHOD(f396)(); + STDMETHOD(f397)(); + STDMETHOD(f398)(); + STDMETHOD(f399)(); + STDMETHOD(f400)(); + STDMETHOD(f401)(); + STDMETHOD(f402)(); + STDMETHOD(f403)(); + STDMETHOD(f404)(); + STDMETHOD(f405)(); + STDMETHOD(f406)(); + STDMETHOD(f407)(); + STDMETHOD(f408)(); + STDMETHOD(f409)(); + STDMETHOD(f410)(); + STDMETHOD(f411)(); + STDMETHOD(f412)(); + STDMETHOD(f413)(); + STDMETHOD(f414)(); + STDMETHOD(f415)(); + STDMETHOD(f416)(); + STDMETHOD(f417)(); + STDMETHOD(f418)(); + STDMETHOD(f419)(); + STDMETHOD(f420)(); + STDMETHOD(f421)(); + STDMETHOD(f422)(); + STDMETHOD(f423)(); + STDMETHOD(f424)(); + STDMETHOD(f425)(); + STDMETHOD(f426)(); + STDMETHOD(f427)(); + STDMETHOD(f428)(); + STDMETHOD(f429)(); + STDMETHOD(f430)(); + STDMETHOD(f431)(); + STDMETHOD(f432)(); + STDMETHOD(f433)(); + STDMETHOD(f434)(); + STDMETHOD(f435)(); + STDMETHOD(f436)(); + STDMETHOD(f437)(); + STDMETHOD(f438)(); + STDMETHOD(f439)(); + STDMETHOD(f440)(); + STDMETHOD(f441)(); + STDMETHOD(f442)(); + STDMETHOD(f443)(); + STDMETHOD(f444)(); + STDMETHOD(f445)(); + STDMETHOD(f446)(); + STDMETHOD(f447)(); + STDMETHOD(f448)(); + STDMETHOD(f449)(); + STDMETHOD(f450)(); + STDMETHOD(f451)(); + STDMETHOD(f452)(); + STDMETHOD(f453)(); + STDMETHOD(f454)(); + STDMETHOD(f455)(); + STDMETHOD(f456)(); + STDMETHOD(f457)(); + STDMETHOD(f458)(); + STDMETHOD(f459)(); + STDMETHOD(f460)(); + STDMETHOD(f461)(); + STDMETHOD(f462)(); + STDMETHOD(f463)(); + STDMETHOD(f464)(); + STDMETHOD(f465)(); + STDMETHOD(f466)(); + STDMETHOD(f467)(); + STDMETHOD(f468)(); + STDMETHOD(f469)(); + STDMETHOD(f470)(); + STDMETHOD(f471)(); + STDMETHOD(f472)(); + STDMETHOD(f473)(); + STDMETHOD(f474)(); + STDMETHOD(f475)(); + STDMETHOD(f476)(); + STDMETHOD(f477)(); + STDMETHOD(f478)(); + STDMETHOD(f479)(); + STDMETHOD(f480)(); + STDMETHOD(f481)(); + STDMETHOD(f482)(); + STDMETHOD(f483)(); + STDMETHOD(f484)(); + STDMETHOD(f485)(); + STDMETHOD(f486)(); + STDMETHOD(f487)(); + STDMETHOD(f488)(); + STDMETHOD(f489)(); + STDMETHOD(f490)(); + STDMETHOD(f491)(); + STDMETHOD(f492)(); + STDMETHOD(f493)(); + STDMETHOD(f494)(); + STDMETHOD(f495)(); + STDMETHOD(f496)(); + STDMETHOD(f497)(); + STDMETHOD(f498)(); + STDMETHOD(f499)(); + STDMETHOD(f500)(); + STDMETHOD(f501)(); + STDMETHOD(f502)(); + STDMETHOD(f503)(); + STDMETHOD(f504)(); + STDMETHOD(f505)(); + STDMETHOD(f506)(); + STDMETHOD(f507)(); + STDMETHOD(f508)(); + STDMETHOD(f509)(); + STDMETHOD(f510)(); + STDMETHOD(f511)(); + STDMETHOD(f512)(); + STDMETHOD(f513)(); + STDMETHOD(f514)(); + STDMETHOD(f515)(); + STDMETHOD(f516)(); + STDMETHOD(f517)(); + STDMETHOD(f518)(); + STDMETHOD(f519)(); + STDMETHOD(f520)(); + STDMETHOD(f521)(); + STDMETHOD(f522)(); + STDMETHOD(f523)(); + STDMETHOD(f524)(); + STDMETHOD(f525)(); + STDMETHOD(f526)(); + STDMETHOD(f527)(); + STDMETHOD(f528)(); + STDMETHOD(f529)(); + STDMETHOD(f530)(); + STDMETHOD(f531)(); + STDMETHOD(f532)(); + STDMETHOD(f533)(); + STDMETHOD(f534)(); + STDMETHOD(f535)(); + STDMETHOD(f536)(); + STDMETHOD(f537)(); + STDMETHOD(f538)(); + STDMETHOD(f539)(); + STDMETHOD(f540)(); + STDMETHOD(f541)(); + STDMETHOD(f542)(); + STDMETHOD(f543)(); + STDMETHOD(f544)(); + STDMETHOD(f545)(); + STDMETHOD(f546)(); + STDMETHOD(f547)(); + STDMETHOD(f548)(); + STDMETHOD(f549)(); + STDMETHOD(f550)(); + STDMETHOD(f551)(); + STDMETHOD(f552)(); + STDMETHOD(f553)(); + STDMETHOD(f554)(); + STDMETHOD(f555)(); + STDMETHOD(f556)(); + STDMETHOD(f557)(); + STDMETHOD(f558)(); + STDMETHOD(f559)(); + STDMETHOD(f560)(); + STDMETHOD(f561)(); + STDMETHOD(f562)(); + STDMETHOD(f563)(); + STDMETHOD(f564)(); + STDMETHOD(f565)(); + STDMETHOD(f566)(); + STDMETHOD(f567)(); + STDMETHOD(f568)(); + STDMETHOD(f569)(); + STDMETHOD(f570)(); + STDMETHOD(f571)(); + STDMETHOD(f572)(); + STDMETHOD(f573)(); + STDMETHOD(f574)(); + STDMETHOD(f575)(); + STDMETHOD(f576)(); + STDMETHOD(f577)(); + STDMETHOD(f578)(); + STDMETHOD(f579)(); + STDMETHOD(f580)(); + STDMETHOD(f581)(); + STDMETHOD(f582)(); + STDMETHOD(f583)(); + STDMETHOD(f584)(); + STDMETHOD(f585)(); + STDMETHOD(f586)(); + STDMETHOD(f587)(); + STDMETHOD(f588)(); + STDMETHOD(f589)(); + STDMETHOD(f590)(); + STDMETHOD(f591)(); + STDMETHOD(f592)(); + STDMETHOD(f593)(); + STDMETHOD(f594)(); + STDMETHOD(f595)(); + STDMETHOD(f596)(); + STDMETHOD(f597)(); + STDMETHOD(f598)(); + STDMETHOD(f599)(); + STDMETHOD(f600)(); + STDMETHOD(f601)(); + STDMETHOD(f602)(); + STDMETHOD(f603)(); + STDMETHOD(f604)(); + STDMETHOD(f605)(); + STDMETHOD(f606)(); + STDMETHOD(f607)(); + STDMETHOD(f608)(); + STDMETHOD(f609)(); + STDMETHOD(f610)(); + STDMETHOD(f611)(); + STDMETHOD(f612)(); + STDMETHOD(f613)(); + STDMETHOD(f614)(); + STDMETHOD(f615)(); + STDMETHOD(f616)(); + STDMETHOD(f617)(); + STDMETHOD(f618)(); + STDMETHOD(f619)(); + STDMETHOD(f620)(); + STDMETHOD(f621)(); + STDMETHOD(f622)(); + STDMETHOD(f623)(); + STDMETHOD(f624)(); + STDMETHOD(f625)(); + STDMETHOD(f626)(); + STDMETHOD(f627)(); + STDMETHOD(f628)(); + STDMETHOD(f629)(); + STDMETHOD(f630)(); + STDMETHOD(f631)(); + STDMETHOD(f632)(); + STDMETHOD(f633)(); + STDMETHOD(f634)(); + STDMETHOD(f635)(); + STDMETHOD(f636)(); + STDMETHOD(f637)(); + STDMETHOD(f638)(); + STDMETHOD(f639)(); + STDMETHOD(f640)(); + STDMETHOD(f641)(); + STDMETHOD(f642)(); + STDMETHOD(f643)(); + STDMETHOD(f644)(); + STDMETHOD(f645)(); + STDMETHOD(f646)(); + STDMETHOD(f647)(); + STDMETHOD(f648)(); + STDMETHOD(f649)(); + STDMETHOD(f650)(); + STDMETHOD(f651)(); + STDMETHOD(f652)(); + STDMETHOD(f653)(); + STDMETHOD(f654)(); + STDMETHOD(f655)(); + STDMETHOD(f656)(); + STDMETHOD(f657)(); + STDMETHOD(f658)(); + STDMETHOD(f659)(); + STDMETHOD(f660)(); + STDMETHOD(f661)(); + STDMETHOD(f662)(); + STDMETHOD(f663)(); + STDMETHOD(f664)(); + STDMETHOD(f665)(); + STDMETHOD(f666)(); + STDMETHOD(f667)(); + STDMETHOD(f668)(); + STDMETHOD(f669)(); + STDMETHOD(f670)(); + STDMETHOD(f671)(); + STDMETHOD(f672)(); + STDMETHOD(f673)(); + STDMETHOD(f674)(); + STDMETHOD(f675)(); + STDMETHOD(f676)(); + STDMETHOD(f677)(); + STDMETHOD(f678)(); + STDMETHOD(f679)(); + STDMETHOD(f680)(); + STDMETHOD(f681)(); + STDMETHOD(f682)(); + STDMETHOD(f683)(); + STDMETHOD(f684)(); + STDMETHOD(f685)(); + STDMETHOD(f686)(); + STDMETHOD(f687)(); + STDMETHOD(f688)(); + STDMETHOD(f689)(); + STDMETHOD(f690)(); + STDMETHOD(f691)(); + STDMETHOD(f692)(); + STDMETHOD(f693)(); + STDMETHOD(f694)(); + STDMETHOD(f695)(); + STDMETHOD(f696)(); + STDMETHOD(f697)(); + STDMETHOD(f698)(); + STDMETHOD(f699)(); + STDMETHOD(f700)(); + STDMETHOD(f701)(); + STDMETHOD(f702)(); + STDMETHOD(f703)(); + STDMETHOD(f704)(); + STDMETHOD(f705)(); + STDMETHOD(f706)(); + STDMETHOD(f707)(); + STDMETHOD(f708)(); + STDMETHOD(f709)(); + STDMETHOD(f710)(); + STDMETHOD(f711)(); + STDMETHOD(f712)(); + STDMETHOD(f713)(); + STDMETHOD(f714)(); + STDMETHOD(f715)(); + STDMETHOD(f716)(); + STDMETHOD(f717)(); + STDMETHOD(f718)(); + STDMETHOD(f719)(); + STDMETHOD(f720)(); + STDMETHOD(f721)(); + STDMETHOD(f722)(); + STDMETHOD(f723)(); + STDMETHOD(f724)(); + STDMETHOD(f725)(); + STDMETHOD(f726)(); + STDMETHOD(f727)(); + STDMETHOD(f728)(); + STDMETHOD(f729)(); + STDMETHOD(f730)(); + STDMETHOD(f731)(); + STDMETHOD(f732)(); + STDMETHOD(f733)(); + STDMETHOD(f734)(); + STDMETHOD(f735)(); + STDMETHOD(f736)(); + STDMETHOD(f737)(); + STDMETHOD(f738)(); + STDMETHOD(f739)(); + STDMETHOD(f740)(); + STDMETHOD(f741)(); + STDMETHOD(f742)(); + STDMETHOD(f743)(); + STDMETHOD(f744)(); + STDMETHOD(f745)(); + STDMETHOD(f746)(); + STDMETHOD(f747)(); + STDMETHOD(f748)(); + STDMETHOD(f749)(); + STDMETHOD(f750)(); + STDMETHOD(f751)(); + STDMETHOD(f752)(); + STDMETHOD(f753)(); + STDMETHOD(f754)(); + STDMETHOD(f755)(); + STDMETHOD(f756)(); + STDMETHOD(f757)(); + STDMETHOD(f758)(); + STDMETHOD(f759)(); + STDMETHOD(f760)(); + STDMETHOD(f761)(); + STDMETHOD(f762)(); + STDMETHOD(f763)(); + STDMETHOD(f764)(); + STDMETHOD(f765)(); + STDMETHOD(f766)(); + STDMETHOD(f767)(); + STDMETHOD(f768)(); + STDMETHOD(f769)(); + STDMETHOD(f770)(); + STDMETHOD(f771)(); + STDMETHOD(f772)(); + STDMETHOD(f773)(); + STDMETHOD(f774)(); + STDMETHOD(f775)(); + STDMETHOD(f776)(); + STDMETHOD(f777)(); + STDMETHOD(f778)(); + STDMETHOD(f779)(); + STDMETHOD(f780)(); + STDMETHOD(f781)(); + STDMETHOD(f782)(); + STDMETHOD(f783)(); + STDMETHOD(f784)(); + STDMETHOD(f785)(); + STDMETHOD(f786)(); + STDMETHOD(f787)(); + STDMETHOD(f788)(); + STDMETHOD(f789)(); + STDMETHOD(f790)(); + STDMETHOD(f791)(); + STDMETHOD(f792)(); + STDMETHOD(f793)(); + STDMETHOD(f794)(); + STDMETHOD(f795)(); + STDMETHOD(f796)(); + STDMETHOD(f797)(); + STDMETHOD(f798)(); + STDMETHOD(f799)(); + STDMETHOD(f800)(); + STDMETHOD(f801)(); + STDMETHOD(f802)(); + STDMETHOD(f803)(); + STDMETHOD(f804)(); + STDMETHOD(f805)(); + STDMETHOD(f806)(); + STDMETHOD(f807)(); + STDMETHOD(f808)(); + STDMETHOD(f809)(); + STDMETHOD(f810)(); + STDMETHOD(f811)(); + STDMETHOD(f812)(); + STDMETHOD(f813)(); + STDMETHOD(f814)(); + STDMETHOD(f815)(); + STDMETHOD(f816)(); + STDMETHOD(f817)(); + STDMETHOD(f818)(); + STDMETHOD(f819)(); + STDMETHOD(f820)(); + STDMETHOD(f821)(); + STDMETHOD(f822)(); + STDMETHOD(f823)(); + STDMETHOD(f824)(); + STDMETHOD(f825)(); + STDMETHOD(f826)(); + STDMETHOD(f827)(); + STDMETHOD(f828)(); + STDMETHOD(f829)(); + STDMETHOD(f830)(); + STDMETHOD(f831)(); + STDMETHOD(f832)(); + STDMETHOD(f833)(); + STDMETHOD(f834)(); + STDMETHOD(f835)(); + STDMETHOD(f836)(); + STDMETHOD(f837)(); + STDMETHOD(f838)(); + STDMETHOD(f839)(); + STDMETHOD(f840)(); + STDMETHOD(f841)(); + STDMETHOD(f842)(); + STDMETHOD(f843)(); + STDMETHOD(f844)(); + STDMETHOD(f845)(); + STDMETHOD(f846)(); + STDMETHOD(f847)(); + STDMETHOD(f848)(); + STDMETHOD(f849)(); + STDMETHOD(f850)(); + STDMETHOD(f851)(); + STDMETHOD(f852)(); + STDMETHOD(f853)(); + STDMETHOD(f854)(); + STDMETHOD(f855)(); + STDMETHOD(f856)(); + STDMETHOD(f857)(); + STDMETHOD(f858)(); + STDMETHOD(f859)(); + STDMETHOD(f860)(); + STDMETHOD(f861)(); + STDMETHOD(f862)(); + STDMETHOD(f863)(); + STDMETHOD(f864)(); + STDMETHOD(f865)(); + STDMETHOD(f866)(); + STDMETHOD(f867)(); + STDMETHOD(f868)(); + STDMETHOD(f869)(); + STDMETHOD(f870)(); + STDMETHOD(f871)(); + STDMETHOD(f872)(); + STDMETHOD(f873)(); + STDMETHOD(f874)(); + STDMETHOD(f875)(); + STDMETHOD(f876)(); + STDMETHOD(f877)(); + STDMETHOD(f878)(); + STDMETHOD(f879)(); + STDMETHOD(f880)(); + STDMETHOD(f881)(); + STDMETHOD(f882)(); + STDMETHOD(f883)(); + STDMETHOD(f884)(); + STDMETHOD(f885)(); + STDMETHOD(f886)(); + STDMETHOD(f887)(); + STDMETHOD(f888)(); + STDMETHOD(f889)(); + STDMETHOD(f890)(); + STDMETHOD(f891)(); + STDMETHOD(f892)(); + STDMETHOD(f893)(); + STDMETHOD(f894)(); + STDMETHOD(f895)(); + STDMETHOD(f896)(); + STDMETHOD(f897)(); + STDMETHOD(f898)(); + STDMETHOD(f899)(); + STDMETHOD(f900)(); + STDMETHOD(f901)(); + STDMETHOD(f902)(); + STDMETHOD(f903)(); + STDMETHOD(f904)(); + STDMETHOD(f905)(); + STDMETHOD(f906)(); + STDMETHOD(f907)(); + STDMETHOD(f908)(); + STDMETHOD(f909)(); + STDMETHOD(f910)(); + STDMETHOD(f911)(); + STDMETHOD(f912)(); + STDMETHOD(f913)(); + STDMETHOD(f914)(); + STDMETHOD(f915)(); + STDMETHOD(f916)(); + STDMETHOD(f917)(); + STDMETHOD(f918)(); + STDMETHOD(f919)(); + STDMETHOD(f920)(); + STDMETHOD(f921)(); + STDMETHOD(f922)(); + STDMETHOD(f923)(); + STDMETHOD(f924)(); + STDMETHOD(f925)(); + STDMETHOD(f926)(); + STDMETHOD(f927)(); + STDMETHOD(f928)(); + STDMETHOD(f929)(); + STDMETHOD(f930)(); + STDMETHOD(f931)(); + STDMETHOD(f932)(); + STDMETHOD(f933)(); + STDMETHOD(f934)(); + STDMETHOD(f935)(); + STDMETHOD(f936)(); + STDMETHOD(f937)(); + STDMETHOD(f938)(); + STDMETHOD(f939)(); + STDMETHOD(f940)(); + STDMETHOD(f941)(); + STDMETHOD(f942)(); + STDMETHOD(f943)(); + STDMETHOD(f944)(); + STDMETHOD(f945)(); + STDMETHOD(f946)(); + STDMETHOD(f947)(); + STDMETHOD(f948)(); + STDMETHOD(f949)(); + STDMETHOD(f950)(); + STDMETHOD(f951)(); + STDMETHOD(f952)(); + STDMETHOD(f953)(); + STDMETHOD(f954)(); + STDMETHOD(f955)(); + STDMETHOD(f956)(); + STDMETHOD(f957)(); + STDMETHOD(f958)(); + STDMETHOD(f959)(); + STDMETHOD(f960)(); + STDMETHOD(f961)(); + STDMETHOD(f962)(); + STDMETHOD(f963)(); + STDMETHOD(f964)(); + STDMETHOD(f965)(); + STDMETHOD(f966)(); + STDMETHOD(f967)(); + STDMETHOD(f968)(); + STDMETHOD(f969)(); + STDMETHOD(f970)(); + STDMETHOD(f971)(); + STDMETHOD(f972)(); + STDMETHOD(f973)(); + STDMETHOD(f974)(); + STDMETHOD(f975)(); + STDMETHOD(f976)(); + STDMETHOD(f977)(); + STDMETHOD(f978)(); + STDMETHOD(f979)(); + STDMETHOD(f980)(); + STDMETHOD(f981)(); + STDMETHOD(f982)(); + STDMETHOD(f983)(); + STDMETHOD(f984)(); + STDMETHOD(f985)(); + STDMETHOD(f986)(); + STDMETHOD(f987)(); + STDMETHOD(f988)(); + STDMETHOD(f989)(); + STDMETHOD(f990)(); + STDMETHOD(f991)(); + STDMETHOD(f992)(); + STDMETHOD(f993)(); + STDMETHOD(f994)(); + STDMETHOD(f995)(); + STDMETHOD(f996)(); + STDMETHOD(f997)(); + STDMETHOD(f998)(); + STDMETHOD(f999)(); + STDMETHOD(f1000)(); + STDMETHOD(f1001)(); + STDMETHOD(f1002)(); + STDMETHOD(f1003)(); + STDMETHOD(f1004)(); + STDMETHOD(f1005)(); + STDMETHOD(f1006)(); + STDMETHOD(f1007)(); + STDMETHOD(f1008)(); + STDMETHOD(f1009)(); + STDMETHOD(f1010)(); + STDMETHOD(f1011)(); + STDMETHOD(f1012)(); + STDMETHOD(f1013)(); + STDMETHOD(f1014)(); + STDMETHOD(f1015)(); + STDMETHOD(f1016)(); + STDMETHOD(f1017)(); + STDMETHOD(f1018)(); + STDMETHOD(f1019)(); + STDMETHOD(f1020)(); + STDMETHOD(f1021)(); + STDMETHOD(f1022)(); + STDMETHOD(f1023)(); + _QIThunk(IUnknown* pOrig, LPCTSTR p, const IID& i, UINT n, bool b) + { + m_lpszClassName = p; + m_iid = i; + m_nIndex = n; + m_dwRef = 0; + m_dwMaxRef = 0; + ATLENSURE(pOrig); + m_pUnk = pOrig; + m_bBreak = b; + m_bNonAddRefThunk = false; + } + IUnknown* m_pUnk; + long m_dwRef; + long m_dwMaxRef; + LPCTSTR m_lpszClassName; + IID m_iid; + UINT m_nIndex; + bool m_bBreak; + bool m_bNonAddRefThunk; + void Dump() throw(); +}; + +#endif + +///////////////////////////////////////////////////////////////////////////// +// Module Classes + + +#ifdef _ATL_STATIC_REGISTRY +#define UpdateRegistryFromResource UpdateRegistryFromResourceS +#else +#define UpdateRegistryFromResource UpdateRegistryFromResourceD +#endif // _ATL_STATIC_REGISTRY + + +class CAtlComModule : public _ATL_COM_MODULE +{ +public: + + CAtlComModule() throw() + { + cbSize = 0; + + m_hInstTypeLib = reinterpret_cast(&__ImageBase); + + m_ppAutoObjMapFirst = &__pobjMapEntryFirst + 1; + m_ppAutoObjMapLast = &__pobjMapEntryLast; + + if (FAILED(m_csObjMap.Init())) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlComModule\n")); + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + return; + } + // Set cbSize on success. + cbSize = sizeof(_ATL_COM_MODULE); + } + + ~CAtlComModule() + { + Term(); + } + + // Called from ~CAtlComModule or from ~CAtlExeModule. + void Term() + { + if (cbSize == 0) + return; + + for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + { + _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; + if (pEntry->pCF != NULL) + pEntry->pCF->Release(); + pEntry->pCF = NULL; + } + } + m_csObjMap.Term(); + // Set to 0 to indicate that this function has been called + // At this point no one should be concerned about cbsize + // having the correct value + cbSize = 0; + } + + // Registry support (helpers) + HRESULT RegisterTypeLib() + { + return AtlRegisterTypeLib(m_hInstTypeLib, NULL); + } + HRESULT RegisterTypeLib(LPCTSTR lpszIndex) + { + USES_CONVERSION_EX; + LPCOLESTR pwszTemp = NULL; + if( lpszIndex != NULL ) + { + pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if( pwszTemp == NULL ) + return E_OUTOFMEMORY; +#endif + } + return AtlRegisterTypeLib(m_hInstTypeLib, pwszTemp); + } + HRESULT UnRegisterTypeLib() + { + return AtlUnRegisterTypeLib(m_hInstTypeLib, NULL); + } + HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) + { + USES_CONVERSION_EX; + LPCOLESTR pwszTemp = NULL; + if( lpszIndex != NULL ) + { + pwszTemp = T2COLE_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if( pwszTemp == NULL ) + return E_OUTOFMEMORY; +#endif + } + return AtlUnRegisterTypeLib(m_hInstTypeLib, pwszTemp); + } + + // RegisterServer walks the ATL Autogenerated object map and registers each object in the map + // If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) + // otherwise all the objects are registered + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) + { + return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID); + } + + // UnregisterServer walks the ATL Autogenerated object map and unregisters each object in the map + // If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) + // otherwise all the objects are unregistered. + HRESULT UnregisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) + { + return AtlComModuleUnregisterServer(this, bRegTypeLib, pCLSID); + } + + // Implementation + + // Call ObjectMain for all the objects. + void ExecuteObjectMain(bool bStarting) + { + for (_ATL_OBJMAP_ENTRY** ppEntry = m_ppAutoObjMapFirst; ppEntry < m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + (*ppEntry)->pfnObjectMain(bStarting); + } + } +}; + +extern CAtlComModule _AtlComModule; + +#ifdef _ATL_DEBUG_INTERFACES + +class CAtlDebugInterfacesModule +{ +public: + CAtlDebugInterfacesModule() throw() : + m_nIndexQI( 0 ), + m_nIndexBreakAt( 0 ) + { + if (FAILED(m_cs.Init())) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to initialize critical section in CAtlDebugInterfacesModule\n")); + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + } + } + ~CAtlDebugInterfacesModule() throw() + { + // Release all class factories. + _AtlComModule.Term(); + DumpLeakedThunks(); + } + + HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() + { + if ((pp == NULL) || (*pp == NULL)) + return E_POINTER; + IUnknown* p = *pp; + _QIThunk* pThunk = NULL; + CComCritSecLock lock(m_cs, false); + HRESULT hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); + ATLASSERT(0); + return hr; + } + + // Check if exists for identity + if (InlineIsEqualUnknown(iid)) + { + for (int i = 0; i < m_aThunks.GetSize(); i++) + { + if (m_aThunks[i]->m_pUnk == p && InlineIsEqualGUID(m_aThunks[i]->m_iid, iid)) + { + m_aThunks[i]->InternalAddRef(); + pThunk = m_aThunks[i]; + break; + } + } + } + if (pThunk == NULL) + { + ++m_nIndexQI; + if (m_nIndexBreakAt == m_nIndexQI) + DebugBreak(); + ATLTRY(pThunk = new _QIThunk(p, lpsz, iid, m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); + if (pThunk == NULL) + { + return E_OUTOFMEMORY; + } + pThunk->InternalAddRef(); + m_aThunks.Add(pThunk); + } + *pp = (IUnknown*)pThunk; + return S_OK; + } + HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() + { + if (ppThunkRet == NULL) + return E_POINTER; + *ppThunkRet = NULL; + + _QIThunk* pThunk = NULL; + CComCritSecLock lock(m_cs, false); + HRESULT hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); + ATLASSERT(0); + return hr; + } + + // Check if exists already for identity + for (int i = 0; i < m_aThunks.GetSize(); i++) + { + if (m_aThunks[i]->m_pUnk == p) + { + m_aThunks[i]->m_bNonAddRefThunk = true; + pThunk = m_aThunks[i]; + break; + } + } + if (pThunk == NULL) + { + ++m_nIndexQI; + if (m_nIndexBreakAt == m_nIndexQI) + DebugBreak(); + ATLTRY(pThunk = new _QIThunk(p, lpsz, __uuidof(IUnknown), m_nIndexQI, (m_nIndexBreakAt == m_nIndexQI))); + if (pThunk == NULL) + { + return E_OUTOFMEMORY; + } + pThunk->m_bNonAddRefThunk = true; + m_aThunks.Add(pThunk); + } + *ppThunkRet = (IUnknown*)pThunk; + return S_OK;; + } + void DeleteNonAddRefThunk(IUnknown* pUnk) throw() + { + CComCritSecLock lock(m_cs, false); + HRESULT hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); + ATLASSERT(0); + return; + } + + for (int i = 0; i < m_aThunks.GetSize(); i++) + { + if (m_aThunks[i]->m_bNonAddRefThunk && m_aThunks[i]->m_pUnk == pUnk) + { + delete m_aThunks[i]; + m_aThunks.RemoveAt(i); + break; + } + } + } + void DeleteThunk(_QIThunk* p) throw() + { + CComCritSecLock lock(m_cs, false); + HRESULT hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CAtlDebugInterfacesModule\n")); + ATLASSERT(0); + return; + } + + int nIndex = m_aThunks.Find(p); + if (nIndex != -1) + { + m_aThunks[nIndex]->m_pUnk = NULL; + delete m_aThunks[nIndex]; + m_aThunks.RemoveAt(nIndex); + } + } + bool DumpLeakedThunks() + { + bool b = false; + for (int i = 0; i < m_aThunks.GetSize(); i++) + { + b = true; + m_aThunks[i]->Dump(); + delete m_aThunks[i]; + } + m_aThunks.RemoveAll(); + return b; + } + +public: + UINT m_nIndexQI; + UINT m_nIndexBreakAt; + CSimpleArray<_QIThunk*> m_aThunks; + CComAutoDeleteCriticalSection m_cs; +}; + +extern CAtlDebugInterfacesModule _AtlDebugInterfacesModule; + +#ifndef _ATL_STATIC_LIB_IMPL +// Should not be pulled into the static lib +__declspec (selectany) CAtlDebugInterfacesModule _AtlDebugInterfacesModule; +#endif + +inline ULONG _QIThunk::Release() +{ + ATLASSUME(m_pUnk != NULL); + if (m_bBreak) + DebugBreak(); + ATLASSUME(m_dwRef > 0); + + // save copies of member variables we wish to use after the InterlockedDecrement + UINT nIndex = m_nIndex; + IUnknown* pUnk = m_pUnk; + IID iid = m_iid; + LPCTSTR lpszClassName = m_lpszClassName; + bool bNonAddRefThunk = m_bNonAddRefThunk; + + ULONG l = InterlockedDecrement(&m_dwRef); + + TCHAR buf[512+1]; +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) + _stprintf_s(buf, _countof(buf), _T("QIThunk - %-10d\tRelease :\tObject = 0x%p\tRefcount = %d\t"), nIndex, pUnk, l); +#else +#pragma warning(push) +#pragma warning(disable:4995) // wsprintf is deprecated + wsprintf(buf, _T("QIThunk - %-10d\tRelease :\tObject = 0x%p\tRefcount = %d\t"), nIndex, pUnk, l); +#pragma warning(pop) +#endif + buf[_countof(buf)-1] = 0; + OutputDebugString(buf); + AtlDumpIID(iid, lpszClassName, S_OK); + + bool bDeleteThunk = (l == 0 && !bNonAddRefThunk); + pUnk->Release(); + if (bDeleteThunk) + _AtlDebugInterfacesModule.DeleteThunk(this); + return l; +} + +#endif // _ATL_DEBUG_INTERFACES + + +class CAtlWinModule : public _ATL_WIN_MODULE +{ +public: + CAtlWinModule() + { + cbSize = sizeof(_ATL_WIN_MODULE); + HRESULT hr = AtlWinModuleInit(this); + if (FAILED(hr)) + { + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + cbSize = 0; + return; + } + } + + ~CAtlWinModule() + { + Term(); + } + + void Term() + { + AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance()); + } + + void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) + { + AtlWinModuleAddCreateWndData(this, pData, pObject); + } + + void* ExtractCreateWndData() + { + return AtlWinModuleExtractCreateWndData(this); + } +}; + +extern CAtlWinModule _AtlWinModule; + +class CAtlModule; +__declspec(selectany) CAtlModule* _pAtlModule = NULL; + +#if defined(_M_CEE) && !defined(_ATL_MIXED) + +// This small class takes care of releasing the class factories at managed +// shutdown when we are compiling /clr. We can't wait to call _AtlComModule.Term() +// in _AtlComModule destructor, since _AtlComModule is a native global object, and it +// will be destructed after the managed runtime has been shutdown. + +// Notice that if the user defines _ATL_MIXED, he/she will need to take care +// of releasing the eventual managed class factories at the right time. + +class CAtlReleaseManagedClassFactories +{ +public: + CAtlReleaseManagedClassFactories() { } + ~CAtlReleaseManagedClassFactories() + { + _AtlComModule.Term(); + } +}; + +__declspec (selectany) CAtlReleaseManagedClassFactories _AtlReleaseManagedClassFactories; + +extern "C" +{ +__declspec (selectany) void *_pAtlReleaseManagedClassFactories = &_AtlReleaseManagedClassFactories; +} +#if defined(_M_IX86) + #pragma comment(linker, "/include:__pAtlReleaseManagedClassFactories") +#else + #pragma comment(linker, "/include:_pAtlReleaseManagedClassFactories") +#endif + +#endif + +class ATL_NO_VTABLE CAtlModule : public _ATL_MODULE +{ +public : + static GUID m_libid; + IGlobalInterfaceTable* m_pGIT; + + CAtlModule() throw() + { + // Should have only one instance of a class + // derived from CAtlModule in a project. + ATLASSERT(_pAtlModule == NULL); + cbSize = 0; + m_pTermFuncs = NULL; + + m_nLockCnt = 0; + _pAtlModule = this; + m_pGIT = NULL; + + if (FAILED(m_csStaticDataInitAndTypeInfo.Init())) + { + ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to initialize critical section in CAtlModule\n")); + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + return; + } + + // Set cbSize on success. + cbSize = sizeof(_ATL_MODULE); + } + + void Term() throw() + { + // cbSize == 0 indicates that Term has already been called + if (cbSize == 0) + return; + + // Call term functions + if (m_pTermFuncs != NULL) + { + AtlCallTermFunc(this); + m_pTermFuncs = NULL; + } + + if (m_pGIT != NULL) + m_pGIT->Release(); + + m_csStaticDataInitAndTypeInfo.Term(); + + cbSize = 0; + } + + virtual ~CAtlModule() throw() + { + Term(); + } + + virtual LONG Lock() throw() + { + return CComGlobalsThreadModel::Increment(&m_nLockCnt); + } + + virtual LONG Unlock() throw() + { + return CComGlobalsThreadModel::Decrement(&m_nLockCnt); + } + + virtual LONG GetLockCount() throw() + { + return m_nLockCnt; + } + + HRESULT AddTermFunc(_ATL_TERMFUNC* pFunc, DWORD_PTR dw) throw() + { + return AtlModuleAddTermFunc(this, pFunc, dw); + } + + virtual HRESULT GetGITPtr(IGlobalInterfaceTable** ppGIT) throw() + { + ATLASSERT(ppGIT != NULL); + + if (ppGIT == NULL) + return E_POINTER; + + HRESULT hr = S_OK; + if (m_pGIT == NULL) + { + hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, + __uuidof(IGlobalInterfaceTable), (void**)&m_pGIT); + } + + if (SUCCEEDED(hr)) + { + ATLASSUME(m_pGIT != NULL); + *ppGIT = m_pGIT; + m_pGIT->AddRef(); + } + return hr; + } + + virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) throw() = 0; + + // Resource-based Registration +#ifdef _ATL_STATIC_REGISTRY + // Statically linking to Registry Ponent + HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); + HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw(); +#else + HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { + if(lpszRes == NULL) + return E_INVALIDARG; + + USES_CONVERSION_EX; + LPCOLESTR pwszTemp = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifdef _UNICODE + if(pwszTemp == NULL) + return E_OUTOFMEMORY; +#endif + return UpdateRegistryFromResourceDHelper(pwszTemp, bRegister, pMapEntries); + } + HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { + return UpdateRegistryFromResourceDHelper((LPCOLESTR)MAKEINTRESOURCE(nResID), bRegister, pMapEntries); + } +#endif + + // Implementation +#if !defined(_ATL_STATIC_REGISTRY) + inline HRESULT WINAPI UpdateRegistryFromResourceDHelper(LPCOLESTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { + CComPtr spRegistrar; + HRESULT hr = AtlCreateRegistrar(&spRegistrar); + if (FAILED(hr)) + return hr; + + if (NULL != pMapEntries) + { + while (NULL != pMapEntries->szKey) + { + ATLASSERT(NULL != pMapEntries->szData); + spRegistrar->AddReplacement(pMapEntries->szKey, pMapEntries->szData); + pMapEntries++; + } + } + + hr = AddCommonRGSReplacements(spRegistrar); + if (FAILED(hr)) + return hr; + + return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, + NULL, spRegistrar); + } +#endif + + static void EscapeSingleQuote(__out_ecount_z(destSizeInChars) LPOLESTR lpDest,__in size_t destSizeInChars, __in_z LPCOLESTR lp) throw() + { + if (destSizeInChars == 0) + { + return; + } + UINT i = 0; + // copy charecters to the destination buffer but leave the last char to be NULL. + for (i=0; i < destSizeInChars-1 && *lp; i++) + { + lpDest[i] = *lp; + // make sure we won't promote lpDest behind the buffer limit. + if (*lp == '\'' && i < destSizeInChars-2) + lpDest[++i] = *lp; + lp++; + } + lpDest[i] = NULL; + } + + ATL_DEPRECATED("CAtlModule::EscapeSingleQuote(dest, src) is unsafe. Instead, use CAtlModule::EscapeSingleQuote(dest, size, src)") + static void EscapeSingleQuote(__out_z LPOLESTR lpDest, __in_z LPCOLESTR lp) throw() + { + EscapeSingleQuote(lpDest, SIZE_MAX/sizeof(OLECHAR), lp); + } + + // search for an occurence of string p2 in string p1 + static LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2) throw() + { + while (p1 != NULL && *p1 != NULL) + { + LPCTSTR p = p2; + while (p != NULL && *p != NULL) + { + if (*p1 == *p) + return CharNext(p1); + p = CharNext(p); + } + p1 = CharNext(p1); + } + return NULL; + } +#pragma warning(push) +#pragma warning(disable : 4302) // 'type cast' : truncation from 'LPSTR' to 'TCHAR' + + static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw() + { + TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1); + TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2); + while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t') + { + psz1 = CharNext(psz1); + psz2 = CharNext(psz2); + c1 = (TCHAR)CharUpper((LPTSTR)*psz1); + c2 = (TCHAR)CharUpper((LPTSTR)*psz2); + } + if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t')) + return 0; + + return (c1 < c2) ? -1 : 1; + } + +#pragma warning (pop) +}; + +__declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; + +#define DECLARE_LIBID(libid) \ + static void InitLibId() throw() \ + { \ + ATL::CAtlModule::m_libid = libid; \ + } + +#define DECLARE_REGISTRY_APPID_RESOURCEID(resid, appid) \ + static LPCOLESTR GetAppId() throw() \ + { \ + return OLESTR(appid); \ + } \ + static TCHAR* GetAppIdT() throw() \ + { \ + return _T(appid); \ + } \ + static HRESULT WINAPI UpdateRegistryAppId(BOOL bRegister) throw() \ + { \ + ATL::_ATL_REGMAP_ENTRY aMapEntries [] = \ + { \ + { OLESTR("APPID"), GetAppId() }, \ + { NULL, NULL } \ + }; \ + return ATL::_pAtlModule->UpdateRegistryFromResource(resid, bRegister, aMapEntries); \ + } + +inline HRESULT AtlGetGITPtr(IGlobalInterfaceTable** ppGIT) throw() +{ + if (ppGIT == NULL) + return E_POINTER; + + if (_pAtlModule == NULL) + { + return CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, + __uuidof(IGlobalInterfaceTable), (void**)ppGIT); + } + else + { + return _pAtlModule->GetGITPtr(ppGIT); + } +} + +template +class ATL_NO_VTABLE CAtlModuleT : public CAtlModule +{ +public : + CAtlModuleT() throw() + { + T::InitLibId(); + } + + static void InitLibId() throw() + { + } + + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw() + { + (pCLSID); + (bRegTypeLib); + + HRESULT hr = S_OK; + +#ifndef _ATL_NO_COM_SUPPORT + + hr = _AtlComModule.RegisterServer(bRegTypeLib, pCLSID); + +#endif // _ATL_NO_COM_SUPPORT + + +#ifndef _ATL_NO_PERF_SUPPORT + + if (SUCCEEDED(hr) && _pPerfRegFunc != NULL) + hr = (*_pPerfRegFunc)(_AtlBaseModule.m_hInst); + +#endif + + return hr; + } + + HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw() + { + (bUnRegTypeLib); + (pCLSID); + + HRESULT hr = S_OK; + +#ifndef _ATL_NO_PERF_SUPPORT + + if (_pPerfUnRegFunc != NULL) + hr = (*_pPerfUnRegFunc)(); + +#endif + +#ifndef _ATL_NO_COM_SUPPORT + + if (SUCCEEDED(hr)) + hr = _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID); + +#endif // _ATL_NO_COM_SUPPORT + + return hr; + + } + + static HRESULT WINAPI UpdateRegistryAppId(BOOL /*bRegister*/) throw() + { + return S_OK; + } + HRESULT RegisterAppId() throw() + { + return T::UpdateRegistryAppId(TRUE); + } + + HRESULT UnregisterAppId() throw() + { + return T::UpdateRegistryAppId(FALSE); + } + + virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* pRegistrar) throw() + { + return pRegistrar->AddReplacement(L"APPID", T::GetAppId()); + } + static LPCOLESTR GetAppId() throw() + { + return OLESTR(""); + } +}; + +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) +namespace __identifier("") +#pragma warning(pop) +{ + __declspec(selectany) bool DllModuleInitialized = false; +} + +#endif + +template +class ATL_NO_VTABLE CAtlDllModuleT : public CAtlModuleT +{ +public : + CAtlDllModuleT() throw() + { + _AtlComModule.ExecuteObjectMain(true); +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + ATLASSERT(DllModuleInitialized == false); + DllModuleInitialized = true; + _DllMain(DLL_PROCESS_ATTACH, NULL); +#endif + } + + ~CAtlDllModuleT() throw() + { +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + ATLASSERT(DllModuleInitialized == true); + _DllMain(DLL_PROCESS_DETACH, NULL); +#endif + _AtlComModule.ExecuteObjectMain(false); + } + + BOOL WINAPI DllMain(DWORD dwReason, LPVOID lpReserved) throw(); + + BOOL WINAPI _DllMain(DWORD dwReason, LPVOID /* lpReserved */) throw() + { + if (dwReason == DLL_PROCESS_ATTACH) + { + if (CAtlBaseModule::m_bInitFailed) + { + ATLASSERT(0); + return FALSE; + } + +#ifdef _ATL_MIN_CRT + DisableThreadLibraryCalls(_AtlBaseModule.GetModuleInstance()); +#endif + } +#ifdef _DEBUG + else if (dwReason == DLL_PROCESS_DETACH) + { + // Prevent false memory leak reporting. ~CAtlWinModule may be too late. + _AtlWinModule.Term(); + } +#endif // _DEBUG + return TRUE; // ok + } + + HRESULT DllCanUnloadNow() throw() + { + T* pT = static_cast(this); + return (pT->GetLockCount()==0) ? S_OK : S_FALSE; + } + + HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() + { + T* pT = static_cast(this); + return pT->GetClassObject(rclsid, riid, ppv); + } + + HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() + { + LCID lcid = GetThreadLocale(); + SetThreadLocale(LOCALE_SYSTEM_DEFAULT); + // registers object, typelib and all interfaces in typelib + T* pT = static_cast(this); + HRESULT hr = pT->RegisterAppId(); + if (SUCCEEDED(hr)) + hr = pT->RegisterServer(bRegTypeLib); + SetThreadLocale(lcid); + return hr; + } + + HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() + { + LCID lcid = GetThreadLocale(); + SetThreadLocale(LOCALE_SYSTEM_DEFAULT); + T* pT = static_cast(this); + HRESULT hr = pT->UnregisterServer(bUnRegTypeLib); + if (SUCCEEDED(hr)) + hr = pT->UnregisterAppId(); + SetThreadLocale(lcid); + return hr; + } + + // Obtain a Class Factory + HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() + { + +#ifndef _ATL_OLEDB_CONFORMANCE_TESTS + ATLASSERT(ppv != NULL); +#endif + + return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); + } +}; + + +#if (_MSC_VER >= 1400) +#pragma managed(push, off) +#else +#pragma unmanaged +#endif + +template +inline BOOL WINAPI CAtlDllModuleT::DllMain(DWORD dwReason, LPVOID lpReserved) throw() +{ +#if !defined(_ATL_NATIVE_INITIALIZATION) + dwReason; lpReserved; +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + if (dwReason == DLL_PROCESS_ATTACH) + { + ATLASSERT(DllModuleInitialized == false); + } + return TRUE; +#else + return _DllMain(dwReason, lpReserved); +#endif +} + + +#if (_MSC_VER >= 1400) +#pragma managed(pop) +#else +#pragma managed +#endif + +#ifndef _AFX + + +template +class ATL_NO_VTABLE CAtlExeModuleT : public CAtlModuleT +{ +public : +#ifndef _ATL_NO_COM_SUPPORT + + DWORD m_dwMainThreadID; + HANDLE m_hEventShutdown; + DWORD m_dwTimeOut; + DWORD m_dwPause; + bool m_bDelayShutdown; + bool m_bActivity; + bool m_bComInitialized; // Flag that indicates if ATL initialized COM + +#endif // _ATL_NO_COM_SUPPORT + + CAtlExeModuleT() throw() + +#ifndef _ATL_NO_COM_SUPPORT + + : m_dwMainThreadID(::GetCurrentThreadId()), + m_dwTimeOut(5000), + m_dwPause(1000), + m_hEventShutdown(NULL), + m_bDelayShutdown(true), + m_bComInitialized(false) + +#endif // _ATL_NO_COM_SUPPORT + + { +#if !defined(_ATL_NO_COM_SUPPORT) + HRESULT hr = T::InitializeCom(); + if (FAILED(hr)) + { + // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing + // COM and InitializeCOM trying to initialize COM with different flags. + if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL) + { + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + return; + } + } + else + { + m_bComInitialized = true; + } + + + _AtlComModule.ExecuteObjectMain(true); + +#endif // !defined(_ATL_NO_COM_SUPPORT) + + } + + ~CAtlExeModuleT() throw() + { +#ifndef _ATL_NO_COM_SUPPORT + + _AtlComModule.ExecuteObjectMain(false); + +#endif + + // Call term functions before COM is uninitialized + Term(); + +#ifndef _ATL_NO_COM_SUPPORT + + // Clean up AtlComModule before COM is uninitialized + _AtlComModule.Term(); + + if (m_bComInitialized) + T::UninitializeCom(); +#endif // _ATL_NO_COM_SUPPORT + } + + static HRESULT InitializeCom() throw() + { + +#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) + return CoInitializeEx(NULL, COINIT_MULTITHREADED); +#else + return CoInitialize(NULL); +#endif + } + + static void UninitializeCom() throw() + { + CoUninitialize(); + } + + LONG Unlock() throw() + { + LONG lRet = CComGlobalsThreadModel::Decrement(&m_nLockCnt); + +#ifndef _ATL_NO_COM_SUPPORT + + if (lRet == 0) + { + if (m_bDelayShutdown) + { + m_bActivity = true; + ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero + } + else + { + ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); + } + } + +#endif // _ATL_NO_COM_SUPPORT + + return lRet; + } +#ifndef _ATL_NO_COM_SUPPORT + + void MonitorShutdown() throw() + { + while (1) + { + ::WaitForSingleObject(m_hEventShutdown, INFINITE); + DWORD dwWait = 0; + do + { + m_bActivity = false; + dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut); + } while (dwWait == WAIT_OBJECT_0); + // timed out + if (!m_bActivity && m_nLockCnt == 0) // if no activity let's really bail + { +#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) + ::CoSuspendClassObjects(); + if (m_nLockCnt == 0) +#endif + break; + } + } + ::CloseHandle(m_hEventShutdown); + ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); + } + + HANDLE StartMonitor() throw() + { + m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL); + if (m_hEventShutdown == NULL) + { + return NULL; + } + DWORD dwThreadID; + HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID); + if(hThread==NULL) + { + ::CloseHandle(m_hEventShutdown); + } + return hThread; + } + + static DWORD WINAPI MonitorProc(void* pv) throw() + { + CAtlExeModuleT* p = static_cast*>(pv); + p->MonitorShutdown(); + return 0; + } +#endif // _ATL_NO_COM_SUPPORT + + int WinMain(int nShowCmd) throw() + { + if (CAtlBaseModule::m_bInitFailed) + { + ATLASSERT(0); + return -1; + } + T* pT = static_cast(this); + HRESULT hr = S_OK; + + LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT + if (pT->ParseCommandLine(lpCmdLine, &hr) == true) + hr = pT->Run(nShowCmd); + +#ifdef _DEBUG + // Prevent false memory leak reporting. ~CAtlWinModule may be too late. + _AtlWinModule.Term(); +#endif // _DEBUG + return hr; + } + + // Scan command line and perform registration + // Return value specifies if server should run + + // Parses the command line and registers/unregisters the rgs file if necessary + bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() + { + *pnRetCode = S_OK; + + TCHAR szTokens[] = _T("-/"); + + T* pT = static_cast(this); + LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); + while (lpszToken != NULL) + { + if (WordCmpI(lpszToken, _T("UnregServer"))==0) + { + *pnRetCode = pT->UnregisterServer(TRUE); + if (SUCCEEDED(*pnRetCode)) + *pnRetCode = pT->UnregisterAppId(); + return false; + } + + // Register as Local Server + if (WordCmpI(lpszToken, _T("RegServer"))==0) + { + *pnRetCode = pT->RegisterAppId(); + if (SUCCEEDED(*pnRetCode)) + *pnRetCode = pT->RegisterServer(TRUE); + return false; + } + + lpszToken = FindOneOf(lpszToken, szTokens); + } + + return true; + } + + HRESULT PreMessageLoop(int /*nShowCmd*/) throw() + { + HRESULT hr = S_OK; + T* pT = static_cast(this); + pT; + +#ifndef _ATL_NO_COM_SUPPORT + +#if ((_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM)) & defined(_ATL_FREE_THREADED) + + hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED); + + if (FAILED(hr)) + return hr; + + if (hr == S_OK) + { + if (m_bDelayShutdown) + { + CHandle h(pT->StartMonitor()); + if (h.m_h == NULL) + { + hr = E_FAIL; + } + else + { + hr = CoResumeClassObjects(); + ATLASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + ::SetEvent(m_hEventShutdown); // tell monitor to shutdown + ::WaitForSingleObject(h, m_dwTimeOut * 2); + } + } + } + else + { + hr = CoResumeClassObjects(); + ATLASSERT(SUCCEEDED(hr)); + } + + if (FAILED(hr)) + pT->RevokeClassObjects(); + } + else + { + m_bDelayShutdown = false; + } + +#else + + hr = pT->RegisterClassObjects(CLSCTX_LOCAL_SERVER, + REGCLS_MULTIPLEUSE); + if (hr == S_OK) + { + if (m_bDelayShutdown && !pT->StartMonitor()) + { + hr = E_FAIL; + } + } + else + { + m_bDelayShutdown = false; + } + + +#endif + +#endif // _ATL_NO_COM_SUPPORT + + ATLASSERT(SUCCEEDED(hr)); + return hr; + } + + HRESULT PostMessageLoop() throw() + { + HRESULT hr = S_OK; + +#ifndef _ATL_NO_COM_SUPPORT + + T* pT = static_cast(this); + hr = pT->RevokeClassObjects(); + if (m_bDelayShutdown) + Sleep(m_dwPause); //wait for any threads to finish + +#endif // _ATL_NO_COM_SUPPORT + + return hr; + } + + void RunMessageLoop() throw() + { + MSG msg; + while (GetMessage(&msg, 0, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + HRESULT Run(int nShowCmd = SW_HIDE) throw() + { + HRESULT hr = S_OK; + + T* pT = static_cast(this); + hr = pT->PreMessageLoop(nShowCmd); + + // Call RunMessageLoop only if PreMessageLoop returns S_OK. + if (hr == S_OK) + { + pT->RunMessageLoop(); + } + + // Call PostMessageLoop if PreMessageLoop returns success. + if (SUCCEEDED(hr)) + { + hr = pT->PostMessageLoop(); + } + + ATLASSERT(SUCCEEDED(hr)); + return hr; + } + + // Register/Revoke All Class Factories with the OS (EXE only) + HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() + { + return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); + } + HRESULT RevokeClassObjects() throw() + { + return AtlComModuleRevokeClassObjects(&_AtlComModule); + } +}; + +#ifndef _ATL_NO_SERVICE +template +class ATL_NO_VTABLE CAtlServiceModuleT : public CAtlExeModuleT +{ +public : + + CAtlServiceModuleT() throw() + { + m_bService = TRUE; + LoadString(_AtlBaseModule.GetModuleInstance(), nServiceNameID, m_szServiceName, sizeof(m_szServiceName) / sizeof(TCHAR)); + + // set up the initial service status + m_hServiceStatus = NULL; + m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + m_status.dwCurrentState = SERVICE_STOPPED; + m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + m_status.dwWin32ExitCode = 0; + m_status.dwServiceSpecificExitCode = 0; + m_status.dwCheckPoint = 0; + m_status.dwWaitHint = 0; + } + + int WinMain(int nShowCmd) throw() + { + if (CAtlBaseModule::m_bInitFailed) + { + ATLASSERT(0); + return -1; + } + + T* pT = static_cast(this); + HRESULT hr = S_OK; + + LPTSTR lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT + if (pT->ParseCommandLine(lpCmdLine, &hr) == true) + hr = pT->Start(nShowCmd); + +#ifdef _DEBUG + // Prevent false memory leak reporting. ~CAtlWinModule may be too late. + _AtlWinModule.Term(); +#endif // _DEBUG + return hr; + } + + HRESULT Start(int nShowCmd) throw() + { + T* pT = static_cast(this); + // Are we Service or Local Server + CRegKey keyAppID; + LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ); + if (lRes != ERROR_SUCCESS) + { + m_status.dwWin32ExitCode = lRes; + return m_status.dwWin32ExitCode; + } + + CRegKey key; + lRes = key.Open(keyAppID, pT->GetAppIdT(), KEY_READ); + if (lRes != ERROR_SUCCESS) + { + m_status.dwWin32ExitCode = lRes; + return m_status.dwWin32ExitCode; + } + + TCHAR szValue[MAX_PATH]; + DWORD dwLen = MAX_PATH; + lRes = key.QueryStringValue(_T("LocalService"), szValue, &dwLen); + + m_bService = FALSE; + if (lRes == ERROR_SUCCESS) + m_bService = TRUE; + + if (m_bService) + { + SERVICE_TABLE_ENTRY st[] = + { + { m_szServiceName, _ServiceMain }, + { NULL, NULL } + }; + if (::StartServiceCtrlDispatcher(st) == 0) + m_status.dwWin32ExitCode = GetLastError(); + return m_status.dwWin32ExitCode; + } + // local server - call Run() directly, rather than + // from ServiceMain() + m_status.dwWin32ExitCode = pT->Run(nShowCmd); + return m_status.dwWin32ExitCode; + } + + inline HRESULT RegisterAppId(bool bService = false) throw() + { + if (IsInstalled()) + return E_FAIL; + + HRESULT hr = T::UpdateRegistryAppId(TRUE); + if (FAILED(hr)) + return hr; + + CRegKey keyAppID; + LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + + CRegKey key; + + lRes = key.Create(keyAppID, T::GetAppIdT()); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + + key.DeleteValue(_T("LocalService")); + + if (!bService) + return S_OK; + + key.SetStringValue(_T("LocalService"), m_szServiceName); + + // Create service + if (!Install()) + return E_FAIL; + return S_OK; + } + + HRESULT UnregisterAppId() throw() + { + if (!Uninstall()) + return E_FAIL; + // First remove entries not in the RGS file. + CRegKey keyAppID; + LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + + CRegKey key; + lRes = key.Open(keyAppID, T::GetAppIdT(), KEY_WRITE); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + key.DeleteValue(_T("LocalService")); + + return T::UpdateRegistryAppId(FALSE); + } + + // Parses the command line and registers/unregisters the rgs file if necessary + bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) throw() + { + if (!CAtlExeModuleT::ParseCommandLine(lpCmdLine, pnRetCode)) + return false; + + TCHAR szTokens[] = _T("-/"); + *pnRetCode = S_OK; + + T* pT = static_cast(this); + LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens); + while (lpszToken != NULL) + { + if (WordCmpI(lpszToken, _T("Service"))==0) + { + *pnRetCode = pT->RegisterAppId(true); + if (SUCCEEDED(*pnRetCode)) + *pnRetCode = pT->RegisterServer(TRUE); + return false; + } + lpszToken = FindOneOf(lpszToken, szTokens); + } + return true; + } + + void ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() + { + lpszArgv; + dwArgc; + // Register the control request handler + m_status.dwCurrentState = SERVICE_START_PENDING; + m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler); + if (m_hServiceStatus == NULL) + { + LogEvent(_T("Handler not installed")); + return; + } + SetServiceStatus(SERVICE_START_PENDING); + + m_status.dwWin32ExitCode = S_OK; + m_status.dwCheckPoint = 0; + m_status.dwWaitHint = 0; + + T* pT = static_cast(this); +#ifndef _ATL_NO_COM_SUPPORT + + HRESULT hr = E_FAIL; + hr = T::InitializeCom(); + if (FAILED(hr)) + { + // Ignore RPC_E_CHANGED_MODE if CLR is loaded. Error is due to CLR initializing + // COM and InitializeCOM trying to initialize COM with different flags. + if (hr != RPC_E_CHANGED_MODE || GetModuleHandle(_T("Mscoree.dll")) == NULL) + { + return; + } + } + else + { + m_bComInitialized = true; + } + + m_bDelayShutdown = false; +#endif //_ATL_NO_COM_SUPPORT + // When the Run function returns, the service has stopped. + m_status.dwWin32ExitCode = pT->Run(SW_HIDE); + +#ifndef _ATL_NO_COM_SUPPORT + if (m_bService && m_bComInitialized) + T::UninitializeCom(); +#endif + + SetServiceStatus(SERVICE_STOPPED); + LogEvent(_T("Service stopped")); + } + + HRESULT Run(int nShowCmd = SW_HIDE) throw() + { + HRESULT hr = S_OK; + T* pT = static_cast(this); + + hr = pT->PreMessageLoop(nShowCmd); + + if (hr == S_OK) + { + if (m_bService) + { + LogEvent(_T("Service started")); + SetServiceStatus(SERVICE_RUNNING); + } + + pT->RunMessageLoop(); + } + + if (SUCCEEDED(hr)) + { + hr = pT->PostMessageLoop(); + } + + return hr; + } + + HRESULT PreMessageLoop(int nShowCmd) throw() + { + HRESULT hr = S_OK; + if (m_bService) + { + m_dwThreadID = GetCurrentThreadId(); + + T* pT = static_cast(this); + hr = pT->InitializeSecurity(); + + if (FAILED(hr)) + return hr; + } + + hr = CAtlExeModuleT::PreMessageLoop(nShowCmd); + if (FAILED(hr)) + return hr; + + return hr; + } + + void OnStop() throw() + { + SetServiceStatus(SERVICE_STOP_PENDING); + PostThreadMessage(m_dwThreadID, WM_QUIT, 0, 0); + } + + void OnPause() throw() + { + } + + void OnContinue() throw() + { + } + + void OnInterrogate() throw() + { + } + + void OnShutdown() throw() + { + } + + void OnUnknownRequest(DWORD /*dwOpcode*/) throw() + { + LogEvent(_T("Bad service request")); + } + + void Handler(DWORD dwOpcode) throw() + { + T* pT = static_cast(this); + + switch (dwOpcode) + { + case SERVICE_CONTROL_STOP: + pT->OnStop(); + break; + case SERVICE_CONTROL_PAUSE: + pT->OnPause(); + break; + case SERVICE_CONTROL_CONTINUE: + pT->OnContinue(); + break; + case SERVICE_CONTROL_INTERROGATE: + pT->OnInterrogate(); + break; + case SERVICE_CONTROL_SHUTDOWN: + pT->OnShutdown(); + break; + default: + pT->OnUnknownRequest(dwOpcode); + } + } + + BOOL IsInstalled() throw() + { + BOOL bResult = FALSE; + + SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if (hSCM != NULL) + { + SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_QUERY_CONFIG); + if (hService != NULL) + { + bResult = TRUE; + ::CloseServiceHandle(hService); + } + ::CloseServiceHandle(hSCM); + } + return bResult; + } + BOOL Install() throw() + { + if (IsInstalled()) + return TRUE; + + // Get the executable file path + TCHAR szFilePath[MAX_PATH + _ATL_QUOTES_SPACE]; + DWORD dwFLen = ::GetModuleFileName(NULL, szFilePath + 1, MAX_PATH); + if( dwFLen == 0 || dwFLen == MAX_PATH ) + return FALSE; + + // Quote the FilePath before calling CreateService + szFilePath[0] = _T('\"'); + szFilePath[dwFLen + 1] = _T('\"'); + szFilePath[dwFLen + 2] = 0; + + SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (hSCM == NULL) + { + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + return FALSE; + } + + SC_HANDLE hService = ::CreateService( + hSCM, m_szServiceName, m_szServiceName, + SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, + szFilePath, NULL, NULL, _T("RPCSS\0"), NULL, NULL); + + if (hService == NULL) + { + ::CloseServiceHandle(hSCM); + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_START_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not start service")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not start service")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + return FALSE; + } + + ::CloseServiceHandle(hService); + ::CloseServiceHandle(hSCM); + return TRUE; + } + + BOOL Uninstall() throw() + { + if (!IsInstalled()) + return TRUE; + + SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + + if (hSCM == NULL) + { + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_MANAGER_OPEN_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open Service Manager")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + return FALSE; + } + + SC_HANDLE hService = ::OpenService(hSCM, m_szServiceName, SERVICE_STOP | DELETE); + + if (hService == NULL) + { + ::CloseServiceHandle(hSCM); + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_OPEN_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not open service")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not open service")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + return FALSE; + } + SERVICE_STATUS status; + BOOL bRet = ::ControlService(hService, SERVICE_CONTROL_STOP, &status); + if (!bRet) + { + DWORD dwError = GetLastError(); + if (!((dwError == ERROR_SERVICE_NOT_ACTIVE) || (dwError == ERROR_SERVICE_CANNOT_ACCEPT_CTRL && status.dwCurrentState == SERVICE_STOP_PENDING))) + { + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_STOP_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not stop service")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not stop service")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + } + } + + + BOOL bDelete = ::DeleteService(hService); + ::CloseServiceHandle(hService); + ::CloseServiceHandle(hSCM); + + if (bDelete) + return TRUE; + + TCHAR szBuf[1024]; + if (AtlLoadString(ATL_SERVICE_DELETE_ERROR, szBuf, 1024) == 0) +#ifdef UNICODE + Checked::wcscpy_s(szBuf, _countof(szBuf), _T("Could not delete service")); +#else + Checked::strcpy_s(szBuf, _countof(szBuf), _T("Could not delete service")); +#endif + MessageBox(NULL, szBuf, m_szServiceName, MB_OK); + return FALSE; + } + + LONG Unlock() throw() + { + LONG lRet; + if (m_bService) + { + // We are running as a service, therefore transition to zero does not + // unload the process + lRet = CAtlModuleT::Unlock(); + } + else + { + // We are running as EXE, use MonitorShutdown logic provided by CExeModule + lRet = CAtlExeModuleT::Unlock(); + } + return lRet; + } + + void LogEventEx(int id, LPCTSTR pszMessage=NULL, WORD type = EVENTLOG_INFORMATION_TYPE) throw() + { + HANDLE hEventSource; + if (m_szServiceName) + { + /* Get a handle to use with ReportEvent(). */ + hEventSource = RegisterEventSource(NULL, m_szServiceName); + if (hEventSource != NULL) + { + /* Write to event log. */ + ReportEvent(hEventSource, + type, + (WORD)0, + id, + NULL, + (WORD)(pszMessage != NULL ? 1 : 0), + 0, + pszMessage != NULL ? &pszMessage : NULL, + NULL); + DeregisterEventSource(hEventSource); + } + } + } + +#pragma warning(push) +#pragma warning(disable : 4793) + void __cdecl LogEvent(LPCTSTR pszFormat, ...) throw() + { + const int LOG_EVENT_MSG_SIZE = 256; + + TCHAR chMsg[LOG_EVENT_MSG_SIZE]; + HANDLE hEventSource; + LPTSTR lpszStrings[1]; + va_list pArg; + + va_start(pArg, pszFormat); +#if _SECURE_ATL + _vsntprintf_s(chMsg, LOG_EVENT_MSG_SIZE, LOG_EVENT_MSG_SIZE-1, pszFormat, pArg); +#else + _vsntprintf(chMsg, LOG_EVENT_MSG_SIZE, pszFormat, pArg); +#endif + va_end(pArg); + + chMsg[LOG_EVENT_MSG_SIZE - 1] = 0; + + lpszStrings[0] = chMsg; + + if (!m_bService) + { + // Not running as a service, so print out the error message + // to the console if possible + _putts(chMsg); + } + + /* Get a handle to use with ReportEvent(). */ + hEventSource = RegisterEventSource(NULL, m_szServiceName); + if (hEventSource != NULL) + { + /* Write to event log. */ + ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL); + DeregisterEventSource(hEventSource); + } + } +#pragma warning(pop) + + void SetServiceStatus(DWORD dwState) throw() + { + m_status.dwCurrentState = dwState; + ::SetServiceStatus(m_hServiceStatus, &m_status); + } + +//Implementation +protected: + static void WINAPI _ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv) throw() + { + ((T*)_pAtlModule)->ServiceMain(dwArgc, lpszArgv); + } + static void WINAPI _Handler(DWORD dwOpcode) throw() + { + ((T*)_pAtlModule)->Handler(dwOpcode); + } + +// data members +public: + TCHAR m_szServiceName[256]; + SERVICE_STATUS_HANDLE m_hServiceStatus; + SERVICE_STATUS m_status; + BOOL m_bService; + DWORD m_dwThreadID; +}; + +#endif // _ATL_NO_SERVICE + +#endif // !_AFX + +#ifdef _AFX + +class CAtlMfcModule : public ATL::CAtlModuleT +{ +public : + virtual LONG Lock() throw() + { +#ifdef _USRDLL + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +#endif + AfxOleLockApp(); + return AfxGetModuleState()->m_nObjectCount; + } + + virtual LONG Unlock() throw() + { +#ifdef _USRDLL + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +#endif + AfxOleUnlockApp(); + return AfxGetModuleState()->m_nObjectCount; + } + + virtual LONG GetLockCount() throw() + { +#ifdef _USRDLL + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +#endif + return AfxGetModuleState()->m_nObjectCount; + } + + // Obtain a Class Factory (DLL only) + HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) + { + return ATL::AtlComModuleGetClassObject(&ATL::_AtlComModule, rclsid, riid, ppv); + } + + // Register/Revoke All Class Factories with the OS (EXE only) + HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) + { + return ATL::AtlComModuleRegisterClassObjects(&ATL::_AtlComModule, dwClsContext, dwFlags); + } + + HRESULT RevokeClassObjects() + { + return ATL::AtlComModuleRevokeClassObjects(&ATL::_AtlComModule); + } +}; + +#endif // _AFX + +///////////////////////////////////////////////////////////////////////////// +// CComModule - Uses the functionality provided by other modules + +#define THREADFLAGS_APARTMENT 0x1 +#define THREADFLAGS_BOTH 0x2 +#define AUTPRXFLAG 0x4 + +#ifndef _ATL_NO_COMMODULE + +class CComModule; + +#if !defined(_ATL_NATIVE_INITIALIZATION) + +#if (_MSC_VER >= 1400) +#pragma managed(push, off) +#else +#pragma unmanaged +#endif + +#pragma warning(push) +#pragma warning(disable:4483) +namespace __identifier("") +#pragma warning(pop) +{ + struct CComModuleHelper + { + CComModule* Module; + HINSTANCE Instance; + _ATL_OBJMAP_ENTRY* ObjectMap; + const GUID* LibraryId; + + // Must NOT have any constructors + // We initialize the object in DllMain *before* + // the constructors would run. + + void Initialize(CComModule* pModule, HINSTANCE hInstance, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) + { + Module = pModule; + Instance = hInstance; + ObjectMap = pObjMap; + LibraryId = pLibID; + } + }; + + __declspec(selectany) CComModuleHelper ComModuleHelper; + __declspec(selectany) bool ComModuleInitialized = false; +} + +#if (_MSC_VER >= 1400) +#pragma managed(pop) +#else +#pragma managed +#endif + +#endif + + +__declspec(selectany) CComModule* _pModule = NULL; +class CComModule : public CAtlModuleT +{ +public : + + CComModule() + { + // Should have only one instance of a class + // derived from CComModule in a project. + ATLASSERT(_pModule == NULL); + _pModule = this; +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + ATLASSERT(ComModuleInitialized == false); + // If ComModuleHelper.Module == NULL it mean that DllMain has not been called, so we assume CComModule lives in + // an exe and not in a dll + if (ComModuleHelper.Module != NULL) + { + ATLASSERT(ComModuleHelper.Module == this); + _DllMain(ComModuleHelper.Instance, DLL_PROCESS_ATTACH, NULL, ComModuleHelper.ObjectMap, ComModuleHelper.LibraryId); + } + ComModuleInitialized = true; +#endif + } + + ~CComModule() + { +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + ATLASSERT(ComModuleInitialized == true); + // If ComModuleHelper.Module == NULL it mean that DllMain has not been called, so we assume CComModule lives in + // an exe and not in a dll + if (ComModuleHelper.Module != NULL) + { + ATLASSERT(ComModuleHelper.Module == this); + _DllMain(ComModuleHelper.Instance, DLL_PROCESS_DETACH, NULL, ComModuleHelper.ObjectMap, ComModuleHelper.LibraryId); + } +#endif + } + + __declspec(property(get = get_m_hInst)) HINSTANCE m_hInst; + HINSTANCE& get_m_hInst() const throw() + { + return _AtlBaseModule.m_hInst; + } + + __declspec(property(get = get_m_hInstResource, put = put_m_hInstResource)) HINSTANCE m_hInstResource; + HINSTANCE& get_m_hInstResource() const throw() + { + return _AtlBaseModule.m_hInstResource; + } + void put_m_hInstResource(HINSTANCE h) throw() + { + _AtlBaseModule.SetResourceInstance(h); + } + HINSTANCE SetResourceInstance(HINSTANCE h) throw() + { + return _AtlBaseModule.SetResourceInstance(h); + } + + HINSTANCE GetModuleInstance() throw() + { + return _AtlBaseModule.m_hInst; + } + HINSTANCE GetResourceInstance() throw() + { + return _AtlBaseModule.m_hInstResource; + } + + __declspec(property(get = get_m_hInstTypeLib, put = put_m_hInstTypeLib)) HINSTANCE m_hInstTypeLib; + HINSTANCE& get_m_hInstTypeLib() const throw() + { + return _AtlComModule.m_hInstTypeLib; + } + void put_m_hInstTypeLib(HINSTANCE h) throw() + { + _AtlComModule.m_hInstTypeLib = h; + } + + HINSTANCE GetTypeLibInstance() const throw() + { + return _AtlComModule.m_hInstTypeLib; + } + + // For Backward compatibility + _ATL_OBJMAP_ENTRY* m_pObjMap; + + __declspec(property(get = get_m_csWindowCreate)) CRITICAL_SECTION m_csWindowCreate; + CRITICAL_SECTION& get_m_csWindowCreate() throw(); + + __declspec(property(get = get_m_csObjMap)) CRITICAL_SECTION m_csObjMap; + CRITICAL_SECTION& get_m_csObjMap() throw(); + + __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csTypeInfoHolder; + __declspec(property(get = get_m_csStaticDataInit)) CRITICAL_SECTION m_csStaticDataInit; + CRITICAL_SECTION& get_m_csStaticDataInit() throw(); + void EnterStaticDataCriticalSection() throw() + { + EnterCriticalSection(&m_csStaticDataInit); + } + + void LeaveStaticDataCriticalSection() throw() + { + LeaveCriticalSection(&m_csStaticDataInit); + } + + __declspec(property(get = get_dwAtlBuildVer)) DWORD dwAtlBuildVer; + DWORD& get_dwAtlBuildVer() throw() + { + return _AtlBaseModule.dwAtlBuildVer; + } + + __declspec(property(get = get_m_pCreateWndList, put = put_m_pCreateWndList)) _AtlCreateWndData* m_pCreateWndList; + _AtlCreateWndData*& get_m_pCreateWndList() throw(); + void put_m_pCreateWndList(_AtlCreateWndData* p) throw(); + + __declspec(property(get = get_pguidVer)) const GUID* pguidVer; + const GUID*& get_pguidVer() throw() + { + return _AtlBaseModule.pguidVer; + } + +#ifdef _ATL_DEBUG_INTERFACES + + __declspec(property(get = get_m_nIndexQI, put = put_m_nIndexQI)) UINT m_nIndexQI; + UINT& get_m_nIndexQI() throw(); + void put_m_nIndexQI(UINT nIndex) throw(); + + __declspec(property(get = get_m_nIndexBreakAt, put = put_m_nIndexBreakAt)) UINT m_nIndexBreakAt; + UINT& get_m_nIndexBreakAt() throw(); + void put_m_nIndexBreakAt(UINT nIndex) throw(); + + __declspec(property(get = get_m_paThunks)) CSimpleArray<_QIThunk*>* m_paThunks; + CSimpleArray<_QIThunk*>* get_m_paThunks() throw(); + HRESULT AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw(); + + HRESULT AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw(); + void DeleteNonAddRefThunk(IUnknown* pUnk) throw(); + void DeleteThunk(_QIThunk* p) throw(); + bool DumpLeakedThunks() throw(); +#endif // _ATL_DEBUG_INTERFACES + + HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL) throw(); + void Term() throw(); + + HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw(); + // Register/Revoke All Class Factories with the OS (EXE only) + HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw(); + HRESULT RevokeClassObjects() throw(); + // Registry support (helpers) + HRESULT RegisterTypeLib() throw(); + HRESULT RegisterTypeLib(LPCTSTR lpszIndex) throw(); + HRESULT UnRegisterTypeLib() throw(); + HRESULT UnRegisterTypeLib(LPCTSTR lpszIndex) throw(); + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL) throw(); + HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) throw(); + HRESULT UnregisterServer(const CLSID* pCLSID = NULL) throw(); + + void AddCreateWndData(_AtlCreateWndData* pData, void* pObject) throw() + { + _AtlWinModule.AddCreateWndData(pData, pObject); + } + + void* ExtractCreateWndData() throw() + { + return _AtlWinModule.ExtractCreateWndData(); + } + + // Only used in CComAutoThreadModule + HRESULT CreateInstance(void* /*pfnCreateInstance*/, REFIID /*riid*/, void** /*ppvObj*/) throw() + { + ATLASSERT(0); + ATLTRACENOTIMPL(_T("CComModule::CreateInstance")); + } + + HRESULT RegisterAppId(LPCTSTR pAppId); + HRESULT UnregisterAppId(LPCTSTR pAppId); + + // Resource-based Registration + virtual HRESULT WINAPI UpdateRegistryFromResourceD(LPCTSTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { +#if defined(_ATL_STATIC_REGISTRY) + (lpszRes); + (bRegister); + (pMapEntries); + return E_FAIL; +#else + return CAtlModuleT::UpdateRegistryFromResourceD(lpszRes, bRegister, pMapEntries); +#endif + } + virtual HRESULT WINAPI UpdateRegistryFromResourceD(UINT nResID, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { +#if defined(_ATL_STATIC_REGISTRY) + (nResID); + (bRegister); + (pMapEntries); + return E_FAIL; +#else + return CAtlModuleT::UpdateRegistryFromResourceD(nResID, bRegister, pMapEntries); +#endif + } + + + // Statically linking to Registry Ponent + virtual HRESULT WINAPI UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { +#ifdef _ATL_STATIC_REGISTRY + return CAtlModuleT::UpdateRegistryFromResourceS(lpszRes, bRegister, pMapEntries); +#else + (lpszRes); + (bRegister); + (pMapEntries); + return E_FAIL; +#endif + } + virtual HRESULT WINAPI UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries = NULL) throw() + { +#ifdef _ATL_STATIC_REGISTRY + return CAtlModuleT::UpdateRegistryFromResourceS(nResID, bRegister, pMapEntries); +#else + (nResID); + (bRegister); + (pMapEntries); + return E_FAIL; +#endif + } + + + // Use RGS file for registration + + ATL_DEPRECATED("CComModule::RegisterProgID is no longer recommended. Instead, use an RGS file for registration.") + static HRESULT RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc); + // Standard Registration + ATL_DEPRECATED("CComModule::UpdateRegistryClass is no longer recommended. Instead, use an RGS file for registration.") + HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister); + ATL_DEPRECATED("CComModule::UpdateRegistryClass is no longer recommended. Instead, use an RGS file for registration.") + HRESULT WINAPI UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister); + ATL_DEPRECATED("CComModule::RegisterClassHelper is no longer recommended. Instead, use an RGS file for registration.") + HRESULT WINAPI RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags); + ATL_DEPRECATED("CComModule::UnregisterClassHelper is no longer recommended. Instead, use an RGS file for registration.") + HRESULT WINAPI UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, LPCTSTR lpszVerIndProgID); + + BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID); + + BOOL WINAPI _DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) + { + if (dwReason == DLL_PROCESS_ATTACH) + { + if (CAtlBaseModule::m_bInitFailed) + { + ATLASSERT(0); + return FALSE; + } + + if (FAILED(Init(pObjMap, hInstance, pLibID))) + { + Term(); + return FALSE; + } +#ifdef _ATL_MIN_CRT + DisableThreadLibraryCalls(hInstance); +#endif + } + else if (dwReason == DLL_PROCESS_DETACH) + Term(); + return TRUE; // ok + } + + HRESULT DllCanUnloadNow() throw() + { + return (GetLockCount()==0) ? S_OK : S_FALSE; + } + HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() + { + return GetClassObject(rclsid, riid, ppv); + } + + HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) throw() + { + // registers object, typelib and all interfaces in typelib + return RegisterServer(bRegTypeLib); + } + + HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) throw() + { + return UnregisterServer(bUnRegTypeLib); + } + +}; + + +#if (_MSC_VER >= 1400) +#pragma managed(push, off) +#else +#pragma unmanaged +#endif + +inline BOOL WINAPI CComModule::DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved, _ATL_OBJMAP_ENTRY* pObjMap, const GUID* pLibID) +{ +#if !defined(_ATL_NATIVE_INITIALIZATION) +#pragma warning(push) +#pragma warning(disable:4483) + using namespace __identifier(""); +#pragma warning(pop) + lpReserved; + if (dwReason == DLL_PROCESS_ATTACH) + { + ATLASSERT(ComModuleInitialized == false); + ComModuleHelper.Initialize(this, hInstance, pObjMap, pLibID); + } + return TRUE; +#else + return _DllMain(hInstance, dwReason, lpReserved, pObjMap, pLibID); +#endif +} + + +#if (_MSC_VER >= 1400) +#pragma managed(pop) +#else +#pragma managed +#endif + +#endif // !_ATL_NO_COMMODULE + +///////////////////////////////////////////////////////////////////////////// +// Thread creation helpers + +#if !defined(_ATL_MIN_CRT) && defined(_MT) +// CRTThreadTraits +// This class is for use with CThreadPool or CWorkerThread +// It should be used if the worker class will use CRT +// functions. +class CRTThreadTraits +{ +public: + static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() + { + ATLASSERT(sizeof(DWORD) == sizeof(unsigned int)); // sanity check for pdwThreadId + + // _beginthreadex calls CreateThread which will set the last error value before it returns. + return (HANDLE) _beginthreadex(lpsa, dwStackSize, (unsigned int (__stdcall *)(void *)) pfnThreadProc, pvParam, dwCreationFlags, (unsigned int *) pdwThreadId); + } +}; + +#endif + +// Win32ThreadTraits +// This class is for use with CThreadPool or CWorkerThread +// It should be used if the worker class will not use CRT +// functions. +class Win32ThreadTraits +{ +public: + static HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, LPTHREAD_START_ROUTINE pfnThreadProc, void *pvParam, DWORD dwCreationFlags, DWORD *pdwThreadId) throw() + { + return ::CreateThread(lpsa, dwStackSize, pfnThreadProc, pvParam, dwCreationFlags, pdwThreadId); + } +}; + +#if !defined(_ATL_MIN_CRT) && defined(_MT) + typedef CRTThreadTraits DefaultThreadTraits; +#else + typedef Win32ThreadTraits DefaultThreadTraits; +#endif + +template +HANDLE CreateThreadT(LPSECURITY_ATTRIBUTES lpsa, DWORD dwStackSize, DWORD (WINAPI * pfn)(T *pparam), + T *pparam, DWORD dwCreationFlags, LPDWORD pdw) +{ + return DefaultThreadTraits::CreateThread(lpsa, + dwStackSize, + (LPTHREAD_START_ROUTINE)pfn, + pparam, + dwCreationFlags, + pdw); +} + +template +HANDLE AtlCreateThread(DWORD (WINAPI* pfn)(T *pparam), T *pparam) +{ + return CreateThreadT(0, 0, pfn, pparam, 0, 0); +} + +///////////////////////////////////////////////////////////////////////////////////////////// +// Thread Pooling classes + +class _AtlAptCreateObjData +{ +public: + _ATL_CREATORFUNC* pfnCreateInstance; + const IID* piid; + HANDLE hEvent; + LPSTREAM pStream; + HRESULT hRes; +}; + +class CComApartment +{ +public: + CComApartment() + { + m_nLockCnt = 0; + m_hThread = NULL; + } + static UINT ATL_CREATE_OBJECT; + static DWORD WINAPI _Apartment(__in void* pv) + { + ATLENSURE(pv != NULL); + return ((CComApartment*)pv)->Apartment(); + } + DWORD Apartment() + { + CoInitialize(NULL); + MSG msg; + while(GetMessage(&msg, 0, 0, 0) > 0) + { + if (msg.message == ATL_CREATE_OBJECT) + { + _AtlAptCreateObjData* pdata = (_AtlAptCreateObjData*)msg.lParam; + IUnknown* pUnk = NULL; + pdata->hRes = pdata->pfnCreateInstance(NULL, __uuidof(IUnknown), (void**)&pUnk); + if (SUCCEEDED(pdata->hRes)) + pdata->hRes = CoMarshalInterThreadInterfaceInStream(*pdata->piid, pUnk, &pdata->pStream); + if (SUCCEEDED(pdata->hRes)) + { + pUnk->Release(); + ATLTRACE(atlTraceCOM, 2, _T("Object created on thread = %d\n"), GetCurrentThreadId()); + } +#ifdef _DEBUG + else + { + ATLTRACE(atlTraceCOM, 2, _T("Failed to create Object on thread = %d\n"), GetCurrentThreadId()); + } +#endif + SetEvent(pdata->hEvent); + } + DispatchMessage(&msg); + } + CoUninitialize(); + + return 0; + } + LONG Lock() {return CComGlobalsThreadModel::Increment(&m_nLockCnt);} + LONG Unlock(){return CComGlobalsThreadModel::Decrement(&m_nLockCnt); + } + LONG GetLockCount() {return m_nLockCnt;} + + DWORD m_dwThreadID; + HANDLE m_hThread; + LONG m_nLockCnt; +}; + +__declspec(selectany) UINT CComApartment::ATL_CREATE_OBJECT = 0; + +class CComSimpleThreadAllocator +{ +public: + CComSimpleThreadAllocator() + { + m_nThread = 0; + } + int GetThread(CComApartment* /*pApt*/, int nThreads) + { + if (++m_nThread == nThreads) + m_nThread = 0; + return m_nThread; + } + int m_nThread; +}; + +__interface IAtlAutoThreadModule +{ + virtual HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj); +}; + +__declspec(selectany) IAtlAutoThreadModule* _pAtlAutoThreadModule; + +template +class ATL_NO_VTABLE CAtlAutoThreadModuleT : public IAtlAutoThreadModule +{ +// This class is not for use in a DLL. +// If this class were used in a DLL, there will be a deadlock when the DLL is unloaded. +// because of dwWait's default value of INFINITE +public: + CAtlAutoThreadModuleT(int nThreads = T::GetDefaultThreads()) + { + ATLASSERT(_pAtlAutoThreadModule == NULL); + _pAtlAutoThreadModule = this; + m_pApartments = NULL; + m_nThreads= 0; + + ATLTRY(m_pApartments = new CComApartment[nThreads]); + ATLASSERT(m_pApartments != NULL); + if(m_pApartments == NULL) + { + CAtlBaseModule::m_bInitFailed = true; + ATLENSURE(0); + } + + memset(m_pApartments, 0, sizeof(CComApartment) * nThreads); + + m_nThreads = nThreads; + for (int i = 0; i < nThreads; i++) + { + +#if !defined(_ATL_MIN_CRT) && defined(_MT) + typedef unsigned ( __stdcall *pfnThread )( void * ); + m_pApartments[i].m_hThread = (HANDLE)_beginthreadex(NULL, 0, (pfnThread)CComApartment::_Apartment, &m_pApartments[i], 0, (UINT*)&m_pApartments[i].m_dwThreadID); + if (m_pApartments[i].m_hThread == NULL) + { + HRESULT hr = E_FAIL; + switch (Checked::get_errno()) + { + case EAGAIN: + hr = HRESULT_FROM_WIN32(ERROR_TOO_MANY_TCBS); + break; + case EINVAL: + hr = E_INVALIDARG; + break; + } + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + break; + } + +#else + m_pApartments[i].m_hThread = ::CreateThread(NULL, 0, CComApartment::_Apartment, (void*)&m_pApartments[i], 0, &m_pApartments[i].m_dwThreadID); + // clean up allocated threads + if (m_pApartments[i].m_hThread == NULL) + { + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + break; + } + +#endif + + } + if (!CAtlBaseModule::m_bInitFailed) + CComApartment::ATL_CREATE_OBJECT = RegisterWindowMessage(_T("ATL_CREATE_OBJECT")); + } + + virtual ~CAtlAutoThreadModuleT() + { + if (m_pApartments == NULL) + return; + + DWORD dwCurrentThreadId = GetCurrentThreadId(); + int nCurrentThread = -1; + for (int i=0; i < m_nThreads; i++) + { + if (m_pApartments[i].m_hThread == NULL) + continue; + if (m_pApartments[i].m_dwThreadID == dwCurrentThreadId) + { + nCurrentThread = i; + continue; + } + while (::PostThreadMessage(m_pApartments[i].m_dwThreadID, WM_QUIT, 0, 0) == 0) + { + if (GetLastError() == ERROR_INVALID_THREAD_ID) + { + ATLASSERT(FALSE); + break; + } + ::Sleep(100); + } + ::WaitForSingleObject(m_pApartments[i].m_hThread, dwWait); + CloseHandle(m_pApartments[i].m_hThread); + } + if (nCurrentThread != -1) + CloseHandle(m_pApartments[nCurrentThread].m_hThread); + + delete [] m_pApartments; + m_pApartments = NULL; + } + + HRESULT CreateInstance(void* pfnCreateInstance, REFIID riid, void** ppvObj) + { + ATLASSERT(ppvObj != NULL); + if (ppvObj == NULL) + return E_POINTER; + *ppvObj = NULL; + + _ATL_CREATORFUNC* pFunc = (_ATL_CREATORFUNC*) pfnCreateInstance; + _AtlAptCreateObjData data; + data.pfnCreateInstance = pFunc; + data.piid = &riid; + data.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + data.hRes = S_OK; + int nThread = m_Allocator.GetThread(m_pApartments, m_nThreads); + int nIterations = 0; + while(::PostThreadMessage(m_pApartments[nThread].m_dwThreadID, CComApartment::ATL_CREATE_OBJECT, 0, (LPARAM)&data) == 0 && ++nIterations < 100) + { + Sleep(100); + } + if (nIterations < 100) + { + AtlWaitWithMessageLoop(data.hEvent); + } + else + { + data.hRes = AtlHresultFromLastError(); + } + CloseHandle(data.hEvent); + if (SUCCEEDED(data.hRes)) + data.hRes = CoGetInterfaceAndReleaseStream(data.pStream, riid, ppvObj); + return data.hRes; + } + DWORD dwThreadID; + int m_nThreads; + CComApartment* m_pApartments; + ThreadAllocator m_Allocator; + static int GetDefaultThreads() + { + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwNumberOfProcessors * 4; + } +}; + +class CAtlAutoThreadModule : public CAtlAutoThreadModuleT +{ +public : +}; + +#ifndef _ATL_NO_COMMODULE + +template +class CComAutoThreadModule : + public CComModule, + public CAtlAutoThreadModuleT, ThreadAllocator, dwWait> +{ +public: + CComAutoThreadModule(int nThreads = GetDefaultThreads()) : + CAtlAutoThreadModuleT, ThreadAllocator, dwWait>(nThreads) + { + } + HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL, int nThreads = GetDefaultThreads()) + { + nThreads; + ATLASSERT(nThreads == GetDefaultThreads() && _T("Set number of threads through the constructor")); + return CComModule::Init(p, h, plibid); + } +}; + +#endif // !_ATL_NO_COMMODULE + +// Used in CThreadPool +class Win32WaitTraits +{ +public: + static DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwTimeout) + { + return ::WaitForSingleObject(hHandle, dwTimeout); + } +}; + +typedef Win32WaitTraits DefaultWaitTraits; + +///////////////////////////////////////////////////////////////////////////// +// GIT Pointer + +template +class CComGITPtr +{ +public: + CComGITPtr() throw() + { + m_dwCookie = 0; + } + CComGITPtr(T* p) + { + m_dwCookie = 0; + HRESULT hr = Attach(p); + + if (FAILED(hr)) + AtlThrow(hr); + } + CComGITPtr(const CComGITPtr& git) + { + m_dwCookie = 0; + CComPtr spT; + + HRESULT hr = git.CopyTo(&spT); + if (SUCCEEDED(hr)) + hr = Attach(spT); + + if (FAILED(hr)) + AtlThrow(hr); + } + explicit CComGITPtr(DWORD dwCookie) throw() + { + ATLASSUME(m_dwCookie != NULL); + m_dwCookie = dwCookie; + +#ifdef _DEBUG + CComPtr spT; + HRESULT hr = CopyTo(&spT); + ATLASSERT(SUCCEEDED(hr)); +#endif + } + + ~CComGITPtr() throw() + { + Revoke(); + } + CComGITPtr& operator=(const CComGITPtr& git) + { + if(*this!=git) + { + CComPtr spT; + + HRESULT hr = git.CopyTo(&spT); + if (SUCCEEDED(hr)) + { + hr = Attach(spT); + } + + if (FAILED(hr)) + { + AtlThrow(hr); + } + } + return *this; + } + CComGITPtr& operator=(T* p) + { + HRESULT hr = Attach(p); + if (FAILED(hr)) + AtlThrow(hr); + return *this; + } + CComGITPtr& operator=(DWORD dwCookie) + { + if(*this!=dwCookie) + { + HRESULT hr = Attach(dwCookie); + if (FAILED(hr)) + { + AtlThrow(hr); + } + + m_dwCookie = dwCookie; + +#ifdef _DEBUG + CComPtr spT; + hr = CopyTo(&spT); + ATLASSERT(SUCCEEDED(hr)); +#endif + } + return *this; + } + + // basic comparison operators + bool operator!=(CComGITPtr& git) const + { + return !operator==(git); + } + + bool operator!=(DWORD dwCookie) const + { + return !operator==(dwCookie); + } + + bool operator==(CComGITPtr& git) const + { + return m_dwCookie==git.GetCookie(); + } + + bool operator==(DWORD dwCookie) const + { + return m_dwCookie==dwCookie; + } + + // Get the cookie from the class + operator DWORD() const + { + return m_dwCookie; + } + // Get the cookie from the class + DWORD GetCookie() const + { + return m_dwCookie; + } + // Register the passed interface pointer in the GIT + HRESULT Attach(T* p) throw() + { + CComPtr spGIT; + HRESULT hr = E_FAIL; + hr = AtlGetGITPtr(&spGIT); + ATLASSERT(spGIT != NULL); + ATLASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + return hr; + + if (m_dwCookie != 0) + hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); + if (FAILED(hr)) + return hr; + + return spGIT->RegisterInterfaceInGlobal(p, __uuidof(T), &m_dwCookie); + } + + HRESULT Attach(DWORD dwCookie) throw() + { + ATLASSERT(dwCookie != NULL); + HRESULT hr = Revoke(); + if (FAILED(hr)) + return hr; + m_dwCookie = dwCookie; + return S_OK; + } + + // Detach + DWORD Detach() throw() + { + DWORD dwCookie = m_dwCookie; + m_dwCookie = NULL; + return dwCookie; + } + + // Remove the interface from the GIT + HRESULT Revoke() throw() + { + HRESULT hr = S_OK; + if (m_dwCookie != 0) + { + CComPtr spGIT; + HRESULT hr = E_FAIL; + hr = AtlGetGITPtr(&spGIT); + + ATLASSERT(spGIT != NULL); + ATLASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + return hr; + + hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie); + if (SUCCEEDED(hr)) + m_dwCookie = 0; + } + return hr; + } + // Get's the interface from the GIT and copies it to the passed pointer. The pointer + // must be released by the caller when finished. + HRESULT CopyTo(T** pp) const throw() + { + CComPtr spGIT; + HRESULT hr = E_FAIL; + hr = AtlGetGITPtr(&spGIT); + + ATLASSERT(spGIT != NULL); + ATLASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + return hr; + + ATLASSUME(m_dwCookie!=NULL); + return spGIT->GetInterfaceFromGlobal(m_dwCookie, __uuidof(T), (void**)pp); + } + DWORD m_dwCookie; +}; + +///////////////////////////////////////////////////////////////////////////// +// CRegKey + +typedef LONG (WINAPI _ATL_DELETEKEYEXFUNC)(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD Reserved); +typedef LONG (WINAPI _ATL_DELETEKEYFUNC)(HKEY hKey, LPCTSTR lpSubKey); + +class CRegKey +{ +public: + CRegKey() throw(); + CRegKey( CRegKey& key ) throw(); + explicit CRegKey(HKEY hKey) throw(); + ~CRegKey() throw(); + + CRegKey& operator=( CRegKey& key ) throw(); + +// Attributes +public: + operator HKEY() const throw(); + HKEY m_hKey; + +private: + _ATL_DELETEKEYEXFUNC* pfnDeleteKeyEx; + _ATL_DELETEKEYFUNC* pfnDeleteKey; + +// Operations +public: + ATL_DEPRECATED("CRegKey::SetValue(DWORD, TCHAR *valueName) has been superseded by CRegKey::SetDWORDValue") + LONG SetValue(DWORD dwValue, LPCTSTR lpszValueName); + ATL_DEPRECATED("CRegKey::SetValue(TCHAR *value, TCHAR *valueName) has been superseded by CRegKey::SetStringValue and CRegKey::SetMultiStringValue") + LONG SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL, bool bMulti = false, int nValueLen = -1); + LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw(); + LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw(); + LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw(); + LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw(); + LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw(); + LONG SetStringValue(__in_z_opt LPCTSTR pszValueName, __in_z LPCTSTR pszValue, __in DWORD dwType = REG_SZ) throw(...); + LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw(...); + + ATL_DEPRECATED("CRegKey::QueryValue(DWORD, TCHAR *valueName) has been superseded by CRegKey::QueryDWORDValue") + LONG QueryValue(__out DWORD& dwValue, __in_z_opt LPCTSTR lpszValueName); + ATL_DEPRECATED("CRegKey::QueryValue(TCHAR *value, TCHAR *valueName) has been superseded by CRegKey::QueryStringValue and CRegKey::QueryMultiStringValue") + LONG QueryValue(__out_ecount_part_z_opt(*pdwCount, *pdwCount) LPTSTR szValue, __in_z_opt LPCTSTR lpszValueName, __inout DWORD* pdwCount); + LONG QueryValue(__in_z_opt LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw(); + LONG QueryGUIDValue(__in_z_opt LPCTSTR pszValueName, GUID& guidValue) throw(); + LONG QueryBinaryValue(__in_z_opt LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw(); + LONG QueryDWORDValue(__in_z_opt LPCTSTR pszValueName, DWORD& dwValue) throw(); + LONG QueryQWORDValue(__in_z_opt LPCTSTR pszValueName, ULONGLONG& qwValue) throw(); + LONG QueryStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) LPTSTR pszValue, __inout ULONG* pnChars) throw(); + + LONG QueryMultiStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) __out_z LPTSTR pszValue, __inout ULONG* pnChars) throw(); + + // Get the key's security attributes. + LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw(); + // Set the key's security attributes. + LONG SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw(); + + LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) throw(); + static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, + LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL); + + // Create a new registry key (or open an existing one). + LONG Create(__in HKEY hKeyParent, __in_z LPCTSTR lpszKeyName, + __in_z_opt LPTSTR lpszClass = REG_NONE, __in DWORD dwOptions = REG_OPTION_NON_VOLATILE, + __in REGSAM samDesired = KEY_READ | KEY_WRITE, + __in_opt LPSECURITY_ATTRIBUTES lpSecAttr = NULL, + __in_opt LPDWORD lpdwDisposition = NULL) throw(); + // Open an existing registry key. + LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, + REGSAM samDesired = KEY_READ | KEY_WRITE) throw(); + // Close the registry key. + LONG Close() throw(); + // Flush the key's data to disk. + LONG Flush() throw(); + + // Detach the CRegKey object from its HKEY. Releases ownership. + HKEY Detach() throw(); + // Attach the CRegKey object to an existing HKEY. Takes ownership. + void Attach(HKEY hKey) throw(); + + // Enumerate the subkeys of the key. + LONG EnumKey(__in DWORD iIndex, __out_ecount_part_z(*pnNameLength, *pnNameLength) LPTSTR pszName, __inout LPDWORD pnNameLength, __out_opt FILETIME* pftLastWriteTime = NULL) throw(); + LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync = TRUE) throw(); + + LONG DeleteSubKey(LPCTSTR lpszSubKey) throw(); + LONG RecurseDeleteKey(LPCTSTR lpszKey) throw(); + LONG DeleteValue(LPCTSTR lpszValue) throw(); +}; + +inline CRegKey::CRegKey() throw() : + m_hKey( NULL ), + pfnDeleteKeyEx( NULL ), + pfnDeleteKey( NULL ) +{ +} + +inline CRegKey::CRegKey( CRegKey& key ) throw() : + m_hKey( NULL ), + pfnDeleteKeyEx( NULL ), + pfnDeleteKey( NULL ) +{ + Attach( key.Detach() ); +} + +inline CRegKey::CRegKey(HKEY hKey) throw() : + m_hKey(hKey), + pfnDeleteKeyEx( NULL ), + pfnDeleteKey( NULL ) +{ +} + +inline CRegKey::~CRegKey() throw() +{Close();} + +inline CRegKey& CRegKey::operator=( CRegKey& key ) throw() +{ + if(m_hKey!=key.m_hKey) + { + Close(); + Attach( key.Detach() ); + } + return( *this ); +} + +inline CRegKey::operator HKEY() const throw() +{return m_hKey;} + +inline HKEY CRegKey::Detach() throw() +{ + HKEY hKey = m_hKey; + m_hKey = NULL; + return hKey; +} + +inline void CRegKey::Attach(HKEY hKey) throw() +{ + ATLASSUME(m_hKey == NULL); + m_hKey = hKey; +} + +#pragma warning(push) +#pragma warning(disable : 4191) // 'type cast' : unsafe conversion from 'FARPROC' to 'ATL::_ATL_DELETEKEYEXFUNC' + +inline LONG CRegKey::DeleteSubKey(LPCTSTR lpszSubKey) throw() +{ + ATLASSUME(m_hKey != NULL); + + HINSTANCE hInstDLL = NULL; + + if (pfnDeleteKeyEx == NULL && pfnDeleteKey == NULL) + { + // No DLL loaded yet -- get the appropriate one for the current OS. + // Use GetModuleHandle rather than LoadLibrary for apiset dll + // for two reasons: + // + // 1. On Win7+, it will already be loaded into the process + // + // 2. It ensures that there is no opportunity to get a rogue + // "apiset dll" loaded on a down-level machine + + hInstDLL = ::GetModuleHandle(_T("API-MS-Win-Core-LocalRegistry-L1-1-0.dll")); + if (hInstDLL != NULL) + { +#ifdef UNICODE + pfnDeleteKeyEx = (_ATL_DELETEKEYEXFUNC*)GetProcAddress(hInstDLL, "RegDeleteKeyExW"); +#else + pfnDeleteKeyEx = (_ATL_DELETEKEYEXFUNC*)GetProcAddress(hInstDLL, "RegDeleteKeyExA"); +#endif + } + else + { + // No apiset dll, so load advapi32.dll instead. + // Note that this DLL is never unloaded for two reasons: + // + // 1. It is likely that the CRegKey destructor is called + // during DLL_PROCESS_ATTACH in multiple applications. + // + // 2. Whichever DLL is found (apiset dll or advapi32.dll) + // is almost guaranteed to be in use by other DLLs in the + // process, so the unload would have little (or no) effect. + + hInstDLL = ::LoadLibrary(_T("advapi32.dll")); + if (hInstDLL != NULL) + { +#ifdef UNICODE + pfnDeleteKey = (_ATL_DELETEKEYFUNC*)GetProcAddress(hInstDLL, "RegDeleteKeyW"); +#else + pfnDeleteKey = (_ATL_DELETEKEYFUNC*)GetProcAddress(hInstDLL, "RegDeleteKeyA"); +#endif + } + } + } + + if (pfnDeleteKeyEx != NULL) + { + return pfnDeleteKeyEx(m_hKey, lpszSubKey, 0, 0); + } + else if (pfnDeleteKey != NULL) + { + return pfnDeleteKey(m_hKey, lpszSubKey); + } + + // DLL loads failed + return GetLastError(); +} + +#pragma warning(pop) + +inline LONG CRegKey::DeleteValue(LPCTSTR lpszValue) throw() +{ + ATLASSUME(m_hKey != NULL); + return RegDeleteValue(m_hKey, (LPTSTR)lpszValue); +} + +inline LONG CRegKey::Close() throw() +{ + LONG lRes = ERROR_SUCCESS; + if (m_hKey != NULL) + { + lRes = RegCloseKey(m_hKey); + m_hKey = NULL; + } + return lRes; +} + +inline LONG CRegKey::Flush() throw() +{ + ATLASSUME(m_hKey != NULL); + + return ::RegFlushKey(m_hKey); +} + +inline LONG CRegKey::EnumKey(__in DWORD iIndex, __out_ecount_part_z(*pnNameLength, *pnNameLength) LPTSTR pszName, __inout LPDWORD pnNameLength, __out_opt FILETIME* pftLastWriteTime) throw() +{ + FILETIME ftLastWriteTime; + + ATLASSUME(m_hKey != NULL); + if (pftLastWriteTime == NULL) + { + pftLastWriteTime = &ftLastWriteTime; + } + + return ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL, NULL, NULL, pftLastWriteTime); +} + +inline LONG CRegKey::NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent, BOOL bAsync) throw() +{ + ATLASSUME(m_hKey != NULL); + ATLASSERT((hEvent != NULL) || !bAsync); + + return ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree, dwNotifyFilter, hEvent, bAsync); +} + +inline LONG CRegKey::Create(__in HKEY hKeyParent, __in_z LPCTSTR lpszKeyName, + __in_z_opt LPTSTR lpszClass, __in DWORD dwOptions, __in REGSAM samDesired, + __in_opt LPSECURITY_ATTRIBUTES lpSecAttr, __in_opt LPDWORD lpdwDisposition) throw() +{ + ATLASSERT(hKeyParent != NULL); + DWORD dw; + HKEY hKey = NULL; + LONG lRes = RegCreateKeyEx(hKeyParent, lpszKeyName, 0, + lpszClass, dwOptions, samDesired, lpSecAttr, &hKey, &dw); + if (lpdwDisposition != NULL) + *lpdwDisposition = dw; + if (lRes == ERROR_SUCCESS) + { + lRes = Close(); + m_hKey = hKey; + } + return lRes; +} + +inline LONG CRegKey::Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired) throw() +{ + ATLASSERT(hKeyParent != NULL); + HKEY hKey = NULL; + LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); + if (lRes == ERROR_SUCCESS) + { + lRes = Close(); + ATLASSERT(lRes == ERROR_SUCCESS); + m_hKey = hKey; + } + return lRes; +} + +#pragma warning(push) +#pragma warning(disable: 4996) +inline LONG CRegKey::QueryValue(DWORD& dwValue, LPCTSTR lpszValueName) +{ + DWORD dwType = NULL; + DWORD dwCount = sizeof(DWORD); + LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, + (LPBYTE)&dwValue, &dwCount); + ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_DWORD)); + ATLASSERT((lRes!=ERROR_SUCCESS) || (dwCount == sizeof(DWORD))); + if (dwType != REG_DWORD) + return ERROR_INVALID_DATA; + return lRes; +} + +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable: 6053) +#endif //!_PREFIX_ + +inline LONG CRegKey::QueryValue(__out_ecount_part_z_opt(*pdwCount, *pdwCount) LPTSTR pszValue, __in_z_opt LPCTSTR lpszValueName, __inout DWORD* pdwCount) +{ + ATLENSURE(pdwCount != NULL); + DWORD dwType = NULL; + LONG lRes = RegQueryValueEx(m_hKey, lpszValueName, NULL, &dwType, (LPBYTE)pszValue, pdwCount); + ATLASSERT((lRes!=ERROR_SUCCESS) || (dwType == REG_SZ) || + (dwType == REG_MULTI_SZ) || (dwType == REG_EXPAND_SZ)); + if (pszValue != NULL) + { + if(*pdwCount>0) + { + switch(dwType) + { + case REG_SZ: + case REG_EXPAND_SZ: + if ((*pdwCount) % sizeof(TCHAR) != 0 || pszValue[(*pdwCount) / sizeof(TCHAR) - 1] != 0) + { + pszValue[0]=_T('\0'); + return ERROR_INVALID_DATA; + } + break; + case REG_MULTI_SZ: + if ((*pdwCount) % sizeof(TCHAR) != 0 || (*pdwCount) / sizeof(TCHAR) < 1 || pszValue[(*pdwCount) / sizeof(TCHAR) -1] != 0 || (((*pdwCount) / sizeof(TCHAR))>1 && pszValue[(*pdwCount) / sizeof(TCHAR) - 2] != 0) ) + { + pszValue[0]=_T('\0'); + return ERROR_INVALID_DATA; + } + break; + default: + // Ensure termination + pszValue[0]=_T('\0'); + return ERROR_INVALID_DATA; + } + } + else + { + // this is a blank one with no data yet + // Ensure termination + pszValue[0]=_T('\0'); + } + } + return lRes; +} +#pragma warning(pop) + +inline LONG CRegKey::QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw() +{ + ATLASSUME(m_hKey != NULL); + + return( ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, static_cast< LPBYTE >( pData ), pnBytes) ); +} + +inline LONG CRegKey::QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() +{ + LONG lRes; + ULONG nBytes; + DWORD dwType; + + ATLASSUME(m_hKey != NULL); + + nBytes = sizeof(DWORD); + lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&dwValue), + &nBytes); + if (lRes != ERROR_SUCCESS) + return lRes; + if (dwType != REG_DWORD) + return ERROR_INVALID_DATA; + + return ERROR_SUCCESS; +} +inline LONG CRegKey::QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() +{ + LONG lRes; + ULONG nBytes; + DWORD dwType; + + ATLASSUME(m_hKey != NULL); + + nBytes = sizeof(ULONGLONG); + lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(&qwValue), + &nBytes); + if (lRes != ERROR_SUCCESS) + return lRes; + if (dwType != REG_QWORD) + return ERROR_INVALID_DATA; + + return ERROR_SUCCESS; +} + +inline LONG CRegKey::QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw() +{ + LONG lRes; + DWORD dwType; + + ATLASSERT(pnBytes != NULL); + ATLASSUME(m_hKey != NULL); + + lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pValue), + pnBytes); + if (lRes != ERROR_SUCCESS) + return lRes; + if (dwType != REG_BINARY) + return ERROR_INVALID_DATA; + + return ERROR_SUCCESS; +} + +#pragma warning(push) + +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable: 6053) +#endif //!_PREFIX_ + +/* prefast noise VSW 496818 */ +inline LONG CRegKey::QueryStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) __out_z LPTSTR pszValue, __inout ULONG* pnChars) throw() +{ + LONG lRes; + DWORD dwType; + ULONG nBytes; + + ATLASSUME(m_hKey != NULL); + ATLASSERT(pnChars != NULL); + + nBytes = (*pnChars)*sizeof(TCHAR); + *pnChars = 0; + lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), + &nBytes); + + if (lRes != ERROR_SUCCESS) + { + return lRes; + } + + if(dwType != REG_SZ && dwType != REG_EXPAND_SZ) + { + return ERROR_INVALID_DATA; + } + + if (pszValue != NULL) + { + if(nBytes!=0) + { + if ((nBytes % sizeof(TCHAR) != 0) || (pszValue[nBytes / sizeof(TCHAR) -1] != 0)) + { + return ERROR_INVALID_DATA; + } + } + else + { + pszValue[0]=_T('\0'); + } + } + + *pnChars = nBytes/sizeof(TCHAR); + + return ERROR_SUCCESS; +} +#pragma warning(pop) + +#pragma warning(push) + +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable: 6053) +#endif // !_PREFIX_ + +/* prefast noise VSW 496818 */ +inline LONG CRegKey::QueryMultiStringValue(__in_z_opt LPCTSTR pszValueName, __out_ecount_part_z_opt(*pnChars, *pnChars) __out_z LPTSTR pszValue, __inout ULONG* pnChars) throw() +{ + LONG lRes; + DWORD dwType; + ULONG nBytes; + + ATLASSUME(m_hKey != NULL); + ATLASSERT(pnChars != NULL); + + if (pszValue != NULL && *pnChars < 2) + return ERROR_INSUFFICIENT_BUFFER; + + nBytes = (*pnChars)*sizeof(TCHAR); + *pnChars = 0; + + lRes = ::RegQueryValueEx(m_hKey, pszValueName, NULL, &dwType, reinterpret_cast(pszValue), + &nBytes); + if (lRes != ERROR_SUCCESS) + return lRes; + if (dwType != REG_MULTI_SZ) + return ERROR_INVALID_DATA; + if (pszValue != NULL && (nBytes % sizeof(TCHAR) != 0 || nBytes / sizeof(TCHAR) < 1 || pszValue[nBytes / sizeof(TCHAR) -1] != 0 || ((nBytes/sizeof(TCHAR))>1 && pszValue[nBytes / sizeof(TCHAR) - 2] != 0))) + return ERROR_INVALID_DATA; + + *pnChars = nBytes/sizeof(TCHAR); + + return ERROR_SUCCESS; +} +#pragma warning(pop) + +inline LONG CRegKey::QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() +{ + TCHAR szGUID[64]; + LONG lRes; + ULONG nCount; + HRESULT hr; + + ATLASSUME(m_hKey != NULL); + + guidValue = GUID_NULL; + + nCount = 64; + lRes = QueryStringValue(pszValueName, szGUID, &nCount); + + if (lRes != ERROR_SUCCESS) + return lRes; + + if(szGUID[0] != _T('{')) + return ERROR_INVALID_DATA; + + USES_CONVERSION_EX; + LPOLESTR lpstr = T2OLE_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpstr == NULL) + return E_OUTOFMEMORY; +#endif + + hr = ::CLSIDFromString(lpstr, &guidValue); + if (FAILED(hr)) + return ERROR_INVALID_DATA; + + return ERROR_SUCCESS; +} + +inline LONG WINAPI CRegKey::SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) +{ + ATLASSERT(lpszValue != NULL); + CRegKey key; + LONG lRes = key.Create(hKeyParent, lpszKeyName); + if (lRes == ERROR_SUCCESS) + lRes = key.SetStringValue(lpszValueName, lpszValue); + return lRes; +} + +inline LONG CRegKey::SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, LPCTSTR lpszValueName) throw() +{ + ATLASSERT(lpszValue != NULL); + CRegKey key; + LONG lRes = key.Create(m_hKey, lpszKeyName); + if (lRes == ERROR_SUCCESS) + lRes = key.SetStringValue(lpszValueName, lpszValue); + return lRes; +} + +#pragma warning(push) +#pragma warning(disable: 4996) +inline LONG CRegKey::SetValue(DWORD dwValue, LPCTSTR pszValueName) +{ + ATLASSUME(m_hKey != NULL); + return SetDWORDValue(pszValueName, dwValue); +} + +inline LONG CRegKey::SetValue(LPCTSTR lpszValue, LPCTSTR lpszValueName, bool bMulti, int nValueLen) +{ + ATLENSURE(lpszValue != NULL); + ATLASSUME(m_hKey != NULL); + + if (bMulti && nValueLen == -1) + return ERROR_INVALID_PARAMETER; + + if (nValueLen == -1) + nValueLen = lstrlen(lpszValue) + 1; + + DWORD dwType = bMulti ? REG_MULTI_SZ : REG_SZ; + + return ::RegSetValueEx(m_hKey, lpszValueName, NULL, dwType, + reinterpret_cast(lpszValue), nValueLen*sizeof(TCHAR)); +} +#pragma warning(pop) + +inline LONG CRegKey::SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw() +{ + ATLASSUME(m_hKey != NULL); + return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, static_cast(pValue), nBytes); +} + +inline LONG CRegKey::SetBinaryValue(LPCTSTR pszValueName, const void* pData, ULONG nBytes) throw() +{ + ATLASSUME(m_hKey != NULL); + return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_BINARY, reinterpret_cast(pData), nBytes); +} + +inline LONG CRegKey::SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() +{ + ATLASSUME(m_hKey != NULL); + return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_DWORD, reinterpret_cast(&dwValue), sizeof(DWORD)); +} + +inline LONG CRegKey::SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() +{ + ATLASSUME(m_hKey != NULL); + return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_QWORD, reinterpret_cast(&qwValue), sizeof(ULONGLONG)); +} + +inline LONG CRegKey::SetStringValue(__in_z_opt LPCTSTR pszValueName, __in_z LPCTSTR pszValue, __in DWORD dwType) throw(...) +{ + ATLASSUME(m_hKey != NULL); + ATLENSURE(pszValue != NULL); + ATLASSERT((dwType == REG_SZ) || (dwType == REG_EXPAND_SZ)); + + return ::RegSetValueEx(m_hKey, pszValueName, NULL, dwType, reinterpret_cast(pszValue), (lstrlen(pszValue)+1)*sizeof(TCHAR)); +} + +inline LONG CRegKey::SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw(...) +{ + LPCTSTR pszTemp; + ULONG nBytes; + ULONG nLength; + + ATLASSUME(m_hKey != NULL); + ATLENSURE(pszValue != NULL); + + // Find the total length (in bytes) of all of the strings, including the + // terminating '\0' of each string, and the second '\0' that terminates + // the list. + nBytes = 0; + pszTemp = pszValue; + do + { + nLength = lstrlen(pszTemp)+1; + pszTemp += nLength; + nBytes += nLength*sizeof(TCHAR); + } while (nLength != 1); + + return ::RegSetValueEx(m_hKey, pszValueName, NULL, REG_MULTI_SZ, reinterpret_cast(pszValue), + nBytes); +} + +inline LONG CRegKey::SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw() +{ + OLECHAR szGUID[64]; + + ATLASSUME(m_hKey != NULL); + + ::StringFromGUID2(guidValue, szGUID, 64); + + USES_CONVERSION_EX; + LPCTSTR lpstr = OLE2CT_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpstr == NULL) + return E_OUTOFMEMORY; +#endif + return SetStringValue(pszValueName, lpstr); +} + +inline LONG CRegKey::GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, LPDWORD pnBytes) throw() +{ + ATLASSUME(m_hKey != NULL); + ATLASSERT(pnBytes != NULL); + + return ::RegGetKeySecurity(m_hKey, si, psd, pnBytes); +} + +inline LONG CRegKey::SetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd) throw() +{ + ATLASSUME(m_hKey != NULL); + ATLASSERT(psd != NULL); + + return ::RegSetKeySecurity(m_hKey, si, psd); +} + +inline LONG CRegKey::RecurseDeleteKey(LPCTSTR lpszKey) throw() +{ + CRegKey key; + LONG lRes = key.Open(m_hKey, lpszKey, KEY_READ | KEY_WRITE); + if (lRes != ERROR_SUCCESS) + { + if (lRes != ERROR_FILE_NOT_FOUND && lRes != ERROR_PATH_NOT_FOUND) + { + ATLTRACE(atlTraceCOM, 0, _T("CRegKey::RecurseDeleteKey : Failed to Open Key %s(Error = %d)\n"), lpszKey, lRes); + } + return lRes; + } + FILETIME time; + DWORD dwSize = 256; + TCHAR szBuffer[256]; + while (RegEnumKeyEx(key.m_hKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, + &time)==ERROR_SUCCESS) + { + lRes = key.RecurseDeleteKey(szBuffer); + if (lRes != ERROR_SUCCESS) + return lRes; + dwSize = 256; + } + key.Close(); + return DeleteSubKey(lpszKey); +} + +#ifndef _ATL_NO_COMMODULE + +inline HRESULT CComModule::RegisterProgID(LPCTSTR lpszCLSID, LPCTSTR lpszProgID, LPCTSTR lpszUserDesc) +{ + CRegKey keyProgID; + LONG lRes = keyProgID.Create(HKEY_CLASSES_ROOT, lpszProgID, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE); + if (lRes == ERROR_SUCCESS) + { + lRes = keyProgID.SetStringValue(NULL, lpszUserDesc); + if (lRes == ERROR_SUCCESS) + { + lRes = keyProgID.SetKeyValue(_T("CLSID"), lpszCLSID); + if (lRes == ERROR_SUCCESS) + return S_OK; + } + } + return AtlHresultFromWin32(lRes); +} + +inline HRESULT CComModule::RegisterAppId(LPCTSTR pAppId) +{ + CRegKey keyAppID; + HRESULT hr = S_OK; + LONG lRet; + + if ( (lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE)) == ERROR_SUCCESS) + { + TCHAR szModule1[MAX_PATH]; + TCHAR szModule2[MAX_PATH]; + TCHAR* pszFileName; + + DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); + if ( dwFLen != 0 && dwFLen != MAX_PATH ) + { + if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) + { + CRegKey keyAppIDEXE; + if ( (lRet = keyAppIDEXE.Create(keyAppID, pszFileName, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) + { + lRet = keyAppIDEXE.SetStringValue(_T("AppID"), pAppId); + if (lRet != ERROR_SUCCESS) + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set app id string value\n")); + hr = AtlHresultFromWin32(lRet); + return hr; + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create file name key\n")); + hr = AtlHresultFromWin32(lRet); + return hr; + } + if ( (lRet = keyAppIDEXE.Create(keyAppID, pAppId, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE)) == ERROR_SUCCESS) + { + lRet = keyAppIDEXE.SetStringValue(NULL, pszFileName); + if (lRet != ERROR_SUCCESS) + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to set file name string value\n")); + hr = AtlHresultFromWin32(lRet); + return hr; + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to create app id key\n")); + hr = AtlHresultFromWin32(lRet); + return hr; + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get full path name for file %s\n"), szModule1); + hr = AtlHresultFromLastError(); + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to get module name\n")); + if( dwFLen == 0 ) + hr = AtlHresultFromLastError(); + else if( dwFLen == MAX_PATH ) + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::RegisterAppId : Failed to open registry key\n")); + hr = AtlHresultFromWin32(lRet); + } + return hr; +} + +inline HRESULT CComModule::UnregisterAppId(LPCTSTR pAppId) +{ + CRegKey keyAppID; + HRESULT hr = S_OK; + LONG lRet = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_READ | KEY_WRITE); + + if (lRet == ERROR_SUCCESS) + { + TCHAR szModule1[MAX_PATH]; + TCHAR szModule2[MAX_PATH]; + TCHAR* pszFileName; + + DWORD dwFLen = ::GetModuleFileName(GetModuleInstance(), szModule1, MAX_PATH); + if ( dwFLen != 0 && dwFLen != MAX_PATH ) + { + if (::GetFullPathName(szModule1, MAX_PATH, szModule2, &pszFileName) != 0) + { + if ((lRet = keyAppID.RecurseDeleteKey(pAppId)) != ERROR_SUCCESS) + { + if (lRet != ERROR_FILE_NOT_FOUND) + hr = AtlHresultFromWin32(lRet); + } + if ((lRet = keyAppID.RecurseDeleteKey(pszFileName)) != ERROR_SUCCESS) + { + if (lRet != ERROR_FILE_NOT_FOUND) + hr = AtlHresultFromWin32(lRet); + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get full path name for file %s\n"), szModule1); + hr = AtlHresultFromLastError(); + } + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to get module name\n")); + if( dwFLen == 0 ) + hr = AtlHresultFromLastError(); + else if( dwFLen == MAX_PATH ) + hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + } + else + { + if (lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) + { + ATLTRACE(atlTraceCOM, 0, _T("CComModule::UnregisterAppId : Failed to open registry key\n")); + hr = AtlHresultFromWin32(lRet); + } + } + return hr; +} +#endif // !_ATL_NO_COMMODULE + +#ifdef _ATL_STATIC_REGISTRY +} // namespace ATL + + +#include + + + +namespace ATL +{ + +// Statically linking to Registry Ponent +inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(LPCTSTR lpszRes, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() +{ + CRegObject ro; + HRESULT hr = ro.FinalConstruct(); + if (FAILED(hr)) + { + return hr; + } + + if (pMapEntries != NULL) + { + while (pMapEntries->szKey != NULL) + { + ATLASSERT(NULL != pMapEntries->szData); + ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); + pMapEntries++; + } + } + + hr = AddCommonRGSReplacements(&ro); + if (FAILED(hr)) + return hr; + + USES_CONVERSION_EX; + TCHAR szModule[MAX_PATH]; + HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); + DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); + if( dwFLen == 0 ) + return AtlHresultFromLastError(); + else if( dwFLen == MAX_PATH ) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + + LPOLESTR pszModule = NULL; + pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(pszModule == NULL) + return E_OUTOFMEMORY; +#endif + + OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; + EscapeSingleQuote(pszModuleUnquoted, _countof(pszModuleUnquoted), pszModule); + + HRESULT hRes; + if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE + { + // If Registering as an EXE, then we quote the resultant path. + // We don't do it for a DLL, because LoadLibrary fails if the path is + // quoted + OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; + pszModuleQuote[0] = OLESTR('\"'); + if(!ocscpy_s(pszModuleQuote + 1, (_MAX_PATH + _ATL_QUOTES_SPACE)*2 - 1, pszModuleUnquoted)) + { + return E_FAIL; + } + size_t nLen = ocslen(pszModuleQuote); + pszModuleQuote[nLen] = OLESTR('\"'); + pszModuleQuote[nLen + 1] = 0; + + hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); + } + else + { + hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); + } + + if(FAILED(hRes)) + return hRes; + + hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); + if(FAILED(hRes)) + return hRes; + + LPCOLESTR szType = OLESTR("REGISTRY"); + LPCOLESTR pszRes = T2COLE_EX(lpszRes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(pszRes == NULL) + return E_OUTOFMEMORY; +#endif + hr = (bRegister) ? ro.ResourceRegisterSz(pszModule, pszRes, szType) : + ro.ResourceUnregisterSz(pszModule, pszRes, szType); + return hr; +} +inline HRESULT WINAPI CAtlModule::UpdateRegistryFromResourceS(UINT nResID, BOOL bRegister, + struct _ATL_REGMAP_ENTRY* pMapEntries /*= NULL*/) throw() +{ + CRegObject ro; + HRESULT hr = ro.FinalConstruct(); + if (FAILED(hr)) + { + return hr; + } + + if (pMapEntries != NULL) + { + while (pMapEntries->szKey != NULL) + { + ATLASSERT(NULL != pMapEntries->szData); + ro.AddReplacement(pMapEntries->szKey, pMapEntries->szData); + pMapEntries++; + } + } + + hr = AddCommonRGSReplacements(&ro); + if (FAILED(hr)) + return hr; + + USES_CONVERSION_EX; + TCHAR szModule[MAX_PATH]; + HINSTANCE hInst = _AtlBaseModule.GetModuleInstance(); + DWORD dwFLen = GetModuleFileName(hInst, szModule, MAX_PATH); + if( dwFLen == 0 ) + return AtlHresultFromLastError(); + else if( dwFLen == MAX_PATH ) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + LPOLESTR pszModule = NULL; + pszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(pszModule == NULL) + return E_OUTOFMEMORY; +#endif + + OLECHAR pszModuleUnquoted[_MAX_PATH * 2]; + EscapeSingleQuote(pszModuleUnquoted, _countof(pszModuleUnquoted), pszModule); + + HRESULT hRes; + if ((hInst == NULL) || (hInst == GetModuleHandle(NULL))) // register as EXE + { + // If Registering as an EXE, then we quote the resultant path. + // We don't do it for a DLL, because LoadLibrary fails if the path is + // quoted + OLECHAR pszModuleQuote[(_MAX_PATH + _ATL_QUOTES_SPACE)*2]; + pszModuleQuote[0] = OLESTR('\"'); + if(!ocscpy_s(pszModuleQuote + 1, (_MAX_PATH + _ATL_QUOTES_SPACE)*2 - 1, pszModuleUnquoted)) + { + return E_FAIL; + } + size_t nLen = ocslen(pszModuleQuote); + pszModuleQuote[nLen] = OLESTR('\"'); + pszModuleQuote[nLen + 1] = 0; + + hRes = ro.AddReplacement(OLESTR("Module"), pszModuleQuote); + } + else + { + hRes = ro.AddReplacement(OLESTR("Module"), pszModuleUnquoted); + } + + if(FAILED(hRes)) + return hRes; + + hRes = ro.AddReplacement(OLESTR("Module_Raw"), pszModuleUnquoted); + if(FAILED(hRes)) + return hRes; + + LPCOLESTR szType = OLESTR("REGISTRY"); + hr = (bRegister) ? ro.ResourceRegister(pszModule, nResID, szType) : + ro.ResourceUnregister(pszModule, nResID, szType); + return hr; +} +#endif //_ATL_STATIC_REGISTRY + +#ifndef _ATL_NO_COMMODULE + +#pragma warning( push ) +#pragma warning( disable: 4996 ) // Disable "deprecated symbol" warning + +inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, + LPCTSTR lpszVerIndProgID, UINT nDescID, DWORD dwFlags, BOOL bRegister) +{ + if (bRegister) + { + TCHAR szDesc[256]; + LoadString(m_hInst, nDescID, szDesc, 256); + return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); + } + return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); +} + +inline HRESULT WINAPI CComModule::UpdateRegistryClass(const CLSID& clsid, LPCTSTR lpszProgID, + LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags, BOOL bRegister) +{ + if (bRegister) + return RegisterClassHelper(clsid, lpszProgID, lpszVerIndProgID, szDesc, dwFlags); + return UnregisterClassHelper(clsid, lpszProgID, lpszVerIndProgID); +} + +inline HRESULT WINAPI CComModule::RegisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, + LPCTSTR lpszVerIndProgID, LPCTSTR szDesc, DWORD dwFlags) +{ + static const TCHAR szProgID[] = _T("ProgID"); + static const TCHAR szVIProgID[] = _T("VersionIndependentProgID"); + static const TCHAR szLS32[] = _T("LocalServer32"); + static const TCHAR szIPS32[] = _T("InprocServer32"); + static const TCHAR szThreadingModel[] = _T("ThreadingModel"); + static const TCHAR szAUTPRX32[] = _T("AUTPRX32.DLL"); + static const TCHAR szApartment[] = _T("Apartment"); + static const TCHAR szBoth[] = _T("both"); + USES_CONVERSION_EX; + TCHAR szModule[_MAX_PATH + _ATL_QUOTES_SPACE]; + + ATLENSURE(lpszProgID && lpszVerIndProgID || !lpszProgID && !lpszVerIndProgID); + + if (!szDesc) + { + szDesc = _T(""); + } + + // If the ModuleFileName's length is equal or greater than the 3rd parameter + // (length of the buffer passed),GetModuleFileName fills the buffer (truncates + // if neccessary), but doesn't null terminate it. It returns the same value as + // the 3rd parameter passed. So if the return value is the same as the 3rd param + // then you have a non null terminated buffer (which may or may not be truncated) + // We pass (szModule + 1) because in case it's an EXE we need to quote the PATH + // The quote is done later in this method before the SetKeyValue is called + DWORD dwLen = GetModuleFileName(m_hInst, szModule + 1, MAX_PATH); + if (dwLen == 0) + { + return AtlHresultFromLastError(); + } + else if( dwLen == MAX_PATH ) + { + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + } + + LPOLESTR lpOleStr; + HRESULT hRes = StringFromCLSID(clsid, &lpOleStr); + if (FAILED(hRes)) + return hRes; + + LPTSTR lpszCLSID = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpszCLSID == NULL) + { + CoTaskMemFree(lpOleStr); + return E_OUTOFMEMORY; + } +#endif + + hRes = lpszProgID ? RegisterProgID(lpszCLSID, lpszProgID, szDesc) : S_OK; + if (hRes == S_OK) + hRes = lpszVerIndProgID ? RegisterProgID(lpszCLSID, lpszVerIndProgID, szDesc) : S_OK; + LONG lRes = ERROR_SUCCESS; + if (hRes == S_OK) + { + CRegKey key; + lRes = key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ | KEY_WRITE); + if (lRes == ERROR_SUCCESS) + { + lRes = key.Create(key, lpszCLSID, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); + if (lRes == ERROR_SUCCESS) + { + lRes = key.SetStringValue(NULL, szDesc); + if (lRes == ERROR_SUCCESS) + { + lRes = lpszProgID ? key.SetKeyValue(szProgID, lpszProgID) : ERROR_SUCCESS; + if (lRes == ERROR_SUCCESS) + { + lRes = lpszVerIndProgID ? key.SetKeyValue(szVIProgID, lpszVerIndProgID) : ERROR_SUCCESS; + if (lRes == ERROR_SUCCESS) + { + if ((m_hInst == NULL) || (m_hInst == GetModuleHandle(NULL))) // register as EXE + { + // If Registering as an EXE, then we quote the resultant path. + // We don't do it for a DLL, because LoadLibrary fails if the path is + // quoted + szModule[0] = _T('\"'); + szModule[dwLen + 1] = _T('\"'); + szModule[dwLen + 2] = 0; + + lRes = key.SetKeyValue(szLS32, szModule); + } + else + { + lRes = key.SetKeyValue(szIPS32, (dwFlags & AUTPRXFLAG) ? szAUTPRX32 : szModule + 1); + if (lRes == ERROR_SUCCESS) + { + LPCTSTR lpszModel = (dwFlags & THREADFLAGS_BOTH) ? szBoth : + (dwFlags & THREADFLAGS_APARTMENT) ? szApartment : NULL; + if (lpszModel != NULL) + lRes = key.SetKeyValue(szIPS32, lpszModel, szThreadingModel); + } + } + } + } + } + } + } + } + CoTaskMemFree(lpOleStr); + if (lRes != ERROR_SUCCESS) + hRes = AtlHresultFromWin32(lRes); + return hRes; +} + +inline HRESULT WINAPI CComModule::UnregisterClassHelper(const CLSID& clsid, LPCTSTR lpszProgID, + LPCTSTR lpszVerIndProgID) +{ + USES_CONVERSION_EX; + CRegKey key; + LONG lRet; + + key.Attach(HKEY_CLASSES_ROOT); + if (lpszProgID != NULL && lpszProgID[0]!=_T('\0')) + { + lRet = key.RecurseDeleteKey(lpszProgID); + if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) + { + ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister ProgID : %s\n"), lpszProgID); + key.Detach(); + return AtlHresultFromWin32(lRet); + } + } + if (lpszVerIndProgID != NULL && lpszVerIndProgID[0]!=_T('\0')) + { + lRet = key.RecurseDeleteKey(lpszVerIndProgID); + if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) + { + ATLTRACE(atlTraceCOM, 0, _T("Failed to Unregister Version Independent ProgID : %s\n"), lpszVerIndProgID); + key.Detach(); + return AtlHresultFromWin32(lRet); + } + } + LPOLESTR lpOleStr; + HRESULT hr = StringFromCLSID(clsid, &lpOleStr); + if (SUCCEEDED(hr)) + { + LPTSTR lpsz = OLE2T_EX(lpOleStr, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpsz == NULL) + { + CoTaskMemFree(lpOleStr); + return E_OUTOFMEMORY; + } +#endif + + lRet = key.Open(key, _T("CLSID"), KEY_READ | KEY_WRITE); + if (lRet == ERROR_SUCCESS) + lRet = key.RecurseDeleteKey(lpsz); + if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND && lRet != ERROR_PATH_NOT_FOUND) + { + ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : %s\n"), lpsz); + hr = AtlHresultFromWin32(lRet); + } + CoTaskMemFree(lpOleStr); + } + else + { + ATLTRACE(atlTraceCOM, 0, _T("Failed to delete CLSID : {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"), + clsid.Data1, + clsid.Data2, + clsid.Data3, + clsid.Data4[0], + clsid.Data4[1], + clsid.Data4[2], + clsid.Data4[3], + clsid.Data4[4], + clsid.Data4[5], + clsid.Data4[6], + clsid.Data4[7] + ); + } + key.Detach(); + return hr; +} + +#pragma warning( pop ) // Disable "deprecated symbol" warning + +#endif // !_ATL_NO_COMMODULE + +#ifdef _ATL_DEBUG_INTERFACES + +inline void _QIThunk::Dump() throw() +{ + TCHAR buf[512+1]; + if (m_dwRef != 0) + { +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) + _stprintf_s(buf, _countof(buf), _T("ATL: QIThunk - %-10d\tLEAK :\tObject = 0x%p\tRefcount = %d\tMaxRefCount = %d\t"), + m_nIndex, m_pUnk, m_dwRef, m_dwMaxRef); +#else +#pragma warning(push) +#pragma warning(disable:4995) // wsprintf is deprecated + wsprintf(buf, _T("ATL: QIThunk - %-10d\tLEAK :\tObject = 0x%p\tRefcount = %d\tMaxRefCount = %d\t"), m_nIndex, m_pUnk, m_dwRef, m_dwMaxRef); +#pragma warning(pop) +#endif + buf[_countof(buf)-1] = 0; + OutputDebugString(buf); + AtlDumpIID(m_iid, m_lpszClassName, S_OK); + } + else + { +#if _SECURE_ATL && !defined(_ATL_MIN_CRT) + _stprintf_s(buf, _countof(buf), _T("ATL: QIThunk - %-10d\tNonAddRef LEAK :\tObject = 0x%p\t"), m_nIndex, m_pUnk); +#else +#pragma warning(push) +#pragma warning(disable:4995) // wsprintf is deprecated + wsprintf(buf, _T("ATL: QIThunk - %-10d\tNonAddRef LEAK :\tObject = 0x%p\t"), m_nIndex, m_pUnk); +#pragma warning(pop) +#endif + buf[_countof(buf)-1] = 0; + OutputDebugString(buf); + AtlDumpIID(m_iid, m_lpszClassName, S_OK); + } +} + +#endif // _ATL_DEBUG_INTERFACES + +#if defined(_ATL_DEBUG_INTERFACES) || defined(_ATL_DEBUG_QI) +__forceinline HRESULT WINAPI AtlDumpIID(REFIID iid, LPCTSTR pszClassName, HRESULT hr) throw() +{ + USES_CONVERSION_EX; + CRegKey key; + TCHAR szName[100]; + DWORD dwType; + DWORD dw = sizeof(szName); + + LPOLESTR pszGUID = NULL; + if (FAILED(StringFromCLSID(iid, &pszGUID))) + return hr; + + OutputDebugString(pszClassName); + OutputDebugString(_T(" - ")); + + LPTSTR lpszGUID = OLE2T_EX(pszGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpszGUID == NULL) + { + CoTaskMemFree(pszGUID); + return hr; + } +#endif + // Attempt to find it in the interfaces section + if (key.Open(HKEY_CLASSES_ROOT, _T("Interface"), KEY_READ) == ERROR_SUCCESS) + { + if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) + { + *szName = 0; + if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) + { + OutputDebugString(szName); + } + } + } + // Attempt to find it in the clsid section + if (key.Open(HKEY_CLASSES_ROOT, _T("CLSID"), KEY_READ) == ERROR_SUCCESS) + { + if (key.Open(key, lpszGUID, KEY_READ) == ERROR_SUCCESS) + { + *szName = 0; + dw = sizeof(szName); + if (RegQueryValueEx(key.m_hKey, (LPTSTR)NULL, NULL, &dwType, (LPBYTE)szName, &dw) == ERROR_SUCCESS) + { + OutputDebugString(_T("(CLSID\?\?\?) ")); + OutputDebugString(szName); + } + } + } + else + OutputDebugString(lpszGUID); + + if (hr != S_OK) + OutputDebugString(_T(" - failed")); + OutputDebugString(_T("\n")); + CoTaskMemFree(pszGUID); + + return hr; +} +#endif // _ATL_DEBUG_INTERFACES || _ATL_DEBUG_QI + + + +// WM_FORWARDMSG - used to forward a message to another window for processing +// WPARAM - DWORD dwUserData - defined by user +// LPARAM - LPMSG pMsg - a pointer to the MSG structure +// return value - 0 if the message was not processed, nonzero if it was +#define WM_FORWARDMSG 0x037F + +}; //namespace ATL + + +#ifndef _ATL_NO_AUTOMATIC_NAMESPACE +using namespace ATL; +#endif //!_ATL_NO_AUTOMATIC_NAMESPACE + +#ifdef _ATL_ATTRIBUTES +#include +#endif + + + +namespace ATL +{ + +// All exports go here +// Pull in if building ATL DLL or not linking to ATL DLL +#ifndef _ATL_DLL + +///////////////////////////////////////////////////////////////////////////// +// statics + +static inline UINT WINAPI AtlGetDirLen(LPCOLESTR lpszPathName) throw() +{ + ATLASSERT(lpszPathName != NULL); + if(lpszPathName == NULL) + return 0; + + // always capture the complete file name including extension (if present) + LPCOLESTR lpszTemp = lpszPathName; + for (LPCOLESTR lpsz = lpszPathName; *lpsz != NULL; ) + { + LPCOLESTR lp = CharNextO(lpsz); + // remember last directory/drive separator + if (*lpsz == OLESTR('\\') || *lpsz == OLESTR('/') || *lpsz == OLESTR(':')) + lpszTemp = lp; + lpsz = lp; + } + + return UINT( lpszTemp-lpszPathName ); +} + +static inline LPTSTR AtlFindExtension(LPCTSTR psz) +{ + if (psz == NULL) + return NULL; + LPCTSTR pszRemember = NULL; + while (*psz != NULL) + { + switch(*psz) + { + case _T('\\'): + pszRemember = NULL; + break; + case _T('.'): + pszRemember = psz; + break; + default: + break; + } + psz = CharNext(psz); + } + return (LPTSTR)((pszRemember == NULL) ? psz : pszRemember); +} + + +///////////////////////////////////////////////////////////////////////////// +// TypeLib registration + +#define _ATL_MAX_PATH_PLUS_INDEX (_MAX_PATH + _ATL_TYPELIB_INDEX_LENGTH) + +ATLINLINE ATLAPI AtlLoadTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) +{ + ATLASSERT(pbstrPath != NULL && ppTypeLib != NULL); + if (pbstrPath == NULL || ppTypeLib == NULL) + return E_POINTER; + + *pbstrPath = NULL; + *ppTypeLib = NULL; + + USES_CONVERSION_EX; + ATLASSERT(hInstTypeLib != NULL); + TCHAR szModule[_ATL_MAX_PATH_PLUS_INDEX]; + + DWORD dwFLen = GetModuleFileName(hInstTypeLib, szModule, MAX_PATH); + if( dwFLen == 0 ) + return AtlHresultFromLastError(); + else if( dwFLen == MAX_PATH ) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + + // get the extension pointer in case of fail + LPTSTR lpszExt = NULL; + + lpszExt = AtlFindExtension(szModule); + + if (lpszIndex != NULL) + { + LPCTSTR lpcszIndex = OLE2CT_EX(lpszIndex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + if(lpcszIndex == NULL) + { + return E_OUTOFMEMORY; + } + DWORD nIndexLen = lstrlen(lpcszIndex); + + DWORD newLen = dwFLen + nIndexLen; + if ((newLen < dwFLen) || (newLen < nIndexLen) || (newLen >= _ATL_MAX_PATH_PLUS_INDEX)) + return E_FAIL; +#ifdef UNICODE + Checked::wcscpy_s(szModule + dwFLen, _countof(szModule) - dwFLen, lpcszIndex); +#else + Checked::strcpy_s(szModule + dwFLen, _countof(szModule) - dwFLen, lpcszIndex); +#endif + } + LPOLESTR lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpszModule == NULL) + return E_OUTOFMEMORY; +#endif + HRESULT hr = LoadTypeLib(lpszModule, ppTypeLib); + if (!SUCCEEDED(hr)) + { + // typelib not in module, try .tlb instead + TCHAR szExt[] = _T(".tlb"); + if ((lpszExt - szModule + sizeof(szExt)/sizeof(TCHAR)) > _MAX_PATH) + return E_FAIL; + +#ifdef UNICODE + Checked::wcscpy_s(lpszExt, _countof(szModule) - (lpszExt - szModule), szExt); +#else + Checked::strcpy_s(lpszExt, _countof(szModule) - (lpszExt - szModule), szExt); +#endif + lpszModule = T2OLE_EX(szModule, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if(lpszModule == NULL) + return E_OUTOFMEMORY; +#endif + hr = LoadTypeLib(lpszModule, ppTypeLib); + } + if (SUCCEEDED(hr)) + { + *pbstrPath = ::SysAllocString(lpszModule); + if (*pbstrPath == NULL) + hr = E_OUTOFMEMORY; + } + return hr; +} + +ATLINLINE ATLAPI AtlUnRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) +{ + CComBSTR bstrPath; + CComPtr pTypeLib; + HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); + if (SUCCEEDED(hr)) + { + TLIBATTR* ptla; + hr = pTypeLib->GetLibAttr(&ptla); + if (SUCCEEDED(hr)) + { + hr = UnRegisterTypeLib(ptla->guid, ptla->wMajorVerNum, ptla->wMinorVerNum, ptla->lcid, ptla->syskind); + pTypeLib->ReleaseTLibAttr(ptla); + } + } + return hr; +} + +ATLINLINE ATLAPI AtlRegisterTypeLib(HINSTANCE hInstTypeLib, LPCOLESTR lpszIndex) +{ + CComBSTR bstrPath; + CComPtr pTypeLib; + HRESULT hr = AtlLoadTypeLib(hInstTypeLib, lpszIndex, &bstrPath, &pTypeLib); + if (SUCCEEDED(hr)) + { + CComBSTR bstrHelpFile; + hr = pTypeLib->GetDocumentation(-1, NULL, NULL, NULL, &bstrHelpFile); + if (SUCCEEDED(hr) && (bstrHelpFile.m_str != NULL)) + { + OLECHAR szDir[MAX_PATH]; + Checked::wcsncpy_s(szDir, MAX_PATH, bstrPath.m_str, bstrPath.Length()); + + szDir[MAX_PATH - 1] = 0; + + // If index is specified remove it from the path + if (lpszIndex != NULL) + { + size_t nLenPath = ocslen(szDir); + size_t nLenIndex = ocslen(lpszIndex); + if ((memcmp(szDir + nLenPath - nLenIndex, lpszIndex, nLenIndex) == 0) + && (nLenPath - nLenIndex < MAX_PATH)) + szDir[nLenPath - nLenIndex] = 0; + } + UINT nDirLen = AtlGetDirLen(szDir); + if (nDirLen < MAX_PATH) + szDir[nDirLen] = 0; + + hr = ::RegisterTypeLib(pTypeLib, bstrPath, szDir); + + } + else + { + hr = ::RegisterTypeLib(pTypeLib, bstrPath, NULL); + } + } + return hr; +} + +///////////////////////////////////////////////////////////////////////////// +// Registration + +// AtlComModuleRegisterServer walks the ATL Autogenerated Object Map and registers each object in the map +// If pCLSID is not NULL then only the object referred to by pCLSID is registered (The default case) +// otherwise all the objects are registered +ATLINLINE ATLAPI AtlComModuleRegisterServer(_ATL_COM_MODULE* pComModule, BOOL bRegTypeLib, const CLSID* pCLSID) +{ + ATLASSERT(pComModule != NULL); + if (pComModule == NULL) + return E_INVALIDARG; + ATLASSERT(pComModule->m_hInstTypeLib != NULL); + + HRESULT hr = S_OK; + + for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + { + _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; + if (pCLSID != NULL) + { + if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) + continue; + } + hr = pEntry->pfnUpdateRegistry(TRUE); + if (FAILED(hr)) + break; + hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, + pEntry->pfnGetCategoryMap(), TRUE ); + if (FAILED(hr)) + break; + } + } + + if (SUCCEEDED(hr) && bRegTypeLib) + hr = AtlRegisterTypeLib(pComModule->m_hInstTypeLib, 0); + + return hr; +} + +// AtlComUnregisterServer walks the ATL Object Map and unregisters each object in the map +// If pCLSID is not NULL then only the object referred to by pCLSID is unregistered (The default case) +// otherwise all the objects are unregistered. +ATLINLINE ATLAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE* pComModule, BOOL bUnRegTypeLib, const CLSID* pCLSID) +{ + ATLASSERT(pComModule != NULL); + if (pComModule == NULL) + return E_INVALIDARG; + + HRESULT hr = S_OK; + + for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + { + _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; + if (pCLSID != NULL) + { + if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) + continue; + } + hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, pEntry->pfnGetCategoryMap(), FALSE ); + if (FAILED(hr)) + break; + hr = pEntry->pfnUpdateRegistry(FALSE); //unregister + if (FAILED(hr)) + break; + } + } + if (SUCCEEDED(hr) && bUnRegTypeLib) + hr = AtlUnRegisterTypeLib(pComModule->m_hInstTypeLib, 0); + + return hr; +} + +ATLINLINE ATLAPI AtlRegisterClassCategoriesHelper( REFCLSID clsid, + const struct _ATL_CATMAP_ENTRY* pCatMap, BOOL bRegister ) +{ + CComPtr< ICatRegister > pCatRegister; + HRESULT hResult; + const struct _ATL_CATMAP_ENTRY* pEntry; + CATID catid; + + if( pCatMap == NULL ) + { + return( S_OK ); + } + + if (InlineIsEqualGUID(clsid, GUID_NULL)) + { + ATLASSERT(0 && _T("Use OBJECT_ENTRY_NON_CREATEABLE_EX macro if you want to register class categories for non creatable objects.")); + return S_OK; + } + + hResult = CoCreateInstance( CLSID_StdComponentCategoriesMgr, NULL, + CLSCTX_INPROC_SERVER, __uuidof(ICatRegister), (void**)&pCatRegister ); + if( FAILED( hResult ) ) + { + // Since not all systems have the category manager installed, we'll allow + // the registration to succeed even though we didn't register our + // categories. If you really want to register categories on a system + // without the category manager, you can either manually add the + // appropriate entries to your registry script (.rgs), or you can + // redistribute comcat.dll. + return( S_OK ); + } + + hResult = S_OK; + pEntry = pCatMap; + while( pEntry->iType != _ATL_CATMAP_ENTRY_END ) + { + catid = *pEntry->pcatid; + if( bRegister ) + { + if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) + { + hResult = pCatRegister->RegisterClassImplCategories( clsid, 1, + &catid ); + } + else + { + ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); + hResult = pCatRegister->RegisterClassReqCategories( clsid, 1, + &catid ); + } + if( FAILED( hResult ) ) + { + return( hResult ); + } + } + else + { + if( pEntry->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED ) + { + pCatRegister->UnRegisterClassImplCategories( clsid, 1, &catid ); + } + else + { + ATLASSERT( pEntry->iType == _ATL_CATMAP_ENTRY_REQUIRED ); + pCatRegister->UnRegisterClassReqCategories( clsid, 1, &catid ); + } + } + pEntry++; + } + + // When unregistering remove "Implemented Categories" and "Required Categories" subkeys if they are empty. + if (!bRegister) + { + OLECHAR szGUID[64]; + ::StringFromGUID2(clsid, szGUID, 64); + USES_CONVERSION_EX; + TCHAR* pszGUID = OLE2T_EX(szGUID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + if (pszGUID != NULL) + { + TCHAR szKey[128]; +#ifdef UNICODE + Checked::wcscpy_s(szKey, _countof(szKey), _T("CLSID\\")); + Checked::wcscat_s(szKey, _countof(szKey), pszGUID); + Checked::wcscat_s(szKey, _countof(szKey), _T("\\Required Categories")); +#else + Checked::strcpy_s(szKey, _countof(szKey), _T("CLSID\\")); + Checked::strcat_s(szKey, _countof(szKey), pszGUID); + Checked::strcat_s(szKey, _countof(szKey), _T("\\Required Categories")); +#endif + + CRegKey root(HKEY_CLASSES_ROOT); + CRegKey key; + DWORD cbSubKeys = 0; + + LRESULT lRes = key.Open(root, szKey, KEY_READ); + if (lRes == ERROR_SUCCESS) + { + lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + key.Close(); + if (lRes == ERROR_SUCCESS && cbSubKeys == 0) + { + root.DeleteSubKey(szKey); + } + } + +#ifdef UNICODE + Checked::wcscpy_s(szKey, _countof(szKey), _T("CLSID\\")); + Checked::wcscat_s(szKey, _countof(szKey), pszGUID); + Checked::wcscat_s(szKey, _countof(szKey), _T("\\Implemented Categories")); +#else + Checked::strcpy_s(szKey, _countof(szKey), _T("CLSID\\")); + Checked::strcat_s(szKey, _countof(szKey), pszGUID); + Checked::strcat_s(szKey, _countof(szKey), _T("\\Implemented Categories")); +#endif + lRes = key.Open(root, szKey, KEY_READ); + if (lRes == ERROR_SUCCESS) + { + lRes = RegQueryInfoKey(key, NULL, NULL, NULL, &cbSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + key.Close(); + if (lRes == ERROR_SUCCESS && cbSubKeys == 0) + { + root.DeleteSubKey(szKey); + } + } + } + } + return( S_OK ); +} + +#endif // _ATL_DLL + +ATLINLINE ATLAPIINL +AtlWinModuleTerm(_ATL_WIN_MODULE* pWinModule, HINSTANCE hInst) +{ + if (pWinModule == NULL) + return E_INVALIDARG; + if (pWinModule->cbSize == 0) + return S_OK; + if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) + return E_INVALIDARG; + + for (int i = 0; i < pWinModule->m_rgWindowClassAtoms.GetSize(); i++) + UnregisterClass((LPCTSTR)pWinModule->m_rgWindowClassAtoms[i], hInst); + pWinModule->m_rgWindowClassAtoms.RemoveAll(); + pWinModule->m_csWindowCreate.Term(); + pWinModule->cbSize = 0; + return S_OK; +} + + + +///////////////////////////////////////////////////////////////////////////// +// General DLL Version Helpers + +#pragma warning(push) +#pragma warning(disable : 4191) // 'type cast' : unsafe conversion from 'FARPROC' to 'DLLGETVERSIONPROC' + +inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo) +{ + ATLENSURE(pDllVersionInfo != NULL); + + // We must get this function explicitly because some DLLs don't implement it. + DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion"); + + if(pfnDllGetVersion == NULL) + { + return E_NOTIMPL; + } + + return (*pfnDllGetVersion)(pDllVersionInfo); +} + +#pragma warning(pop) + +inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo) +{ + HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName); + if(hInstDLL == NULL) + { + return AtlHresultFromLastError(); + } + HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo); + ::FreeLibrary(hInstDLL); + return hRet; +} + +// Common Control Versions: +// Win95/WinNT 4.0 maj=4 min=00 +// IE 3.x maj=4 min=70 +// IE 4.0 maj=4 min=71 +// IE 5.0 maj=5 min=80 +// Win2000 maj=5 min=81 +inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) +{ + ATLENSURE(( pdwMajor != NULL ) && ( pdwMinor != NULL )); + + DLLVERSIONINFO dvi; + memset(&dvi, 0, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + + HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi); + + if(SUCCEEDED(hRet)) + { + *pdwMajor = dvi.dwMajorVersion; + *pdwMinor = dvi.dwMinorVersion; + } + else if(hRet == E_NOTIMPL) + { + // If DllGetVersion is not there, then the DLL is a version + // previous to the one shipped with IE 3.x + *pdwMajor = 4; + *pdwMinor = 0; + hRet = S_OK; + } + + return hRet; +} + +// Shell Versions: +// Win95/WinNT 4.0 maj=4 min=00 +// IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00 +// IE 4.0 with Web Integrated Desktop maj=4 min=71 +// IE 4.01 with Web Integrated Desktop maj=4 min=72 +// Win2000 maj=5 min=00 +inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) +{ + ATLENSURE(( pdwMajor != NULL) && ( pdwMinor != NULL )); + + DLLVERSIONINFO dvi; + memset(&dvi, 0, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi); + + if(SUCCEEDED(hRet)) + { + *pdwMajor = dvi.dwMajorVersion; + *pdwMinor = dvi.dwMinorVersion; + } + else if(hRet == E_NOTIMPL) + { + // If DllGetVersion is not there, then the DLL is a version + // previous to the one shipped with IE 4.x + *pdwMajor = 4; + *pdwMinor = 0; + hRet = S_OK; + } + + return hRet; +} + +inline ATL_DEPRECATED("AtlModuleRegisterClassObjects has been replaced by AtlComModuleRegisterClassObjects") +HRESULT AtlModuleRegisterClassObjects(_ATL_MODULE* /*pM*/, DWORD dwClsContext, DWORD dwFlags) +{ + return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); +} + +inline ATL_DEPRECATED("AtlModuleRevokeClassObjects has been replaced by AtlComModuleRevokeClassObjects") +HRESULT AtlModuleRevokeClassObjects(_ATL_MODULE* /*pM*/) +{ + return AtlComModuleRevokeClassObjects(&_AtlComModule); +} + +inline ATL_DEPRECATED("AtlModuleGetClassObject has been replaced by AtlComModuleGetClassObject") +HRESULT AtlModuleGetClassObject(_ATL_MODULE* /*pM*/, REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ +#ifndef _ATL_OLEDB_CONFORMANCE_TESTS + ATLASSERT(ppv != NULL); +#endif + + return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); +} + +inline ATL_DEPRECATED("AtlModuleRegisterServer has been replaced by AtlComModuleRegisterServer") +HRESULT AtlModuleRegisterServer(_ATL_MODULE* /*pM*/, BOOL bRegTypeLib, const CLSID* pCLSID = NULL) +{ + return AtlComModuleRegisterServer(&_AtlComModule, bRegTypeLib, pCLSID); +} + +inline ATL_DEPRECATED("AtlModuleUnregisterServer has been replaced by AtlComModuleUnregisterServer") +HRESULT AtlModuleUnregisterServer(_ATL_MODULE* /*pM*/, const CLSID* pCLSID = NULL) +{ + return AtlComModuleUnregisterServer(&_AtlComModule, FALSE, pCLSID); +} + +inline ATL_DEPRECATED("AtlModuleUnregisterServerEx has been replaced by AtlComModuleUnregisterServer") +HRESULT AtlModuleUnregisterServerEx(_ATL_MODULE* /*pM*/, BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL) +{ + return AtlComModuleUnregisterServer(&_AtlComModule, bUnRegTypeLib, pCLSID); +} + +inline ATL_DEPRECATED("AtlModuleUpdateRegistryFromResourceD has been replaced by AtlUpdateRegistryFromResourceD") +HRESULT AtlModuleUpdateRegistryFromResourceD(_ATL_MODULE* /*pM*/, LPCOLESTR lpszRes, + BOOL bRegister, struct _ATL_REGMAP_ENTRY* pMapEntries, IRegistrar* pReg = NULL) +{ + return AtlUpdateRegistryFromResourceD(_AtlBaseModule.GetModuleInstance(), lpszRes, bRegister, pMapEntries, pReg); +} + +inline ATL_DEPRECATED("AtlModuleRegisterTypeLib has been replaced by AtlRegisterTypeLib") +HRESULT AtlModuleRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) +{ + return AtlRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); +} + +inline ATL_DEPRECATED("AtlModuleUnRegisterTypeLib has been replaced by AtlUnRegisterTypeLib") +HRESULT AtlModuleUnRegisterTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex) +{ + return AtlUnRegisterTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex); +} + +inline ATL_DEPRECATED("AtlModuleLoadTypeLib has been replaced by AtlLoadTypeLib") +HRESULT AtlModuleLoadTypeLib(_ATL_MODULE* /*pM*/, LPCOLESTR lpszIndex, BSTR* pbstrPath, ITypeLib** ppTypeLib) +{ + return AtlLoadTypeLib(_AtlComModule.m_hInstTypeLib, lpszIndex, pbstrPath, ppTypeLib); +} + +inline ATL_DEPRECATED("AtlModuleInit is no longer required") +HRESULT AtlModuleInit(_ATL_MODULE* /*pM*/, _ATL_OBJMAP_ENTRY* /*p*/, HINSTANCE /*h*/) +{ + return S_OK; +} + +inline ATL_DEPRECATED("AtlModuleTerm is no longer required") +HRESULT AtlModuleTerm(_ATL_MODULE* /*pM*/) +{ + return S_OK; +} + +inline ATL_DEPRECATED("AtlModuleAddCreateWndData has been replaced by AtlWinModuleAddCreateWndData") +void AtlModuleAddCreateWndData(_ATL_MODULE* /*pM*/, _AtlCreateWndData* pData, void* pObject) +{ + AtlWinModuleAddCreateWndData(&_AtlWinModule, pData, pObject); +} + +inline ATL_DEPRECATED("AtlModuleExtractCreateWndData has been replaced by AtlWinModuleExtractCreateWndData") +void* AtlModuleExtractCreateWndData(_ATL_MODULE* /*pM*/) +{ + return AtlWinModuleExtractCreateWndData(&_AtlWinModule); +} + +#ifndef _ATL_NO_COMMODULE + +inline CRITICAL_SECTION& CComModule::get_m_csWindowCreate() throw() +{ + return _AtlWinModule.m_csWindowCreate.m_sec; +} + +inline CRITICAL_SECTION& CComModule::get_m_csObjMap() throw() +{ + return _AtlComModule.m_csObjMap.m_sec; +} + +inline CRITICAL_SECTION& CComModule::get_m_csStaticDataInit() throw() +{ + return m_csStaticDataInitAndTypeInfo.m_sec; +} + +inline _AtlCreateWndData*& CComModule::get_m_pCreateWndList() throw() +{ + return _AtlWinModule.m_pCreateWndList; +} +inline void CComModule::put_m_pCreateWndList(_AtlCreateWndData* p) throw() +{ + _AtlWinModule.m_pCreateWndList = p; +} +#ifdef _ATL_DEBUG_INTERFACES +inline UINT& CComModule::get_m_nIndexQI() throw() +{ + return _AtlDebugInterfacesModule.m_nIndexQI; +} +inline void CComModule::put_m_nIndexQI(UINT nIndex) throw() +{ + _AtlDebugInterfacesModule.m_nIndexQI = nIndex; +} +inline UINT& CComModule::get_m_nIndexBreakAt() throw() +{ + return _AtlDebugInterfacesModule.m_nIndexBreakAt; +} +inline void CComModule::put_m_nIndexBreakAt(UINT nIndex) throw() +{ + _AtlDebugInterfacesModule.m_nIndexBreakAt = nIndex; +} +inline CSimpleArray<_QIThunk*>* CComModule::get_m_paThunks() throw() +{ + return &_AtlDebugInterfacesModule.m_aThunks; +} +inline HRESULT CComModule::AddThunk(IUnknown** pp, LPCTSTR lpsz, REFIID iid) throw() +{ + return _AtlDebugInterfacesModule.AddThunk(pp, lpsz, iid); +} +inline HRESULT CComModule::AddNonAddRefThunk(IUnknown* p, LPCTSTR lpsz, IUnknown** ppThunkRet) throw() +{ + return _AtlDebugInterfacesModule.AddNonAddRefThunk(p, lpsz, ppThunkRet); +} + +inline void CComModule::DeleteNonAddRefThunk(IUnknown* pUnk) throw() +{ + _AtlDebugInterfacesModule.DeleteNonAddRefThunk(pUnk); +} + +inline void CComModule::DeleteThunk(_QIThunk* p) throw() +{ + _AtlDebugInterfacesModule.DeleteThunk(p); +} + +inline bool CComModule::DumpLeakedThunks() throw() +{ + return _AtlDebugInterfacesModule.DumpLeakedThunks(); +} +#endif // _ATL_DEBUG_INTERFACES + +inline HRESULT CComModule::Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE /*h*/, const GUID* plibid) throw() +{ + if (plibid != NULL) + m_libid = *plibid; + + _ATL_OBJMAP_ENTRY* pEntry; + if (p != (_ATL_OBJMAP_ENTRY*)-1) + { + m_pObjMap = p; + if (m_pObjMap != NULL) + { + pEntry = m_pObjMap; + while (pEntry->pclsid != NULL) + { + pEntry->pfnObjectMain(true); //initialize class resources + pEntry++; + } + } + } + for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + (*ppEntry)->pfnObjectMain(true); //initialize class resources + } + return S_OK; +} + +inline void CComModule::Term() throw() +{ + _ATL_OBJMAP_ENTRY* pEntry; + if (m_pObjMap != NULL) + { + pEntry = m_pObjMap; + while (pEntry->pclsid != NULL) + { + if (pEntry->pCF != NULL) + pEntry->pCF->Release(); + pEntry->pCF = NULL; + pEntry->pfnObjectMain(false); //cleanup class resources + pEntry++; + } + } + + for (_ATL_OBJMAP_ENTRY** ppEntry = _AtlComModule.m_ppAutoObjMapFirst; ppEntry < _AtlComModule.m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + (*ppEntry)->pfnObjectMain(false); //cleanup class resources + } +#ifdef _DEBUG + // Prevent false memory leak reporting. ~CAtlWinModule may be too late. + _AtlWinModule.Term(); +#endif // _DEBUG + + CAtlModuleT::Term(); +} + +inline HRESULT CComModule::GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) throw() +{ + if (ppv == NULL) + return E_POINTER; + HRESULT hr = S_OK; + _ATL_OBJMAP_ENTRY* pEntry; + if (m_pObjMap != NULL) + { + pEntry = m_pObjMap; + while (pEntry->pclsid != NULL) + { + if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) + { + if (pEntry->pCF == NULL) + { + CComCritSecLock lock(_AtlComModule.m_csObjMap, false); + hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in CComModule::GetClassObject\n")); + ATLASSERT(0); + break; + } + if (pEntry->pCF == NULL) + hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); + } + if (pEntry->pCF != NULL) + hr = pEntry->pCF->QueryInterface(riid, ppv); + break; + } + pEntry++; + } + } + if (*ppv == NULL && hr == S_OK) + hr = AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); + return hr; +} + +// Register/Revoke All Class Factories with the OS (EXE only) +inline HRESULT CComModule::RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw() +{ + HRESULT hr = S_OK; + _ATL_OBJMAP_ENTRY* pEntry; + if (m_pObjMap != NULL) + { + pEntry = m_pObjMap; + while (pEntry->pclsid != NULL && hr == S_OK) + { + hr = pEntry->RegisterClassObject(dwClsContext, dwFlags); + pEntry++; + } + } + if (hr == S_OK) + hr = AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); + return hr; +} +inline HRESULT CComModule::RevokeClassObjects() throw() +{ + HRESULT hr = S_OK; + _ATL_OBJMAP_ENTRY* pEntry; + if (m_pObjMap != NULL) + { + pEntry = m_pObjMap; + while (pEntry->pclsid != NULL && hr == S_OK) + { + hr = pEntry->RevokeClassObject(); + pEntry++; + } + } + if (hr == S_OK) + hr = AtlComModuleRevokeClassObjects(&_AtlComModule); + return hr; +} + +// Registry support (helpers) +inline HRESULT CComModule::RegisterTypeLib() throw() +{ + return _AtlComModule.RegisterTypeLib(); +} +inline HRESULT CComModule::RegisterTypeLib(LPCTSTR lpszIndex) throw() +{ + return _AtlComModule.RegisterTypeLib(lpszIndex); +} +inline HRESULT CComModule::UnRegisterTypeLib() throw() +{ + return _AtlComModule.UnRegisterTypeLib(); +} +inline HRESULT CComModule::UnRegisterTypeLib(LPCTSTR lpszIndex) throw() +{ + return _AtlComModule.UnRegisterTypeLib(lpszIndex); +} + +inline HRESULT CComModule::RegisterServer(BOOL bRegTypeLib /*= FALSE*/, const CLSID* pCLSID /*= NULL*/) throw() +{ + HRESULT hr = S_OK; + _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; + if (pEntry != NULL) + { + for (;pEntry->pclsid != NULL; pEntry++) + { + if (pCLSID != NULL) + { + if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) + continue; + } + hr = pEntry->pfnUpdateRegistry(TRUE); + if (FAILED(hr)) + break; + hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, + pEntry->pfnGetCategoryMap(), TRUE ); + if (FAILED(hr)) + break; + } + } + if (SUCCEEDED(hr)) + hr = CAtlModuleT::RegisterServer(bRegTypeLib, pCLSID); + return hr; +} + +inline HRESULT CComModule::UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID /*= NULL*/) throw() +{ + HRESULT hr = S_OK; + _ATL_OBJMAP_ENTRY* pEntry = m_pObjMap; + if (pEntry != NULL) + { + for (;pEntry->pclsid != NULL; pEntry++) + { + if (pCLSID != NULL) + { + if (!IsEqualGUID(*pCLSID, *pEntry->pclsid)) + continue; + } + hr = AtlRegisterClassCategoriesHelper( *pEntry->pclsid, + pEntry->pfnGetCategoryMap(), FALSE ); + if (FAILED(hr)) + break; + hr = pEntry->pfnUpdateRegistry(FALSE); //unregister + if (FAILED(hr)) + break; + } + } + if (SUCCEEDED(hr)) + hr = CAtlModuleT::UnregisterServer(bUnRegTypeLib, pCLSID); + return hr; +} + +inline HRESULT CComModule::UnregisterServer(const CLSID* pCLSID /*= NULL*/) throw() +{ + return UnregisterServer(FALSE, pCLSID); +} + +#endif // !_ATL_NO_COMMODULE + +} // namespace ATL + + +#pragma warning( pop ) + +#if !defined(_ATL_DLL) && !defined(_DEBUG) + +#include + +#endif // !_ATL_DLL && !_DEBUG + +#pragma pack(pop) +#ifdef _ATL_ALL_WARNINGS +#pragma warning( pop ) +#endif + +// +// [pfx_parse] - workaround for old PREfix/PREfast parser +// +#if (defined(_PREFIX_) || defined(_PREFAST_)) && (_MSC_VER < 1400) +#pragma warning (pop) +#endif // old PREfast parser + +///////////////////////////////////////////////////////////////////////////// + +#endif // __ATLBASE_H__ + diff --git a/c/jacob/include/atlbase.inl b/c/jacob/include/atlbase.inl new file mode 100644 index 0000000..0d2534c --- /dev/null +++ b/c/jacob/include/atlbase.inl @@ -0,0 +1,428 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLBASE_INL__ +#define __ATLBASE_INL__ + +#pragma once + +#ifndef __ATLBASE_H__ + #error atlbase.inl requires atlbase.h to be included first +#endif +#pragma warning(push) +#pragma warning(disable:4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions +namespace ATL +{ + +///////////////////////////////////////////////////////////////////////////// +// Connection Point Helpers + +ATLINLINE ATLAPI AtlAdvise(IUnknown* pUnkCP, IUnknown* pUnk, const IID& iid, LPDWORD pdw) +{ + if(pUnkCP == NULL) + return E_INVALIDARG; + + CComPtr pCPC; + CComPtr pCP; + HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); + if (SUCCEEDED(hRes)) + hRes = pCPC->FindConnectionPoint(iid, &pCP); + if (SUCCEEDED(hRes)) + hRes = pCP->Advise(pUnk, pdw); + return hRes; +} + +ATLINLINE ATLAPI AtlUnadvise(IUnknown* pUnkCP, const IID& iid, DWORD dw) +{ + if(pUnkCP == NULL) + return E_INVALIDARG; + + CComPtr pCPC; + CComPtr pCP; + HRESULT hRes = pUnkCP->QueryInterface(__uuidof(IConnectionPointContainer), (void**)&pCPC); + if (SUCCEEDED(hRes)) + hRes = pCPC->FindConnectionPoint(iid, &pCP); + if (SUCCEEDED(hRes)) + hRes = pCP->Unadvise(dw); + return hRes; +} + +///////////////////////////////////////////////////////////////////////////// +// Inproc Marshaling helpers + +//This API should be called from the same thread that called +//AtlMarshalPtrInProc +ATLINLINE ATLAPI AtlFreeMarshalStream(IStream* pStream) +{ + HRESULT hRes=S_OK; + if (pStream != NULL) + { + LARGE_INTEGER l; + l.QuadPart = 0; + pStream->Seek(l, STREAM_SEEK_SET, NULL); + hRes=CoReleaseMarshalData(pStream); + pStream->Release(); + } + return hRes; +} + +ATLINLINE ATLAPI AtlMarshalPtrInProc(IUnknown* pUnk, const IID& iid, IStream** ppStream) +{ + ATLASSERT(ppStream != NULL); + if (ppStream == NULL) + return E_POINTER; + + HRESULT hRes = CreateStreamOnHGlobal(NULL, TRUE, ppStream); + if (SUCCEEDED(hRes)) + { + hRes = CoMarshalInterface(*ppStream, iid, + pUnk, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); + if (FAILED(hRes)) + { + (*ppStream)->Release(); + *ppStream = NULL; + } + } + return hRes; +} + +ATLINLINE ATLAPI AtlUnmarshalPtr(IStream* pStream, const IID& iid, IUnknown** ppUnk) +{ + ATLASSERT(ppUnk != NULL); + if (ppUnk == NULL) + return E_POINTER; + + *ppUnk = NULL; + HRESULT hRes = E_INVALIDARG; + if (pStream != NULL) + { + LARGE_INTEGER l; + l.QuadPart = 0; + pStream->Seek(l, STREAM_SEEK_SET, NULL); + hRes = CoUnmarshalInterface(pStream, iid, (void**)ppUnk); + } + return hRes; +} + +///////////////////////////////////////////////////////////////////////////// +// Module + +ATLINLINE ATLAPI AtlComModuleGetClassObject(_ATL_COM_MODULE* pComModule, REFCLSID rclsid, REFIID riid, LPVOID* ppv) +{ + ATLASSERT(pComModule != NULL); + if (pComModule == NULL) + return E_INVALIDARG; + if (pComModule->cbSize == 0) // Module hasn't been initialized + return E_UNEXPECTED; + + if (ppv == NULL) + return E_POINTER; + *ppv = NULL; + + HRESULT hr = S_OK; + + for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast; ppEntry++) + { + if (*ppEntry != NULL) + { + _ATL_OBJMAP_ENTRY* pEntry = *ppEntry; + if ((pEntry->pfnGetClassObject != NULL) && InlineIsEqualGUID(rclsid, *pEntry->pclsid)) + { + if (pEntry->pCF == NULL) + { + CComCritSecLock lock(pComModule->m_csObjMap, false); + hr = lock.Lock(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceCOM, 0, _T("ERROR : Unable to lock critical section in AtlComModuleGetClassObject\n")); + ATLASSERT(0); + break; + } + if (pEntry->pCF == NULL) + hr = pEntry->pfnGetClassObject(pEntry->pfnCreateInstance, __uuidof(IUnknown), (LPVOID*)&pEntry->pCF); + } + if (pEntry->pCF != NULL) + hr = pEntry->pCF->QueryInterface(riid, ppv); + break; + } + } + } + + if (*ppv == NULL && hr == S_OK) + hr = CLASS_E_CLASSNOTAVAILABLE; + return hr; +} + +ATLINLINE ATLAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE* pComModule, DWORD dwClsContext, DWORD dwFlags) +{ + ATLASSERT(pComModule != NULL); + if (pComModule == NULL) + return E_INVALIDARG; + + HRESULT hr = S_FALSE; + for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && SUCCEEDED(hr); ppEntry++) + { + if (*ppEntry != NULL) + hr = (*ppEntry)->RegisterClassObject(dwClsContext, dwFlags); + } + return hr; +} + +ATLINLINE ATLAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE* pComModule) +{ + ATLASSERT(pComModule != NULL); + if (pComModule == NULL) + return E_INVALIDARG; + + HRESULT hr = S_OK; + for (_ATL_OBJMAP_ENTRY** ppEntry = pComModule->m_ppAutoObjMapFirst; ppEntry < pComModule->m_ppAutoObjMapLast && hr == S_OK; ppEntry++) + { + if (*ppEntry != NULL) + hr = (*ppEntry)->RevokeClassObject(); + } + return hr; +} + +ATLINLINE ATLAPI_(BOOL) AtlWaitWithMessageLoop(HANDLE hEvent) +{ + DWORD dwRet; + MSG msg; + + while(1) + { + dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); + + if (dwRet == WAIT_OBJECT_0) + return TRUE; // The event was signaled + + if (dwRet != WAIT_OBJECT_0 + 1) + break; // Something else happened + + // There is one or more window message available. Dispatch them + while(PeekMessage(&msg,0,0,0,PM_NOREMOVE)) + { + // check for unicode window so we call the appropriate functions + BOOL bUnicode = ::IsWindowUnicode(msg.hwnd); + BOOL bRet; + + if (bUnicode) + bRet = ::GetMessageW(&msg, NULL, 0, 0); + else + bRet = ::GetMessageA(&msg, NULL, 0, 0); + + if (bRet > 0) + { + ::TranslateMessage(&msg); + + if (bUnicode) + ::DispatchMessageW(&msg); + else + ::DispatchMessageA(&msg); + } + + if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) + return TRUE; // Event is now signaled. + } + } + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// QI support + +ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis, + const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject) +{ + ATLASSERT(pThis != NULL); + ATLASSERT(pEntries!= NULL); + + if(pThis == NULL || pEntries == NULL) + return E_INVALIDARG ; + + // First entry in the com map should be a simple map entry + ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY); + if (ppvObject == NULL) + return E_POINTER; + *ppvObject = NULL; + if (InlineIsEqualUnknown(iid)) // use first interface + { + IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); + pUnk->AddRef(); + *ppvObject = pUnk; + return S_OK; + } + while (pEntries->pFunc != NULL) + { + BOOL bBlind = (pEntries->piid == NULL); + if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid)) + { + if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset + { + ATLASSERT(!bBlind); + IUnknown* pUnk = (IUnknown*)((INT_PTR)pThis+pEntries->dw); + pUnk->AddRef(); + *ppvObject = pUnk; + return S_OK; + } + else //actual function call + { + HRESULT hRes = pEntries->pFunc(pThis, + iid, ppvObject, pEntries->dw); + if (hRes == S_OK || (!bBlind && FAILED(hRes))) + return hRes; + } + } + pEntries++; + } + return E_NOINTERFACE; +} + +ATLINLINE ATLAPI_(DWORD) AtlGetVersion(void* /* pReserved */) +{ + return _ATL_VER; +} + +///////////////////////////////////////////////////////////////////////////// +// Windowing + +ATLINLINE ATLAPI_(void) AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE* pWinModule, _AtlCreateWndData* pData, void* pObject) +{ + if (pWinModule == NULL) + _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); + + ATLASSERT(pData != NULL && pObject != NULL); + if(pData == NULL || pObject == NULL) + _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); + + pData->m_pThis = pObject; + pData->m_dwThreadID = ::GetCurrentThreadId(); + CComCritSecLock lock(pWinModule->m_csWindowCreate, false); + if (FAILED(lock.Lock())) + { + ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleAddCreateWndData\n")); + ATLASSERT(0); + return; + } + pData->m_pNext = pWinModule->m_pCreateWndList; + pWinModule->m_pCreateWndList = pData; +} + +ATLINLINE ATLAPI_(void*) AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE* pWinModule) +{ + if (pWinModule == NULL) + return NULL; + + void* pv = NULL; + CComCritSecLock lock(pWinModule->m_csWindowCreate, false); + if (FAILED(lock.Lock())) + { + ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to lock critical section in AtlWinModuleExtractCreateWndData\n")); + ATLASSERT(0); + return pv; + } + _AtlCreateWndData* pEntry = pWinModule->m_pCreateWndList; + if(pEntry != NULL) + { + DWORD dwThreadID = ::GetCurrentThreadId(); + _AtlCreateWndData* pPrev = NULL; + while(pEntry != NULL) + { + if(pEntry->m_dwThreadID == dwThreadID) + { + if(pPrev == NULL) + pWinModule->m_pCreateWndList = pEntry->m_pNext; + else + pPrev->m_pNext = pEntry->m_pNext; + pv = pEntry->m_pThis; + break; + } + pPrev = pEntry; + pEntry = pEntry->m_pNext; + } + } + return pv; +} + + +ATLINLINE ATLAPI AtlWinModuleInit(_ATL_WIN_MODULE* pWinModule) +{ + if (pWinModule == NULL) + return E_INVALIDARG; + + // check only in the DLL + if (pWinModule->cbSize != sizeof(_ATL_WIN_MODULE)) + return E_INVALIDARG; + + pWinModule->m_pCreateWndList = NULL; + + HRESULT hr = pWinModule->m_csWindowCreate.Init(); + if (FAILED(hr)) + { + ATLTRACE(atlTraceWindowing, 0, _T("ERROR : Unable to initialize critical section in AtlWinModuleInit\n")); + ATLASSERT(0); + } + return hr; +} + +///////////////////////////////////////////////////////////////////////////// +// Module + +ATLINLINE ATLAPI AtlModuleAddTermFunc(_ATL_MODULE* pModule, _ATL_TERMFUNC* pFunc, DWORD_PTR dw) +{ + if (pModule == NULL) + return E_INVALIDARG; + + HRESULT hr = S_OK; + _ATL_TERMFUNC_ELEM* pNew = NULL; + ATLTRY(pNew = new _ATL_TERMFUNC_ELEM); + if (pNew == NULL) + hr = E_OUTOFMEMORY; + else + { + pNew->pFunc = pFunc; + pNew->dw = dw; + CComCritSecLock lock(pModule->m_csStaticDataInitAndTypeInfo, false); + hr = lock.Lock(); + if (SUCCEEDED(hr)) + { + pNew->pNext = pModule->m_pTermFuncs; + pModule->m_pTermFuncs = pNew; + } + else + { + delete pNew; + ATLTRACE(atlTraceGeneral, 0, _T("ERROR : Unable to lock critical section in AtlModuleAddTermFunc\n")); + ATLASSERT(0); + } + } + return hr; +} + +ATLINLINE ATLAPI_(void) AtlCallTermFunc(_ATL_MODULE* pModule) +{ + if (pModule == NULL) + _AtlRaiseException((DWORD)EXCEPTION_ACCESS_VIOLATION); + + _ATL_TERMFUNC_ELEM* pElem = pModule->m_pTermFuncs; + _ATL_TERMFUNC_ELEM* pNext = NULL; + while (pElem != NULL) + { + pElem->pFunc(pElem->dw); + pNext = pElem->pNext; + delete pElem; + pElem = pNext; + } + pModule->m_pTermFuncs = NULL; +} + +} // namespace ATL +#pragma warning(pop) +#endif // __ATLBASE_INL__ + diff --git a/c/jacob/include/atlchecked.h b/c/jacob/include/atlchecked.h new file mode 100644 index 0000000..aadb522 --- /dev/null +++ b/c/jacob/include/atlchecked.h @@ -0,0 +1,605 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLCHECKED_H__ +#define __ATLCHECKED_H__ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#pragma warning(push) +#pragma warning(disable:4127) + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ + +inline errno_t AtlCrtErrorCheck(errno_t nError) +{ + switch(nError) + { + case ENOMEM: + AtlThrow(E_OUTOFMEMORY); + break; + case EINVAL: + case ERANGE: + AtlThrow(E_INVALIDARG); + break; + case 0: + case STRUNCATE: + break; + default: + AtlThrow(E_FAIL); + break; + } + return nError; +} + +///////////////////////////////////////////////////////////////////////////// +// Secure (Checked) CRT functions + +namespace Checked +{ + +#if _SECURE_ATL + +#ifdef _AFX +#define ATLMFC_CRT_ERRORCHECK(expr) AFX_CRT_ERRORCHECK(expr) +#else +#define ATLMFC_CRT_ERRORCHECK(expr) ATL_CRT_ERRORCHECK(expr) +#endif + +inline void __cdecl memcpy_s(__out_bcount_part(_S1max,_N) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, __in size_t _N) +{ + ATLMFC_CRT_ERRORCHECK(::memcpy_s(_S1, _S1max, _S2, _N)); +} + +inline void __cdecl wmemcpy_s(__out_ecount_part(_N1,_N) wchar_t *_S1, __in size_t _N1, __in_ecount(_N) const wchar_t *_S2, __in size_t _N) +{ + ATLMFC_CRT_ERRORCHECK(::wmemcpy_s(_S1, _N1, _S2, _N)); +} + +inline void __cdecl memmove_s(__out_bcount_part(_S1max,_N) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, size_t _N) +{ + ATLMFC_CRT_ERRORCHECK(::memmove_s(_S1, _S1max, _S2, _N)); +} + +inline void __cdecl strcpy_s(__out_ecount(_S1max) char *_S1, __in size_t _S1max, __in_z const char *_S2) +{ + ATLMFC_CRT_ERRORCHECK(::strcpy_s(_S1, _S1max, _S2)); +} + +inline void __cdecl wcscpy_s(__out_ecount(_S1max) wchar_t *_S1, __in size_t _S1max, __in_z const wchar_t *_S2) +{ + ATLMFC_CRT_ERRORCHECK(::wcscpy_s(_S1, _S1max, _S2)); +} + +inline void __cdecl tcscpy_s(__out_ecount(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) +{ +#ifndef _ATL_MIN_CRT + ATLMFC_CRT_ERRORCHECK(::_tcscpy_s(_Dst, _SizeInChars, _Src)); +#else +#ifdef UNICODE + ATLMFC_CRT_ERRORCHECK(::wcscpy_s(_Dst, _SizeInChars, _Src)); +#else + ATLMFC_CRT_ERRORCHECK(::strcpy_s(_Dst, _SizeInChars, _Src)); +#endif +#endif +} + +inline errno_t __cdecl strncpy_s(__out_ecount(_SizeInChars) char *_Dest, __in size_t _SizeInChars, __in_z const char *_Source, __in size_t _Count) +{ + return ATLMFC_CRT_ERRORCHECK(::strncpy_s(_Dest, _SizeInChars, _Source,_Count)); +} + +inline errno_t __cdecl wcsncpy_s(__out_ecount(_SizeInChars) wchar_t *_Dest, __in size_t _SizeInChars, __in_z const wchar_t *_Source, __in size_t _Count) +{ + return ATLMFC_CRT_ERRORCHECK(::wcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); +} + +inline errno_t __cdecl tcsncpy_s(__out_ecount(_SizeInChars) TCHAR *_Dest, __in size_t _SizeInChars, __in_z const TCHAR *_Source, __in size_t _Count) +{ +#ifndef _ATL_MIN_CRT + return ATLMFC_CRT_ERRORCHECK(::_tcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); +#else +#ifdef UNICODE + return ATLMFC_CRT_ERRORCHECK(::wcsncpy_s(_Dest, _SizeInChars, _Source,_Count)); +#else + return ATLMFC_CRT_ERRORCHECK(::strncpy_s(_Dest, _SizeInChars, _Source,_Count)); +#endif +#endif +} + +inline void __cdecl strcat_s(__inout_ecount_z(_SizeInChars) char * _Dst, __in size_t _SizeInChars, __in_z const char * _Src) +{ + ATLMFC_CRT_ERRORCHECK(::strcat_s(_Dst, _SizeInChars, _Src)); +} + +inline void __cdecl wcscat_s(__inout_ecount_z(_SizeInChars) wchar_t * _Dst, __in size_t _SizeInChars, __in_z const wchar_t * _Src) +{ + ATLMFC_CRT_ERRORCHECK(::wcscat_s(_Dst, _SizeInChars, _Src)); +} + +inline void __cdecl tcscat_s(__inout_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) +{ +#ifndef _ATL_MIN_CRT + ATLMFC_CRT_ERRORCHECK(::_tcscat_s(_Dst, _SizeInChars, _Src)); +#else +#ifdef UNICODE + ATLMFC_CRT_ERRORCHECK(::wcscat_s(_Dst, _SizeInChars, _Src)); +#else + ATLMFC_CRT_ERRORCHECK(::strcat_s(_Dst, _SizeInChars, _Src)); +#endif +#endif +} + +inline void __cdecl strlwr_s(__inout_ecount_z(_SizeInChars) char * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_strlwr_s(_Str, _SizeInChars)); +} + +inline void __cdecl wcslwr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_wcslwr_s(_Str, _SizeInChars)); +} + +#if !defined(_MANAGED) +inline void __cdecl mbslwr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_mbslwr_s(_Str, _SizeInChars)); +} +#endif + +inline void __cdecl tcslwr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, __in size_t _SizeInChars) +{ +#ifndef _ATL_MIN_CRT + ATLMFC_CRT_ERRORCHECK(::_tcslwr_s(_Str, _SizeInChars)); +#else +#ifdef UNICODE + ATLMFC_CRT_ERRORCHECK(::_wcslwr_s(_Str, _SizeInChars)); +#else + ATLMFC_CRT_ERRORCHECK(::_strlwr_s(_Str, _SizeInChars)); +#endif +#endif +} + +inline void __cdecl strupr_s(__inout_ecount_z(_SizeInChars) char * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_strupr_s(_Str, _SizeInChars)); +} + +inline void __cdecl wcsupr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_wcsupr_s(_Str, _SizeInChars)); +} + +#if !defined(_MANAGED) +inline void __cdecl mbsupr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_mbsupr_s(_Str, _SizeInChars)); +} +#endif + +inline void __cdecl tcsupr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, __in size_t _SizeInChars) +{ + ATLMFC_CRT_ERRORCHECK(::_tcsupr_s(_Str, _SizeInChars)); +} + +inline void __cdecl itoa_s(__in int _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_itoa_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl itot_s(__in int _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_itot_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ltoa_s(__in long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ltoa_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ltot_s(__in long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ltot_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ultoa_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ultoa_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ultow_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ultow_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ultot_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ultot_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl i64toa_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_i64toa_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl i64tow_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_i64tow_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ui64toa_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ui64toa_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl ui64tow_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + ATLMFC_CRT_ERRORCHECK(::_ui64tow_s(_Val, _Buf, _SizeInChars, _Radix)); +} + +inline void __cdecl gcvt_s(__out_ecount_z(_SizeInChars) char *_Buffer, __in size_t _SizeInChars, __in double _Value, __in int _Ndec) +{ + ATLMFC_CRT_ERRORCHECK(::_gcvt_s(_Buffer, _SizeInChars, _Value, _Ndec)); +} + +inline void __cdecl tsplitpath_s(__in_z const TCHAR *_Path, __out_ecount_z_opt(_Drive_len) TCHAR *_Drive, __in size_t _Drive_len, + __out_ecount_z_opt(_Dir_len) TCHAR *_Dir, __in size_t _Dir_len, + __out_ecount_z_opt(_Fname_len) TCHAR *_Fname, __in size_t _Fname_len, + __out_ecount_z_opt(_Ext_len) TCHAR *_Ext, __in size_t _Ext_len) +{ + ATLMFC_CRT_ERRORCHECK(::_tsplitpath_s(_Path, _Drive, _Drive_len, _Dir, _Dir_len, _Fname, _Fname_len, _Ext, _Ext_len)); +} + +inline void __cdecl tmakepath_s(__out_ecount_z(_SizeInChars) TCHAR *_Path, __in size_t _SizeInChars, __in_z const TCHAR *_Drive, + __in_z const TCHAR *_Dir, __in_z const TCHAR *_Fname, __in_z const TCHAR *_Ext) +{ + ATLMFC_CRT_ERRORCHECK(::_tmakepath_s(_Path, _SizeInChars, _Drive, _Dir, _Fname, _Ext)); +} + +inline size_t __cdecl strnlen(__in_ecount(_Maxsize) const char *_Str, __in size_t _Maxsize) +{ + return ::strnlen(_Str, _Maxsize); +} + +inline size_t __cdecl wcsnlen(__in_ecount(_Maxsize) const wchar_t *_Wcs, __in size_t _Maxsize) +{ + return ::wcsnlen(_Wcs, _Maxsize); +} + +inline size_t __cdecl tcsnlen(__in_ecount(_Maxsize) const TCHAR *_Str, __in size_t _Maxsize) +{ + return ::_tcsnlen(_Str, _Maxsize); +} + +inline int get_errno() +{ + int nErrNo; + ATLMFC_CRT_ERRORCHECK(::_get_errno(&nErrNo)); + return nErrNo; +} + +inline void set_errno(__in int _Value) +{ + ATLMFC_CRT_ERRORCHECK(::_set_errno(_Value)); +} + +#else // !_SECURE_ATL + +#define ATLMFC_CRT_ERRORCHECK(expr) do { expr; } while (0) + +inline void __cdecl memcpy_s(__out_bcount(_S1max) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, size_t _N) +{ + (_S1max); + memcpy(_S1, _S2, _N); +} + +inline void __cdecl wmemcpy_s(__out_ecount(_N1) wchar_t *_S1, __in size_t _N1, __in_ecount(_N) const wchar_t *_S2, __in size_t _N) +{ + (_N1); + ::wmemcpy(_S1, _S2, _N); +} + +inline void __cdecl memmove_s(__out_bcount(_S1max) void *_S1, __in size_t _S1max, __in_bcount(_N) const void *_S2, __in size_t _N) +{ + (_S1max); + memmove(_S1, _S2, _N); +} + +inline void __cdecl strcpy_s(__out_ecount_z(_S1max) char *_S1, __in size_t _S1max, __in_z const char *_S2) +{ + (_S1max); + ::strcpy(_S1, _S2); +} + +inline void __cdecl wcscpy_s(__out_ecount_z(_S1max) wchar_t *_S1, __in size_t _S1max, __in_z const wchar_t *_S2) +{ + (_S1max); + ::wcscpy(_S1, _S2); +} + +inline void __cdecl tcscpy_s(__out_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) +{ + (_SizeInChars); +#ifndef _ATL_MIN_CRT + ::_tcscpy(_Dst, _Src); +#else +#ifdef UNICODE + ::wcscpy(_Dst, _Src); +#else + ::strcpy(_Dst, _Src); +#endif +#endif +} + +/* ensure that strncpy_s null-terminate the dest string */ +inline errno_t __cdecl strncpy_s(__out_ecount_z(_SizeInChars) char *_Dest, __in size_t _SizeInChars, __in_z const char *_Source,__in size_t _Count) +{ + if (_Count == _TRUNCATE) + { + _Count = _SizeInChars - 1; + } + while (_Count > 0 && *_Source != 0) + { + *_Dest++ = *_Source++; + --_Count; + } + *_Dest = 0; + + return (*_Source!=0) ? STRUNCATE : 0; +} + +inline errno_t __cdecl wcsncpy_s(__out_ecount_z(_SizeInChars) wchar_t *_Dest, __in size_t _SizeInChars, __in_z const wchar_t *_Source, __in size_t _Count) +{ + if (_Count == _TRUNCATE) + { + _Count = _SizeInChars - 1; + } + while (_Count > 0 && *_Source != 0) + { + *_Dest++ = *_Source++; + --_Count; + } + *_Dest = 0; + + return (*_Source!=0) ? STRUNCATE : 0; +} + +inline errno_t __cdecl tcsncpy_s(__out_ecount_z(_SizeInChars) TCHAR *_Dest, __in size_t _SizeInChars, __in_z const TCHAR *_Source,__in size_t _Count) +{ + if (_Count == _TRUNCATE) + { + if(_SizeInChars>0) + { + _Count = _SizeInChars - 1; + } + else + { + _Count =0; + } + } + +#ifndef _ATL_MIN_CRT +#pragma warning(push) +#pragma warning(disable: 6535) + ::_tcsncpy(_Dest,_Source,_Count); +#pragma warning(pop) + if(_SizeInChars>0) + { + size_t nulCount = __min(_SizeInChars-1, _Count); + _Dest[nulCount] = 0; + } +#else + while (_Count > 0 && *_Source != 0) + { + *_Dest++ = *_Source++; + --_Count; + } + *_Dest = 0; +#endif + + return (*_Source!=0) ? STRUNCATE : 0; +} + +inline void __cdecl strcat_s(__inout_ecount_z(_SizeInChars) char * _Dst, __in size_t _SizeInChars, __in_z const char * _Src) +{ + (_SizeInChars); + ::strcat(_Dst, _Src); +} + +inline void __cdecl wcscat_s(__inout_ecount_z(_SizeInChars) wchar_t * _Dst, __in size_t _SizeInChars, __in_z const wchar_t * _Src) +{ + (_SizeInChars); + ::wcscat(_Dst, _Src); +} + +inline void __cdecl tcscat_s(__inout_ecount_z(_SizeInChars) TCHAR * _Dst, __in size_t _SizeInChars, __in_z const TCHAR * _Src) +{ + (_SizeInChars); +#ifndef _ATL_MIN_CRT + ::_tcscat(_Dst, _Src); +#else +#ifdef UNICODE + ::wcscat(_Dst, _Src); +#else + ::strcat(_Dst, _Src); +#endif +#endif +} + +inline void __cdecl strlwr_s(__inout_ecount_z(_SizeInChars) char * _Str, size_t _SizeInChars) +{ + (_SizeInChars); + ::_strlwr(_Str); +} + +inline void __cdecl wcslwr_s(__inout_ecount_z(_SizeInChars) wchar_t * _Str, size_t _SizeInChars) +{ + (_SizeInChars); + ::_wcslwr(_Str); +} + +inline void __cdecl mbslwr_s(__inout_bcount_z(_SizeInChars) unsigned char * _Str, size_t _SizeInChars) +{ + (_SizeInChars); + ::_mbslwr(_Str); +} + +inline void __cdecl tcslwr_s(__inout_ecount_z(_SizeInChars) TCHAR * _Str, size_t _SizeInChars) +{ + (_SizeInChars); +#ifndef _ATL_MIN_CRT + ::_tcslwr(_Str); +#else +#ifdef UNICODE + ::_wcslwr(_Str); +#else + ::_strlwr(_Str); +#endif +#endif +} + +inline void __cdecl itoa_s(__in int _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_itoa_s(_Val, _Buf, _SizeInChars, _Radix); +} + +inline void __cdecl itot_s(__in int _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_itot(_Val, _Buf, _Radix); +} + +inline void __cdecl ltoa_s(__in long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ltoa(_Val, _Buf, _Radix); +} + +inline void __cdecl ltot_s(__in long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ltot(_Val, _Buf, _Radix); +} + +inline void __cdecl ultoa_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ultoa(_Val, _Buf, _Radix); +} + +inline void __cdecl ultow_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ultow(_Val, _Buf, _Radix); +} + +inline void __cdecl ultot_s(__in unsigned long _Val, __out_ecount_z(_SizeInChars) TCHAR *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ultot(_Val, _Buf, _Radix); +} + +inline void __cdecl i64toa_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_i64toa(_Val, _Buf, _Radix); +} + +inline void __cdecl i64tow_s(__in __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_i64tow(_Val, _Buf, _Radix); +} + +inline void __cdecl ui64toa_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) char *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ui64toa(_Val, _Buf, _Radix); +} + +inline void __cdecl ui64tow_s(__in unsigned __int64 _Val, __out_ecount_z(_SizeInChars) wchar_t *_Buf, __in size_t _SizeInChars, __in int _Radix) +{ + (_SizeInChars); + ::_ui64tow(_Val, _Buf, _Radix); +} + +inline void __cdecl gcvt_s(__out_ecount_z(_SizeInChars) char *_Buffer, __in size_t _SizeInChars, __in double _Value, __in int _Ndec) +{ + (_SizeInChars); + ::_gcvt(_Value, _Ndec, _Buffer); +} + +inline void __cdecl tsplitpath_s(__in_z const TCHAR *_Path, __out_ecount_z_opt(_Drive_len) TCHAR *_Drive, __in size_t _Drive_len, + __out_ecount_z_opt(_Dir_len) TCHAR *_Dir, __in size_t _Dir_len, + __out_ecount_z_opt(_Fname_ext) TCHAR *_Fname, __in size_t _Fname_len, + __out_ecount_z_opt(_Ext_len) TCHAR *_Ext, __in size_t _Ext_len) +{ + (_Drive_len, _Dir_len, _Fname_len, _Ext_len); + ::_tsplitpath(_Path, _Drive, _Dir, _Fname, _Ext); +} + +inline void __cdecl tmakepath_s(__out_ecount_z(_SizeInChars) TCHAR *_Path, __in size_t _SizeInChars, __in_z const TCHAR *_Drive, + __in_z const TCHAR *_Dir, __in_z const TCHAR *_Fname, __in_z const TCHAR *_Ext) +{ + (_SizeInChars); + ::_tmakepath(_Path, _Drive, _Dir, _Fname, _Ext); +} + +inline size_t __cdecl strnlen(__in_ecount(_Maxsize) const char *_Str, __in size_t _Maxsize) +{ + (_Maxsize); + return ::strlen(_Str); +} + +inline size_t __cdecl wcsnlen(__in_ecount(_Maxsize) const wchar_t *_Wcs, __in size_t _Maxsize) +{ + (_Maxsize); + return ::wcslen(_Wcs); +} + +inline size_t __cdecl tcsnlen(__in_ecount(_Maxsize) const TCHAR *_Str, __in size_t _Maxsize) +{ + (_Maxsize); + return ::_tcslen(_Str); +} + +inline int get_errno() +{ + return errno; +} + +inline void set_errno(__in int _Value) +{ + errno = _Value; +} + +#endif // _SECURE_ATL + +} // namespace Checked + +} // namespace ATL +#pragma warning(pop) +#pragma pack(pop) + +#endif // __ATLCHECKED_H__ + +///////////////////////////////////////////////////////////////////////////// + diff --git a/c/jacob/include/atlcomcli.h b/c/jacob/include/atlcomcli.h new file mode 100644 index 0000000..f0d71cd --- /dev/null +++ b/c/jacob/include/atlcomcli.h @@ -0,0 +1,2874 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLCOMCLI_H__ +#define __ATLCOMCLI_H__ + +#pragma once + +#include +#include +#include + +#pragma warning (push) +#pragma warning (disable: 4127) // conditional expression constant +#pragma warning (disable: 4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions + + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ +///////////////////////////////////////////////////////////////////////////// +// Error to HRESULT helpers + +ATL_NOINLINE inline HRESULT AtlHresultFromLastError() throw() +{ + DWORD dwErr = ::GetLastError(); + return HRESULT_FROM_WIN32(dwErr); +} + +ATL_NOINLINE inline HRESULT AtlHresultFromWin32(__in DWORD nError) throw() +{ + return( HRESULT_FROM_WIN32( nError ) ); +} + +///////////////////////////////////////////////////////////////////////////// +// Smart Pointer helpers + +ATLAPI_(IUnknown*) AtlComPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp); +ATLAPI_(IUnknown*) AtlComQIPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp, REFIID riid); + +#ifndef _ATL_DLL + +ATLINLINE ATLAPI_(IUnknown*) AtlComPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp) +{ + if (pp == NULL) + return NULL; + + if (lp != NULL) + lp->AddRef(); + if (*pp) + (*pp)->Release(); + *pp = lp; + return lp; +} + +ATLINLINE ATLAPI_(IUnknown*) AtlComQIPtrAssign(__deref_out_opt IUnknown** pp, __in_opt IUnknown* lp, REFIID riid) +{ + if (pp == NULL) + return NULL; + + IUnknown* pTemp = *pp; + *pp = NULL; + if (lp != NULL) + lp->QueryInterface(riid, (void**)pp); + if (pTemp) + pTemp->Release(); + return *pp; +} + +#endif // _ATL_DLL + +///////////////////////////////////////////////////////////////////////////// +// COM Smart pointers + +template +class _NoAddRefReleaseOnCComPtr : public T +{ + private: + STDMETHOD_(ULONG, AddRef)()=0; + STDMETHOD_(ULONG, Release)()=0; +}; + +inline __checkReturn HRESULT AtlSetChildSite(__inout IUnknown* punkChild, __in_opt IUnknown* punkParent) +{ + if (punkChild == NULL) + return E_POINTER; + + HRESULT hr; + IObjectWithSite* pChildSite = NULL; + hr = punkChild->QueryInterface(__uuidof(IObjectWithSite), (void**)&pChildSite); + if (SUCCEEDED(hr) && pChildSite != NULL) + { + hr = pChildSite->SetSite(punkParent); + pChildSite->Release(); + } + return hr; +} + + +//CComPtrBase provides the basis for all other smart pointers +//The other smartpointers add their own constructors and operators +template +class CComPtrBase +{ +protected: + CComPtrBase() throw() + { + p = NULL; + } + CComPtrBase(__in int nNull) throw() + { + ATLASSERT(nNull == 0); + (void)nNull; + p = NULL; + } + CComPtrBase(__in_opt T* lp) throw() + { + p = lp; + if (p != NULL) + p->AddRef(); + } +public: + typedef T _PtrClass; + ~CComPtrBase() throw() + { + if (p) + p->Release(); + } + operator T*() const throw() + { + return p; + } + T& operator*() const + { + ATLENSURE(p!=NULL); + return *p; + } + //The assert on operator& usually indicates a bug. If this is really + //what is needed, however, take the address of the p member explicitly. + T** operator&() throw() + { + ATLASSERT(p==NULL); + return &p; + } + _NoAddRefReleaseOnCComPtr* operator->() const throw() + { + ATLASSERT(p!=NULL); + return (_NoAddRefReleaseOnCComPtr*)p; + } + bool operator!() const throw() + { + return (p == NULL); + } + bool operator<(__in_opt T* pT) const throw() + { + return p < pT; + } + bool operator!=(__in_opt T* pT) const + { + return !operator==(pT); + } + bool operator==(__in_opt T* pT) const throw() + { + return p == pT; + } + + // Release the interface and set to NULL + void Release() throw() + { + T* pTemp = p; + if (pTemp) + { + p = NULL; + pTemp->Release(); + } + } + // Compare two objects for equivalence + bool IsEqualObject(__in_opt IUnknown* pOther) throw() + { + if (p == NULL && pOther == NULL) + return true; // They are both NULL objects + + if (p == NULL || pOther == NULL) + return false; // One is NULL the other is not + + CComPtr punk1; + CComPtr punk2; + p->QueryInterface(__uuidof(IUnknown), (void**)&punk1); + pOther->QueryInterface(__uuidof(IUnknown), (void**)&punk2); + return punk1 == punk2; + } + // Attach to an existing interface (does not AddRef) + void Attach(__in T* p2) throw() + { + if (p) + p->Release(); + p = p2; + } + // Detach the interface (does not Release) + T* Detach() throw() + { + T* pt = p; + p = NULL; + return pt; + } + __checkReturn HRESULT CopyTo(__deref_out_opt T** ppT) throw() + { + ATLASSERT(ppT != NULL); + if (ppT == NULL) + return E_POINTER; + *ppT = p; + if (p) + p->AddRef(); + return S_OK; + } + __checkReturn HRESULT SetSite(__in_opt IUnknown* punkParent) throw() + { + return AtlSetChildSite(p, punkParent); + } + __checkReturn HRESULT Advise(__in IUnknown* pUnk, __in const IID& iid, __out LPDWORD pdw) throw() + { + return AtlAdvise(p, pUnk, iid, pdw); + } + __checkReturn HRESULT CoCreateInstance(__in REFCLSID rclsid, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() + { + ATLASSERT(p == NULL); + return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); + } + __checkReturn HRESULT CoCreateInstance(__in LPCOLESTR szProgID, __in_opt LPUNKNOWN pUnkOuter = NULL, __in DWORD dwClsContext = CLSCTX_ALL) throw() + { + CLSID clsid; + HRESULT hr = CLSIDFromProgID(szProgID, &clsid); + ATLASSERT(p == NULL); + if (SUCCEEDED(hr)) + hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); + return hr; + } + template + __checkReturn HRESULT QueryInterface(__deref_out_opt Q** pp) const throw() + { + ATLASSERT(pp != NULL); + return p->QueryInterface(__uuidof(Q), (void**)pp); + } + T* p; +}; + +template +class CComPtr : public CComPtrBase +{ +public: + CComPtr() throw() + { + } + CComPtr(int nNull) throw() : + CComPtrBase(nNull) + { + } + CComPtr(T* lp) throw() : + CComPtrBase(lp) + + { + } + CComPtr(__in const CComPtr& lp) throw() : + CComPtrBase(lp.p) + { + } + T* operator=(__in_opt T* lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); + } + return *this; + } + template + T* operator=(__in const CComPtr& lp) throw() + { + if( !IsEqualObject(lp) ) + { + return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(T))); + } + return *this; + } + T* operator=(__in const CComPtr& lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); + } + return *this; + } +}; + +//specialization for IDispatch +template <> +class CComPtr : public CComPtrBase +{ +public: + CComPtr() throw() + { + } + CComPtr(IDispatch* lp) throw() : + CComPtrBase(lp) + { + } + CComPtr(const CComPtr& lp) throw() : + CComPtrBase(lp.p) + { + } + IDispatch* operator=(IDispatch* lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); + } + return *this; + } + IDispatch* operator=(const CComPtr& lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); + } + return *this; + } + +// IDispatch specific stuff + __checkReturn HRESULT GetPropertyByName(__in LPCOLESTR lpsz, __out VARIANT* pVar) throw() + { + ATLASSERT(p); + ATLASSERT(pVar); + DISPID dwDispID; + HRESULT hr = GetIDOfName(lpsz, &dwDispID); + if (SUCCEEDED(hr)) + hr = GetProperty(dwDispID, pVar); + return hr; + } + __checkReturn HRESULT GetProperty(__in DISPID dwDispID, __out VARIANT* pVar) throw() + { + return GetProperty(p, dwDispID, pVar); + } + __checkReturn HRESULT PutPropertyByName(__in LPCOLESTR lpsz, __in VARIANT* pVar) throw() + { + ATLASSERT(p); + ATLASSERT(pVar); + DISPID dwDispID; + HRESULT hr = GetIDOfName(lpsz, &dwDispID); + if (SUCCEEDED(hr)) + hr = PutProperty(dwDispID, pVar); + return hr; + } + __checkReturn HRESULT PutProperty(__in DISPID dwDispID, __in VARIANT* pVar) throw() + { + return PutProperty(p, dwDispID, pVar); + } + __checkReturn HRESULT GetIDOfName(__in LPCOLESTR lpsz, __out DISPID* pdispid) throw() + { + return p->GetIDsOfNames(IID_NULL, const_cast(&lpsz), 1, LOCALE_USER_DEFAULT, pdispid); + } + // Invoke a method by DISPID with no parameters + __checkReturn HRESULT Invoke0(__in DISPID dispid, __out_opt VARIANT* pvarRet = NULL) throw() + { + DISPPARAMS dispparams = { NULL, NULL, 0, 0}; + return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); + } + // Invoke a method by name with no parameters + __checkReturn HRESULT Invoke0(__in LPCOLESTR lpszName, __out_opt VARIANT* pvarRet = NULL) throw() + { + HRESULT hr; + DISPID dispid; + hr = GetIDOfName(lpszName, &dispid); + if (SUCCEEDED(hr)) + hr = Invoke0(dispid, pvarRet); + return hr; + } + // Invoke a method by DISPID with a single parameter + __checkReturn HRESULT Invoke1(__in DISPID dispid, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() + { + DISPPARAMS dispparams = { pvarParam1, NULL, 1, 0}; + return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); + } + // Invoke a method by name with a single parameter + __checkReturn HRESULT Invoke1(__in LPCOLESTR lpszName, VARIANT* pvarParam1, __out_opt VARIANT* pvarRet = NULL) throw() + { + HRESULT hr; + DISPID dispid; + hr = GetIDOfName(lpszName, &dispid); + if (SUCCEEDED(hr)) + hr = Invoke1(dispid, pvarParam1, pvarRet); + return hr; + } + // Invoke a method by DISPID with two parameters + __checkReturn HRESULT Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw(); + // Invoke a method by name with two parameters + __checkReturn HRESULT Invoke2(__in LPCOLESTR lpszName, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet = NULL) throw() + { + HRESULT hr; + DISPID dispid; + hr = GetIDOfName(lpszName, &dispid); + if (SUCCEEDED(hr)) + hr = Invoke2(dispid, pvarParam1, pvarParam2, pvarRet); + return hr; + } + // Invoke a method by DISPID with N parameters + __checkReturn HRESULT InvokeN(DISPID dispid, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() + { + DISPPARAMS dispparams = { pvarParams, NULL, nParams, 0}; + return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); + } + // Invoke a method by name with Nparameters + __checkReturn HRESULT InvokeN(LPCOLESTR lpszName, VARIANT* pvarParams, int nParams, VARIANT* pvarRet = NULL) throw() + { + HRESULT hr; + DISPID dispid; + hr = GetIDOfName(lpszName, &dispid); + if (SUCCEEDED(hr)) + hr = InvokeN(dispid, pvarParams, nParams, pvarRet); + return hr; + } + static __checkReturn HRESULT PutProperty(__inout IDispatch* p, __in DISPID dwDispID, __in VARIANT* pVar) throw() + { + ATLASSERT(p); + ATLASSERT(pVar != NULL); + if (pVar == NULL) + return E_POINTER; + + if(p == NULL) + return E_INVALIDARG; + + ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::PutProperty\n")); + DISPPARAMS dispparams = {NULL, NULL, 1, 1}; + dispparams.rgvarg = pVar; + DISPID dispidPut = DISPID_PROPERTYPUT; + dispparams.rgdispidNamedArgs = &dispidPut; + + if (pVar->vt == VT_UNKNOWN || pVar->vt == VT_DISPATCH || + (pVar->vt & VT_ARRAY) || (pVar->vt & VT_BYREF)) + { + HRESULT hr = p->Invoke(dwDispID, IID_NULL, + LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, + &dispparams, NULL, NULL, NULL); + if (SUCCEEDED(hr)) + return hr; + } + return p->Invoke(dwDispID, IID_NULL, + LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, + &dispparams, NULL, NULL, NULL); + } + static __checkReturn HRESULT GetProperty(__in IDispatch* p, __in DISPID dwDispID, __out VARIANT* pVar) throw() + { + ATLASSERT(p); + ATLASSERT(pVar != NULL); + if (pVar == NULL) + return E_POINTER; + + if(p == NULL) + return E_INVALIDARG; + + ATLTRACE(atlTraceCOM, 2, _T("CPropertyHelper::GetProperty\n")); + DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0}; + return p->Invoke(dwDispID, IID_NULL, + LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, + &dispparamsNoArgs, pVar, NULL, NULL); + } +}; + +template +class CComQIPtr : public CComPtr +{ +public: + CComQIPtr() throw() + { + } + CComQIPtr(__in T* lp) throw() : + CComPtr(lp) + { + } + CComQIPtr(__in const CComQIPtr& lp) throw() : + CComPtr(lp.p) + { + } + CComQIPtr(__in_opt IUnknown* lp) throw() + { + if (lp != NULL) + lp->QueryInterface(*piid, (void **)&p); + } + T* operator=(__in T* lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp)); + } + return *this; + } + T* operator=(__in const CComQIPtr& lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComPtrAssign((IUnknown**)&p, lp.p)); + } + return *this; + } + T* operator=(__in IUnknown* lp) throw() + { + if(*this!=lp) + { + return static_cast(AtlComQIPtrAssign((IUnknown**)&p, lp, *piid)); + } + return *this; + } +}; + +//Specialization to make it work +template<> +class CComQIPtr : public CComPtr +{ +public: + CComQIPtr() throw() + { + } + CComQIPtr(__in IUnknown* lp) throw() + { + //Actually do a QI to get identity + if (lp != NULL) + lp->QueryInterface(__uuidof(IUnknown), (void **)&p); + } + CComQIPtr(__in const CComQIPtr& lp) throw() : + CComPtr(lp.p) + { + } + IUnknown* operator=(__in IUnknown* lp) throw() + { + if(*this!=lp) + { + //Actually do a QI to get identity + return AtlComQIPtrAssign((IUnknown**)&p, lp, __uuidof(IUnknown)); + } + return *this; + } + + IUnknown* operator=(__in const CComQIPtr& lp) throw() + { + if(*this!=lp) + { + return AtlComPtrAssign((IUnknown**)&p, lp.p); + } + return *this; + } +}; + +typedef CComQIPtr CComDispatchDriver; + +#define com_cast ATL::CComQIPtr +#ifndef _ATL_STREAM_MAX_SIZE +#define _ATL_STREAM_MAX_SIZE 0x100000 +#endif + + +///////////////////////////////////////////////////////////////////////////// +// CComBSTR + +class CComBSTR +{ +public: + BSTR m_str; + + CComBSTR() throw() + { + m_str = NULL; + } + + CComBSTR(__in int nSize) + { + if (nSize == 0) + m_str = NULL; + else + { + m_str = ::SysAllocStringLen(NULL, nSize); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + } + + CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCOLESTR sz) + { + if (nSize == 0) + { + m_str = NULL; + } + else + { + m_str = ::SysAllocStringLen(sz, nSize); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + } + + CComBSTR(__in_opt LPCOLESTR pSrc) + { + if (pSrc == NULL) + { + m_str = NULL; + } + else + { + m_str = ::SysAllocString(pSrc); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + } + + CComBSTR(__in const CComBSTR& src) + { + m_str = src.Copy(); + if (!!src && !*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + + CComBSTR(__in REFGUID guid) + { + OLECHAR szGUID[64]; + ::StringFromGUID2(guid, szGUID, 64); + m_str = ::SysAllocString(szGUID); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + + CComBSTR& operator=(__in const CComBSTR& src) + { + if (m_str != src.m_str) + { + ::SysFreeString(m_str); + m_str = src.Copy(); + if (!!src && !*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + return *this; + } + + CComBSTR& operator=(__in_opt LPCOLESTR pSrc) + { + if (pSrc != m_str) + { + ::SysFreeString(m_str); + if (pSrc != NULL) + { + m_str = ::SysAllocString(pSrc); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + else + { + m_str = NULL; + } + } + return *this; + } + + ~CComBSTR() throw(); + + unsigned int Length() const throw() + { + return ::SysStringLen(m_str); + } + + unsigned int ByteLength() const throw() + { + return ::SysStringByteLen(m_str); + } + + operator BSTR() const throw() + { + return m_str; + } + + +#ifndef ATL_CCOMBSTR_ADDRESS_OF_ASSERT +// Temp disable CComBSTR::operator& Assert +#define ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT +#endif + + + BSTR* operator&() throw() + { +#ifndef ATL_NO_CCOMBSTR_ADDRESS_OF_ASSERT +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "We are deliberately checking if this has already been allocated") + ATLASSERT(!*this); +#pragma prefast(pop) +#pragma warning(pop) +#endif + return &m_str; + } + + BSTR Copy() const throw() + { + if (!*this) + { + return NULL; + } + return ::SysAllocStringByteLen((char*)m_str, ::SysStringByteLen(m_str)); + } + + __checkReturn HRESULT CopyTo(__inout_opt BSTR* pbstr) throw() + { + ATLASSERT(pbstr != NULL); + if (pbstr == NULL) + { + return E_POINTER; + } + *pbstr = Copy(); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "We are checking allocation semantics here") + if ((*pbstr == NULL) && (m_str != NULL)) + { + return E_OUTOFMEMORY; + } +#pragma prefast(pop) +#pragma warning(pop) + return S_OK; + } + + // copy BSTR to VARIANT + __checkReturn HRESULT CopyTo(__out_opt VARIANT *pvarDest) throw() + { + ATLASSERT(pvarDest != NULL); + HRESULT hRes = E_POINTER; + if (pvarDest != NULL) + { + pvarDest->vt = VT_BSTR; + pvarDest->bstrVal = Copy(); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "We are checking allocation semantics here") + if (pvarDest->bstrVal == NULL && m_str != NULL) + { + hRes = E_OUTOFMEMORY; + } +#pragma prefast(pop) +#pragma warning(pop) + else + { + hRes = S_OK; + } + } + return hRes; + } + + void Attach(__in BSTR src) throw() + { + if (m_str != src) + { + ::SysFreeString(m_str); + m_str = src; + } + } + + BSTR Detach() throw() + { + BSTR s = m_str; + m_str = NULL; + return s; + } + + void Empty() throw() + { + ::SysFreeString(m_str); + m_str = NULL; + } + + bool operator!() const throw() + { +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + return (m_str == NULL); +#pragma prefast(pop) +#pragma warning(pop) + } + + __checkReturn HRESULT Append(__in const CComBSTR& bstrSrc) throw() + { + return AppendBSTR(bstrSrc.m_str); + } + + __checkReturn HRESULT Append(__in_opt LPCOLESTR lpsz) throw() + { + return Append(lpsz, UINT(ocslen(lpsz))); + } + + // a BSTR is just a LPCOLESTR so we need a special version to signify + // that we are appending a BSTR + __checkReturn HRESULT AppendBSTR(__in_opt BSTR p) throw() + { + if (::SysStringLen(p) == 0) + { + return S_OK; + } + BSTR bstrNew = NULL; + HRESULT hr; + hr = VarBstrCat(m_str, p, &bstrNew); + if (SUCCEEDED(hr)) + { + ::SysFreeString(m_str); + m_str = bstrNew; + } + return hr; + } + + __checkReturn HRESULT Append(__in_ecount_opt(nLen) LPCOLESTR lpsz, __in int nLen) throw() + { +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + if (lpsz == NULL || (m_str != NULL && nLen == 0)) +#pragma prefast(pop) +#pragma warning(pop) + return S_OK; + int n1 = Length(); + if (n1+nLen < n1) + return E_OUTOFMEMORY; + BSTR b; + b = ::SysAllocStringLen(NULL, n1+nLen); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + if (b == NULL) +#pragma prefast(pop) +#pragma warning(pop) + return E_OUTOFMEMORY; + if(::SysStringLen(m_str) > 0) + { + Checked::memcpy_s(b, (n1+nLen)*sizeof(OLECHAR), m_str, n1*sizeof(OLECHAR)); + } + Checked::memcpy_s(b+n1, nLen*sizeof(OLECHAR), lpsz, nLen*sizeof(OLECHAR)); + b[n1+nLen] = NULL; + SysFreeString(m_str); + m_str = b; + return S_OK; + } + + __checkReturn HRESULT Append(__in char ch) throw() + { + OLECHAR chO = ch; + + return( Append( &chO, 1 ) ); + } + + __checkReturn HRESULT Append(__in wchar_t ch) throw() + { + return( Append( &ch, 1 ) ); + } + + __checkReturn HRESULT AppendBytes(__in_ecount_opt(nLen) const char* lpsz, __in int nLen) throw() + { + if (lpsz == NULL || nLen == 0) + return S_OK; + int n1 = ByteLength(); + if (n1+nLen < n1) + return E_OUTOFMEMORY; + BSTR b; + b = ::SysAllocStringByteLen(NULL, n1+nLen); + if (b == NULL) + { + return E_OUTOFMEMORY; + } + Checked::memcpy_s(b, n1+nLen, m_str, n1); + Checked::memcpy_s(((char*)b)+n1, nLen, lpsz, nLen); + *((OLECHAR*)(((char*)b)+n1+nLen)) = NULL; + SysFreeString(m_str); + m_str = b; + return S_OK; + } + + __checkReturn HRESULT AssignBSTR(const BSTR bstrSrc) throw() + { + HRESULT hr = S_OK; + if (m_str != bstrSrc) + { + ::SysFreeString(m_str); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + if (bstrSrc != NULL) +#pragma prefast(pop) +#pragma warning(pop) + { + m_str = ::SysAllocStringByteLen((char*)bstrSrc, ::SysStringByteLen(bstrSrc)); + if (!*this) + { + hr = E_OUTOFMEMORY; + } + } + else + { + m_str = NULL; + } + } + + return hr; + } + + __checkReturn HRESULT ToLower() throw() + { + if (::SysStringLen(m_str) > 0) + { +#ifdef _UNICODE + // Convert in place + CharLowerBuff(m_str, Length()); +#else + // Cannot use conversion macros due to possible embedded NULLs + UINT _acp = _AtlGetConversionACP(); + int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); + CTempBuffer pszA; + ATLTRY(pszA.Allocate(_convert)); + if (pszA == NULL) + return E_OUTOFMEMORY; + + int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); + if (nRet == 0) + { + ATLASSERT(0); + return AtlHresultFromLastError(); + } + + CharLowerBuff(pszA, nRet); + + _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); + + CTempBuffer pszW; + ATLTRY(pszW.Allocate(_convert)); + if (pszW == NULL) + return E_OUTOFMEMORY; + + nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); + if (nRet <= 0) + { + ATLASSERT(0); + return AtlHresultFromLastError(); + } + + UINT nBytes=0; + HRESULT hr=S_OK; + if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) + { + return hr; + } + BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); + if (b == NULL) + return E_OUTOFMEMORY; + SysFreeString(m_str); + m_str = b; +#endif + } + return S_OK; + } + __checkReturn HRESULT ToUpper() throw() + { + if (::SysStringLen(m_str) > 0) + { +#ifdef _UNICODE + // Convert in place + CharUpperBuff(m_str, Length()); +#else + // Cannot use conversion macros due to possible embedded NULLs + UINT _acp = _AtlGetConversionACP(); + int _convert = WideCharToMultiByte(_acp, 0, m_str, Length(), NULL, 0, NULL, NULL); + CTempBuffer pszA; + ATLTRY(pszA.Allocate(_convert)); + if (pszA == NULL) + return E_OUTOFMEMORY; + + int nRet = WideCharToMultiByte(_acp, 0, m_str, Length(), pszA, _convert, NULL, NULL); + if (nRet == 0) + { + ATLASSERT(0); + return AtlHresultFromLastError(); + } + + CharUpperBuff(pszA, nRet); + + _convert = MultiByteToWideChar(_acp, 0, pszA, nRet, NULL, 0); + + CTempBuffer pszW; + ATLTRY(pszW.Allocate(_convert)); + if (pszW == NULL) + return E_OUTOFMEMORY; + + nRet = MultiByteToWideChar(_acp, 0, pszA, nRet, pszW, _convert); + if (nRet <= 0) + { + ATLASSERT(0); + return AtlHresultFromLastError(); + } + + UINT nBytes=0; + HRESULT hr=S_OK; + if( FAILED(hr=::ATL::AtlMultiply(&nBytes, static_cast(nRet), static_cast(sizeof(OLECHAR))))) + { + return hr; + } + BSTR b = ::SysAllocStringByteLen((LPCSTR) (LPWSTR) pszW, nBytes); + if (b == NULL) + return E_OUTOFMEMORY; + SysFreeString(m_str); + m_str = b; +#endif + } + return S_OK; + } + + bool LoadString(__in HINSTANCE hInst, __in UINT nID) throw() + { + ::SysFreeString(m_str); + m_str = NULL; + return LoadStringResource(hInst, nID, m_str); + } + + bool LoadString(__in UINT nID) throw() + { + ::SysFreeString(m_str); + m_str = NULL; + return LoadStringResource(nID, m_str); + } + + CComBSTR& operator+=(__in const CComBSTR& bstrSrc) + { + HRESULT hr; + hr = AppendBSTR(bstrSrc.m_str); + if (FAILED(hr)) + AtlThrow(hr); + return *this; + } + + CComBSTR& operator+=(__in_opt LPCOLESTR pszSrc) + { + HRESULT hr; + hr = Append(pszSrc); + if (FAILED(hr)) + AtlThrow(hr); + return *this; + } + + bool operator<(const CComBSTR& bstrSrc) const throw() + { + return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_LT); + } + bool operator<(__in_z LPCOLESTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator<(bstr2); + } + bool operator<(__in_z LPOLESTR pszSrc) const + { + return operator<((LPCOLESTR)pszSrc); + } + + bool operator>(const CComBSTR& bstrSrc) const throw() + { + return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_GT); + } + bool operator>(__in_z LPCOLESTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator>(bstr2); + } + bool operator>(__in_z LPOLESTR pszSrc) const + { + return operator>((LPCOLESTR)pszSrc); + } + + bool operator!=(const CComBSTR& bstrSrc) const throw() + { + return !operator==(bstrSrc); + } + bool operator!=(__in_z LPCOLESTR pszSrc) const + { + return !operator==(pszSrc); + } + bool operator!=(int nNull) const throw() + { + return !operator==(nNull); + } + bool operator!=(__in_z LPOLESTR pszSrc) const + { + return operator!=((LPCOLESTR)pszSrc); + } + + bool operator==(const CComBSTR& bstrSrc) const throw() + { + return VarBstrCmp(m_str, bstrSrc.m_str, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); + } + bool operator==(__in_z LPCOLESTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator==(bstr2); + } + bool operator==(__in_z LPOLESTR pszSrc) const + { + return operator==((LPCOLESTR)pszSrc); + } + + bool operator==(int nNull) const throw() + { + ATLASSERT(nNull == NULL); + (void)nNull; + return (!*this); + } + + CComBSTR(__in LPCSTR pSrc) + { + if (pSrc != NULL) + { + m_str = A2WBSTR(pSrc); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + } + else + { + m_str = NULL; + } + } + + CComBSTR(__in int nSize, __in_ecount_opt(nSize) LPCSTR sz) + { + if (nSize != 0 && sz == NULL) + { + m_str = ::SysAllocStringLen(NULL, nSize); + if (!*this) + { + AtlThrow(E_OUTOFMEMORY); + } + return; + } + + m_str = A2WBSTR(sz, nSize); + if (!*this && nSize != 0) + { + AtlThrow(E_OUTOFMEMORY); + } + } + + __checkReturn HRESULT Append(__in LPCSTR lpsz) throw() + { + if (lpsz == NULL) + return S_OK; + + CComBSTR bstrTemp; + ATLTRY(bstrTemp = lpsz); + if (!bstrTemp) + { + return E_OUTOFMEMORY; + } + return Append(bstrTemp); + } + + CComBSTR& operator=(__in LPCSTR pSrc) + { + ::SysFreeString(m_str); + m_str = A2WBSTR(pSrc); + if (!*this && pSrc != NULL) + { + AtlThrow(E_OUTOFMEMORY); + } + return *this; + } + + bool operator<(__in_z LPCSTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator<(bstr2); + } + bool operator>(__in_z LPCSTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator>(bstr2); + } + bool operator!=(__in_z LPCSTR pszSrc) const + { + return !operator==(pszSrc); + } + bool operator==(__in_z LPCSTR pszSrc) const + { + CComBSTR bstr2(pszSrc); + return operator==(bstr2); + } + + __checkReturn HRESULT WriteToStream(__inout IStream* pStream) throw() + { + ATLASSERT(pStream != NULL); + if(pStream == NULL) + return E_INVALIDARG; + + ULONG cb; + ULONG cbStrLen = CComBSTR::GetStreamSize(m_str) - sizeof(ULONG); + HRESULT hr = pStream->Write((void*) &cbStrLen, sizeof(cbStrLen), &cb); + if (FAILED(hr)) + return hr; + return cbStrLen ? pStream->Write((void*) m_str, cbStrLen, &cb) : S_OK; + } + + __checkReturn HRESULT ReadFromStream(__inout IStream* pStream) throw() + { + ATLASSERT(pStream != NULL); + if(pStream == NULL) + { + return E_INVALIDARG; + } + + ATLASSERT(!*this); // should be empty + Empty(); + + HRESULT hrSeek; + ULARGE_INTEGER nBegOffset; + { + LARGE_INTEGER nZeroOffset; + nZeroOffset.QuadPart = 0L; + hrSeek = pStream->Seek(nZeroOffset, STREAM_SEEK_CUR, &nBegOffset); + } + + ULONG cbRead = 0; + ULONG cbStrLen = 0; + HRESULT hr = pStream->Read(reinterpret_cast(&cbStrLen), sizeof(cbStrLen), &cbRead); + + if (SUCCEEDED(hr)) + { + // invalid data sizes + if (sizeof(cbStrLen) != cbRead) + { + ATLTRACE(atlTraceCOM, 0, _T("Input stream is corrupted.")); + hr = E_FAIL; + } + // check for NULL bstr + else if (cbStrLen == 0) + { + } + // security checks when system hang for huge stream of data + else if (cbStrLen > _ATL_STREAM_MAX_SIZE) + { + ATLTRACE(atlTraceCOM, 0, _T("String exceeded the maximum allowed size see _ATL_STREAM_MAX_SIZE.")); + hr = E_ACCESSDENIED; + } + else + { + //subtract size for terminating NULL which we wrote out + cbStrLen -= sizeof(OLECHAR); + + m_str = ::SysAllocStringByteLen(NULL, cbStrLen); + if (!*this) + { + hr = E_OUTOFMEMORY; + } + else + { + hr = pStream->Read(reinterpret_cast(m_str), cbStrLen, &cbRead); + + if (SUCCEEDED(hr)) + { + if (cbRead != cbStrLen) + { + ATLTRACE(atlTraceCOM, 0, _T("Length of string data is different than expected.")); + hr = E_FAIL; + } + else + { + OLECHAR ch; + hr = pStream->Read(reinterpret_cast(&ch), sizeof(OLECHAR), &cbRead); + + if (SUCCEEDED(hr)) + { + if (cbRead != sizeof(OLECHAR)) + { + ATLTRACE(atlTraceCOM, 0, _T("Cannot read NULL terminator from stream.")); + hr = E_FAIL; + } + else + { + //check if string is properly terminated with NULL + ATLASSERT(ch == L'\0'); + } + } + } + } + + if (FAILED(hr)) + { + ::SysFreeString(m_str); + m_str = NULL; + } + } + } + } + + // If SysAllocStringByteLen or IStream::Read failed, reset seek + // pointer to start of BSTR size. + if (FAILED(hr) && SUCCEEDED(hrSeek)) + { + LARGE_INTEGER nOffset; + nOffset.QuadPart = static_cast(nBegOffset.QuadPart); + pStream->Seek(nOffset, STREAM_SEEK_SET, NULL); + } + + return hr; + } + + static bool LoadStringResource(__in HINSTANCE hInstance, __in UINT uID, __deref_out_opt BSTR& bstrText) throw() + { + const ATLSTRINGRESOURCEIMAGE* pImage; + +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + ATLASSERT(bstrText == NULL); +#pragma prefast(pop) +#pragma warning(pop) + + pImage = AtlGetStringResourceImage(hInstance, uID); + if (pImage != NULL) + { + bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); + } +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + return (bstrText != NULL) ? true : false; +#pragma prefast(pop) +#pragma warning(pop) + } + + static bool LoadStringResource(__in UINT uID, __deref_out_opt BSTR& bstrText) throw() + { + const ATLSTRINGRESOURCEIMAGE* pImage; + +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + ATLASSERT(bstrText == NULL); +#pragma prefast(pop) +#pragma warning(pop) + + pImage = AtlGetStringResourceImage(uID); + if (pImage != NULL) + { + bstrText = ::SysAllocStringLen(pImage->achString, pImage->nLength); + } + +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + return (bstrText != NULL) ? true : false; +#pragma prefast(pop) +#pragma warning(pop) + } + + // each character in BSTR is copied to each element in SAFEARRAY + __success(return>=0) HRESULT BSTRToArray(__deref_out LPSAFEARRAY *ppArray) throw() + { + return VectorFromBstr(m_str, ppArray); + } + + // first character of each element in SAFEARRAY is copied to BSTR + __checkReturn HRESULT ArrayToBSTR(__in const SAFEARRAY *pSrc) throw() + { + ::SysFreeString(m_str); + return BstrFromVector((LPSAFEARRAY)pSrc, &m_str); + } + static ULONG GetStreamSize(BSTR bstr) + { + ULONG ulSize=sizeof(ULONG); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + if (bstr != NULL) +#pragma prefast(pop) +#pragma warning(pop) + { + ulSize += SysStringByteLen(bstr) + sizeof(OLECHAR); + } + return ulSize; + } +}; + +inline CComBSTR::~CComBSTR() throw() + { + ::SysFreeString(m_str); + } + +inline void SysFreeStringHelper(__in CComBSTR& bstr) +{ + bstr.Empty(); +} + +inline void SysFreeStringHelper(BSTR bstr) +{ + ::SysFreeString(bstr); +} + +inline __checkReturn HRESULT SysAllocStringHelper(__out_opt CComBSTR& bstrDest,BSTR bstrSrc) +{ + bstrDest=bstrSrc; + return !bstrDest ? E_OUTOFMEMORY : S_OK; +} + +inline __checkReturn HRESULT SysAllocStringHelper(__out_opt BSTR& bstrDest,BSTR bstrSrc) +{ + bstrDest=::SysAllocString(bstrSrc); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "The semantics of this function are about allocation, not content") + return bstrDest==NULL ? E_OUTOFMEMORY : S_OK; +#pragma prefast(pop) +#pragma warning(pop) +} + +///////////////////////////////////////////////////////////// +// Class to Adapt CComBSTR and CComPtr for use with STL containers +// the syntax to use it is +// std::vector< CAdapt > vect; + +template +class CAdapt +{ +public: + CAdapt() + { + } + CAdapt(__in const T& rSrc) : + m_T( rSrc ) + { + } + + CAdapt(__in const CAdapt& rSrCA) : + m_T( rSrCA.m_T ) + { + } + + CAdapt& operator=(__in const T& rSrc) + { + m_T = rSrc; + return *this; + } + bool operator<(__in const T& rSrc) const + { + return m_T < rSrc; + } + bool operator==(__in const T& rSrc) const + { + return m_T == rSrc; + } + operator T&() + { + return m_T; + } + + operator const T&() const + { + return m_T; + } + + T m_T; +}; + +///////////////////////////////////////////////////////////////////////////// +// CComVariant + + +#define ATL_VARIANT_TRUE VARIANT_BOOL( -1 ) +#define ATL_VARIANT_FALSE VARIANT_BOOL( 0 ) + +template< typename T > +class CVarTypeInfo +{ +// static const VARTYPE VT; // VARTYPE corresponding to type T +// static T VARIANT::* const pmField; // Pointer-to-member of corresponding field in VARIANT struct +}; + +template<> +class CVarTypeInfo< char > +{ +public: + static const VARTYPE VT = VT_I1; + static char VARIANT::* const pmField; +}; + +__declspec( selectany ) char VARIANT::* const CVarTypeInfo< char >::pmField = &VARIANT::cVal; + +template<> +class CVarTypeInfo< unsigned char > +{ +public: + static const VARTYPE VT = VT_UI1; + static unsigned char VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned char VARIANT::* const CVarTypeInfo< unsigned char >::pmField = &VARIANT::bVal; + +template<> +class CVarTypeInfo< char* > +{ +public: + static const VARTYPE VT = VT_I1|VT_BYREF; + static char* VARIANT::* const pmField; +}; + +__declspec( selectany ) char* VARIANT::* const CVarTypeInfo< char* >::pmField = &VARIANT::pcVal; + +template<> +class CVarTypeInfo< unsigned char* > +{ +public: + static const VARTYPE VT = VT_UI1|VT_BYREF; + static unsigned char* VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned char* VARIANT::* const CVarTypeInfo< unsigned char* >::pmField = &VARIANT::pbVal; + +template<> +class CVarTypeInfo< short > +{ +public: + static const VARTYPE VT = VT_I2; + static short VARIANT::* const pmField; +}; + +__declspec( selectany ) short VARIANT::* const CVarTypeInfo< short >::pmField = &VARIANT::iVal; + +template<> +class CVarTypeInfo< short* > +{ +public: + static const VARTYPE VT = VT_I2|VT_BYREF; + static short* VARIANT::* const pmField; +}; + +__declspec( selectany ) short* VARIANT::* const CVarTypeInfo< short* >::pmField = &VARIANT::piVal; + +template<> +class CVarTypeInfo< unsigned short > +{ +public: + static const VARTYPE VT = VT_UI2; + static unsigned short VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned short VARIANT::* const CVarTypeInfo< unsigned short >::pmField = &VARIANT::uiVal; + +#ifdef _NATIVE_WCHAR_T_DEFINED // Only treat unsigned short* as VT_UI2|VT_BYREF if BSTR isn't the same as unsigned short* +template<> +class CVarTypeInfo< unsigned short* > +{ +public: + static const VARTYPE VT = VT_UI2|VT_BYREF; + static unsigned short* VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned short* VARIANT::* const CVarTypeInfo< unsigned short* >::pmField = &VARIANT::puiVal; +#endif // _NATIVE_WCHAR_T_DEFINED + +template<> +class CVarTypeInfo< int > +{ +public: + static const VARTYPE VT = VT_I4; + static int VARIANT::* const pmField; +}; + +__declspec( selectany ) int VARIANT::* const CVarTypeInfo< int >::pmField = &VARIANT::intVal; + +template<> +class CVarTypeInfo< int* > +{ +public: + static const VARTYPE VT = VT_I4|VT_BYREF; + static int* VARIANT::* const pmField; +}; + +__declspec( selectany ) int* VARIANT::* const CVarTypeInfo< int* >::pmField = &VARIANT::pintVal; + +template<> +class CVarTypeInfo< unsigned int > +{ +public: + static const VARTYPE VT = VT_UI4; + static unsigned int VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned int VARIANT::* const CVarTypeInfo< unsigned int >::pmField = &VARIANT::uintVal; + +template<> +class CVarTypeInfo< unsigned int* > +{ +public: + static const VARTYPE VT = VT_UI4|VT_BYREF; + static unsigned int* VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned int* VARIANT::* const CVarTypeInfo< unsigned int* >::pmField = &VARIANT::puintVal; + +template<> +class CVarTypeInfo< long > +{ +public: + static const VARTYPE VT = VT_I4; + static long VARIANT::* const pmField; +}; + +__declspec( selectany ) long VARIANT::* const CVarTypeInfo< long >::pmField = &VARIANT::lVal; + +template<> +class CVarTypeInfo< long* > +{ +public: + static const VARTYPE VT = VT_I4|VT_BYREF; + static long* VARIANT::* const pmField; +}; + +__declspec( selectany ) long* VARIANT::* const CVarTypeInfo< long* >::pmField = &VARIANT::plVal; + +template<> +class CVarTypeInfo< unsigned long > +{ +public: + static const VARTYPE VT = VT_UI4; + static unsigned long VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned long VARIANT::* const CVarTypeInfo< unsigned long >::pmField = &VARIANT::ulVal; + +template<> +class CVarTypeInfo< unsigned long* > +{ +public: + static const VARTYPE VT = VT_UI4|VT_BYREF; + static unsigned long* VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned long* VARIANT::* const CVarTypeInfo< unsigned long* >::pmField = &VARIANT::pulVal; + +template<> +class CVarTypeInfo< __int64 > +{ +public: + static const VARTYPE VT = VT_I8; + static __int64 VARIANT::* const pmField; +}; + +__declspec( selectany ) __int64 VARIANT::* const CVarTypeInfo< __int64 >::pmField = &VARIANT::llVal; + +template<> +class CVarTypeInfo< __int64* > +{ +public: + static const VARTYPE VT = VT_I8|VT_BYREF; + static __int64* VARIANT::* const pmField; +}; + +__declspec( selectany ) __int64* VARIANT::* const CVarTypeInfo< __int64* >::pmField = &VARIANT::pllVal; + +template<> +class CVarTypeInfo< unsigned __int64 > +{ +public: + static const VARTYPE VT = VT_UI8; + static unsigned __int64 VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned __int64 VARIANT::* const CVarTypeInfo< unsigned __int64 >::pmField = &VARIANT::ullVal; + +template<> +class CVarTypeInfo< unsigned __int64* > +{ +public: + static const VARTYPE VT = VT_UI8|VT_BYREF; + static unsigned __int64* VARIANT::* const pmField; +}; + +__declspec( selectany ) unsigned __int64* VARIANT::* const CVarTypeInfo< unsigned __int64* >::pmField = &VARIANT::pullVal; + +template<> +class CVarTypeInfo< float > +{ +public: + static const VARTYPE VT = VT_R4; + static float VARIANT::* const pmField; +}; + +__declspec( selectany ) float VARIANT::* const CVarTypeInfo< float >::pmField = &VARIANT::fltVal; + +template<> +class CVarTypeInfo< float* > +{ +public: + static const VARTYPE VT = VT_R4|VT_BYREF; + static float* VARIANT::* const pmField; +}; + +__declspec( selectany ) float* VARIANT::* const CVarTypeInfo< float* >::pmField = &VARIANT::pfltVal; + +template<> +class CVarTypeInfo< double > +{ +public: + static const VARTYPE VT = VT_R8; + static double VARIANT::* const pmField; +}; + +__declspec( selectany ) double VARIANT::* const CVarTypeInfo< double >::pmField = &VARIANT::dblVal; + +template<> +class CVarTypeInfo< double* > +{ +public: + static const VARTYPE VT = VT_R8|VT_BYREF; + static double* VARIANT::* const pmField; +}; + +__declspec( selectany ) double* VARIANT::* const CVarTypeInfo< double* >::pmField = &VARIANT::pdblVal; + +template<> +class CVarTypeInfo< VARIANT > +{ +public: + static const VARTYPE VT = VT_VARIANT; +}; + +template<> +class CVarTypeInfo< BSTR > +{ +public: + static const VARTYPE VT = VT_BSTR; + static BSTR VARIANT::* const pmField; +}; + +__declspec( selectany ) BSTR VARIANT::* const CVarTypeInfo< BSTR >::pmField = &VARIANT::bstrVal; + +template<> +class CVarTypeInfo< BSTR* > +{ +public: + static const VARTYPE VT = VT_BSTR|VT_BYREF; + static BSTR* VARIANT::* const pmField; +}; + +__declspec( selectany ) BSTR* VARIANT::* const CVarTypeInfo< BSTR* >::pmField = &VARIANT::pbstrVal; + +template<> +class CVarTypeInfo< IUnknown* > +{ +public: + static const VARTYPE VT = VT_UNKNOWN; + static IUnknown* VARIANT::* const pmField; +}; + +__declspec( selectany ) IUnknown* VARIANT::* const CVarTypeInfo< IUnknown* >::pmField = &VARIANT::punkVal; + +template<> +class CVarTypeInfo< IUnknown** > +{ +public: + static const VARTYPE VT = VT_UNKNOWN|VT_BYREF; + static IUnknown** VARIANT::* const pmField; +}; + +__declspec( selectany ) IUnknown** VARIANT::* const CVarTypeInfo< IUnknown** >::pmField = &VARIANT::ppunkVal; + +template<> +class CVarTypeInfo< IDispatch* > +{ +public: + static const VARTYPE VT = VT_DISPATCH; + static IDispatch* VARIANT::* const pmField; +}; + +__declspec( selectany ) IDispatch* VARIANT::* const CVarTypeInfo< IDispatch* >::pmField = &VARIANT::pdispVal; + +template<> +class CVarTypeInfo< IDispatch** > +{ +public: + static const VARTYPE VT = VT_DISPATCH|VT_BYREF; + static IDispatch** VARIANT::* const pmField; +}; + +__declspec( selectany ) IDispatch** VARIANT::* const CVarTypeInfo< IDispatch** >::pmField = &VARIANT::ppdispVal; + +template<> +class CVarTypeInfo< CY > +{ +public: + static const VARTYPE VT = VT_CY; + static CY VARIANT::* const pmField; +}; + +__declspec( selectany ) CY VARIANT::* const CVarTypeInfo< CY >::pmField = &VARIANT::cyVal; + +template<> +class CVarTypeInfo< CY* > +{ +public: + static const VARTYPE VT = VT_CY|VT_BYREF; + static CY* VARIANT::* const pmField; +}; + +__declspec( selectany ) CY* VARIANT::* const CVarTypeInfo< CY* >::pmField = &VARIANT::pcyVal; + +class CComVariant : public tagVARIANT +{ +// Constructors +public: + CComVariant() throw() + { + ::VariantInit(this); + } + ~CComVariant() throw() + { + Clear(); + } + + CComVariant(__in const VARIANT& varSrc) + { + vt = VT_EMPTY; + InternalCopy(&varSrc); + } + + CComVariant(__in const CComVariant& varSrc) + { + vt = VT_EMPTY; + InternalCopy(&varSrc); + } + CComVariant(__in LPCOLESTR lpszSrc) + { + vt = VT_EMPTY; + *this = lpszSrc; + } + + CComVariant(__in LPCSTR lpszSrc) + { + vt = VT_EMPTY; + *this = lpszSrc; + } + + CComVariant(__in bool bSrc) + { + vt = VT_BOOL; + boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; + } + + CComVariant(__in int nSrc, __in VARTYPE vtSrc = VT_I4) throw() + { + ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_INT); + vt = vtSrc; + intVal = nSrc; + } + CComVariant(__in BYTE nSrc) throw() + { + vt = VT_UI1; + bVal = nSrc; + } + CComVariant(__in short nSrc) throw() + { + vt = VT_I2; + iVal = nSrc; + } + CComVariant(__in long nSrc, __in VARTYPE vtSrc = VT_I4) throw() + { + ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR); + vt = vtSrc; + lVal = nSrc; + } + CComVariant(__in float fltSrc) throw() + { + vt = VT_R4; + fltVal = fltSrc; + } + CComVariant(__in double dblSrc, __in VARTYPE vtSrc = VT_R8) throw() + { + ATLASSERT(vtSrc == VT_R8 || vtSrc == VT_DATE); + vt = vtSrc; + dblVal = dblSrc; + } +#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) + CComVariant(__in LONGLONG nSrc) throw() + { + vt = VT_I8; + llVal = nSrc; + } + CComVariant(__in ULONGLONG nSrc) throw() + { + vt = VT_UI8; + ullVal = nSrc; + } +#endif + CComVariant(CY __in cySrc) throw() + { + vt = VT_CY; + cyVal.Hi = cySrc.Hi; + cyVal.Lo = cySrc.Lo; + } + CComVariant(__in_opt IDispatch* pSrc) throw() + { + vt = VT_DISPATCH; + pdispVal = pSrc; + // Need to AddRef as VariantClear will Release + if (pdispVal != NULL) + pdispVal->AddRef(); + } + CComVariant(__in_opt IUnknown* pSrc) throw() + { + vt = VT_UNKNOWN; + punkVal = pSrc; + // Need to AddRef as VariantClear will Release + if (punkVal != NULL) + punkVal->AddRef(); + } + CComVariant(__in char cSrc) throw() + { + vt = VT_I1; + cVal = cSrc; + } + CComVariant(__in unsigned short nSrc) throw() + { + vt = VT_UI2; + uiVal = nSrc; + } + CComVariant(__in unsigned long nSrc) throw() + { + vt = VT_UI4; + ulVal = nSrc; + } + CComVariant(__in unsigned int nSrc, __in VARTYPE vtSrc = VT_UI4) throw() + { + ATLASSERT(vtSrc == VT_UI4 || vtSrc == VT_UINT); + vt = vtSrc; + uintVal= nSrc; + } + CComVariant(__in const CComBSTR& bstrSrc) + { + vt = VT_EMPTY; + *this = bstrSrc; + } + CComVariant(__in_opt const SAFEARRAY *pSrc) + { + LPSAFEARRAY pCopy; + if (pSrc != NULL) + { + HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); + if (SUCCEEDED(hRes) && pCopy != NULL) + { + ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); + vt |= VT_ARRAY; + parray = pCopy; + } + else + { + vt = VT_ERROR; + scode = hRes; +#ifndef _ATL_NO_VARIANT_THROW + ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); +#endif + } + } + else + { + vt = VT_EMPTY; + } + } +// Assignment Operators +public: + CComVariant& operator=(__in const CComVariant& varSrc) + { + if(this!=&varSrc) + { + InternalCopy(&varSrc); + } + return *this; + } + CComVariant& operator=(__in const VARIANT& varSrc) + { + if(static_cast(this)!=&varSrc) + { + InternalCopy(&varSrc); + } + return *this; + } + + CComVariant& operator=(__in const CComBSTR& bstrSrc) + { + Clear(); + vt = VT_BSTR; + bstrVal = bstrSrc.Copy(); +#pragma warning(push) +#pragma warning(disable:4068) +#pragma prefast(push) +#pragma prefast(disable:325, "We are checking allocation semantics here") + if (bstrVal == NULL && bstrSrc.m_str != NULL) + { + vt = VT_ERROR; + scode = E_OUTOFMEMORY; +#ifndef _ATL_NO_VARIANT_THROW + ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); +#endif + } +#pragma prefast(pop) +#pragma warning(pop) + return *this; + } + + CComVariant& operator=(__in LPCOLESTR lpszSrc) + { + Clear(); + vt = VT_BSTR; + bstrVal = ::SysAllocString(lpszSrc); + + if (bstrVal == NULL && lpszSrc != NULL) + { + vt = VT_ERROR; + scode = E_OUTOFMEMORY; +#ifndef _ATL_NO_VARIANT_THROW + ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); +#endif + + } + return *this; + } + + CComVariant& operator=(__in LPCSTR lpszSrc) + { + USES_CONVERSION_EX; + Clear(); + vt = VT_BSTR; + bstrVal = ::SysAllocString(A2COLE_EX(lpszSrc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD)); + + if (bstrVal == NULL && lpszSrc != NULL) + { + vt = VT_ERROR; + scode = E_OUTOFMEMORY; +#ifndef _ATL_NO_VARIANT_THROW + ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); +#endif + } + return *this; + } + + CComVariant& operator=(__in bool bSrc) + { + if (vt != VT_BOOL) + { + Clear(); + vt = VT_BOOL; + } + boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE; + return *this; + } + + CComVariant& operator=(__in int nSrc) throw() + { + if (vt != VT_I4) + { + Clear(); + vt = VT_I4; + } + intVal = nSrc; + + return *this; + } + + CComVariant& operator=(__in BYTE nSrc) throw() + { + if (vt != VT_UI1) + { + Clear(); + vt = VT_UI1; + } + bVal = nSrc; + return *this; + } + + CComVariant& operator=(__in short nSrc) throw() + { + if (vt != VT_I2) + { + Clear(); + vt = VT_I2; + } + iVal = nSrc; + return *this; + } + + CComVariant& operator=(__in long nSrc) throw() + { + if (vt != VT_I4) + { + Clear(); + vt = VT_I4; + } + lVal = nSrc; + return *this; + } + + CComVariant& operator=(__in float fltSrc) throw() + { + if (vt != VT_R4) + { + Clear(); + vt = VT_R4; + } + fltVal = fltSrc; + return *this; + } + + CComVariant& operator=(__in double dblSrc) throw() + { + if (vt != VT_R8) + { + Clear(); + vt = VT_R8; + } + dblVal = dblSrc; + return *this; + } + + CComVariant& operator=(__in CY cySrc) throw() + { + if (vt != VT_CY) + { + Clear(); + vt = VT_CY; + } + cyVal.Hi = cySrc.Hi; + cyVal.Lo = cySrc.Lo; + return *this; + } + + CComVariant& operator=(__in_opt IDispatch* pSrc) throw() + { + Clear(); + vt = VT_DISPATCH; + pdispVal = pSrc; + // Need to AddRef as VariantClear will Release + if (pdispVal != NULL) + pdispVal->AddRef(); + return *this; + } + + CComVariant& operator=(__in_opt IUnknown* pSrc) throw() + { + Clear(); + vt = VT_UNKNOWN; + punkVal = pSrc; + + // Need to AddRef as VariantClear will Release + if (punkVal != NULL) + punkVal->AddRef(); + return *this; + } + + CComVariant& operator=(__in char cSrc) throw() + { + if (vt != VT_I1) + { + Clear(); + vt = VT_I1; + } + cVal = cSrc; + return *this; + } + + CComVariant& operator=(__in unsigned short nSrc) throw() + { + if (vt != VT_UI2) + { + Clear(); + vt = VT_UI2; + } + uiVal = nSrc; + return *this; + } + + CComVariant& operator=(__in unsigned long nSrc) throw() + { + if (vt != VT_UI4) + { + Clear(); + vt = VT_UI4; + } + ulVal = nSrc; + return *this; + } + + CComVariant& operator=(__in unsigned int nSrc) throw() + { + if (vt != VT_UI4) + { + Clear(); + vt = VT_UI4; + } + uintVal= nSrc; + return *this; + } + + CComVariant& operator=(__in_opt BYTE* pbSrc) throw() + { + if (vt != (VT_UI1|VT_BYREF)) + { + Clear(); + vt = VT_UI1|VT_BYREF; + } + pbVal = pbSrc; + return *this; + } + + CComVariant& operator=(__in_opt short* pnSrc) throw() + { + if (vt != (VT_I2|VT_BYREF)) + { + Clear(); + vt = VT_I2|VT_BYREF; + } + piVal = pnSrc; + return *this; + } + +#ifdef _NATIVE_WCHAR_T_DEFINED + CComVariant& operator=(__in_opt USHORT* pnSrc) throw() + { + if (vt != (VT_UI2|VT_BYREF)) + { + Clear(); + vt = VT_UI2|VT_BYREF; + } + puiVal = pnSrc; + return *this; + } +#endif + + CComVariant& operator=(__in_opt int* pnSrc) throw() + { + if (vt != (VT_I4|VT_BYREF)) + { + Clear(); + vt = VT_I4|VT_BYREF; + } + pintVal = pnSrc; + return *this; + } + + CComVariant& operator=(__in_opt UINT* pnSrc) throw() + { + if (vt != (VT_UI4|VT_BYREF)) + { + Clear(); + vt = VT_UI4|VT_BYREF; + } + puintVal = pnSrc; + return *this; + } + + CComVariant& operator=(__in_opt long* pnSrc) throw() + { + if (vt != (VT_I4|VT_BYREF)) + { + Clear(); + vt = VT_I4|VT_BYREF; + } + plVal = pnSrc; + return *this; + } + + CComVariant& operator=(__in_opt ULONG* pnSrc) throw() + { + if (vt != (VT_UI4|VT_BYREF)) + { + Clear(); + vt = VT_UI4|VT_BYREF; + } + pulVal = pnSrc; + return *this; + } + +#if (_WIN32_WINNT >= 0x0501) || defined(_ATL_SUPPORT_VT_I8) + CComVariant& operator=(__in LONGLONG nSrc) throw() + { + if (vt != VT_I8) + { + Clear(); + vt = VT_I8; + } + llVal = nSrc; + + return *this; + } + + CComVariant& operator=(__in_opt LONGLONG* pnSrc) throw() + { + if (vt != (VT_I8|VT_BYREF)) + { + Clear(); + vt = VT_I8|VT_BYREF; + } + pllVal = pnSrc; + return *this; + } + + CComVariant& operator=(__in ULONGLONG nSrc) throw() + { + if (vt != VT_UI8) + { + Clear(); + vt = VT_UI8; + } + ullVal = nSrc; + + return *this; + } + + CComVariant& operator=(__in_opt ULONGLONG* pnSrc) throw() + { + if (vt != (VT_UI8|VT_BYREF)) + { + Clear(); + vt = VT_UI8|VT_BYREF; + } + pullVal = pnSrc; + return *this; + } +#endif + +#pragma warning(push) +#pragma warning(disable: 28110) + + CComVariant& operator=(__in_opt float* pfSrc) throw() + { + if (vt != (VT_R4|VT_BYREF)) + { + Clear(); + vt = VT_R4|VT_BYREF; + } + pfltVal = pfSrc; + return *this; + } + + CComVariant& operator=(__in_opt double* pfSrc) throw() + { + if (vt != (VT_R8|VT_BYREF)) + { + Clear(); + vt = VT_R8|VT_BYREF; + } + pdblVal = pfSrc; + return *this; + } + +#pragma warning(pop) + + CComVariant& operator=(__in_opt const SAFEARRAY *pSrc) + { + Clear(); + LPSAFEARRAY pCopy; + if (pSrc != NULL) + { + HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy); + if (SUCCEEDED(hRes) && pCopy != NULL) + { + ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt); + vt |= VT_ARRAY; + parray = pCopy; + } + else + { + vt = VT_ERROR; + scode = hRes; +#ifndef _ATL_NO_VARIANT_THROW + ATLENSURE_THROW(FALSE, E_OUTOFMEMORY); +#endif + } + } + return *this; + } + +// Comparison Operators +public: + bool operator==(__in const VARIANT& varSrc) const throw() + { + // For backwards compatibility + if (vt == VT_NULL && varSrc.vt == VT_NULL) + { + return true; + } + // Variants not equal if types don't match + if (vt != varSrc.vt) + { + return false; + } + return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0) == static_cast(VARCMP_EQ); + } + + bool operator!=(__in const VARIANT& varSrc) const throw() + { + return !operator==(varSrc); + } + + bool operator<(__in const VARIANT& varSrc) const throw() + { + if (vt == VT_NULL && varSrc.vt == VT_NULL) + return false; + return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_LT); + } + + bool operator>(__in const VARIANT& varSrc) const throw() + { + if (vt == VT_NULL && varSrc.vt == VT_NULL) + return false; + return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT, 0)== static_cast(VARCMP_GT); + } + +// Operations +public: + HRESULT Clear() { return ::VariantClear(this); } + HRESULT ClearToZero() + { + HRESULT hr = ::VariantClear(this); + if( FAILED(hr) ) + { + return hr; + } + memset(this ,0 ,sizeof(tagVARIANT)); + vt = VT_EMPTY; + return hr; + } + + HRESULT Copy(__in const VARIANT* pSrc) { return ::VariantCopy(this, const_cast(pSrc)); } + // copy VARIANT to BSTR + HRESULT CopyTo(__out BSTR *pstrDest) + { + ATLASSERT(pstrDest != NULL && vt == VT_BSTR); + HRESULT hRes = E_POINTER; + if (pstrDest != NULL && vt == VT_BSTR) + { + *pstrDest = ::SysAllocStringByteLen((char*)bstrVal, ::SysStringByteLen(bstrVal)); + if (*pstrDest == NULL) + hRes = E_OUTOFMEMORY; + else + hRes = S_OK; + } + else if (vt != VT_BSTR) + hRes = DISP_E_TYPEMISMATCH; + return hRes; + } + HRESULT Attach(__in VARIANT* pSrc) + { + if(pSrc == NULL) + return E_INVALIDARG; + + // Clear out the variant + HRESULT hr = Clear(); + if (!FAILED(hr)) + { + // Copy the contents and give control to CComVariant + Checked::memcpy_s(this, sizeof(CComVariant), pSrc, sizeof(VARIANT)); + pSrc->vt = VT_EMPTY; + hr = S_OK; + } + return hr; + } + + HRESULT Detach(__out VARIANT* pDest) + { + ATLASSERT(pDest != NULL); + if(pDest == NULL) + return E_POINTER; + + // Clear out the variant + HRESULT hr = ::VariantClear(pDest); + if (!FAILED(hr)) + { + // Copy the contents and remove control from CComVariant + Checked::memcpy_s(pDest, sizeof(VARIANT), this, sizeof(VARIANT)); + vt = VT_EMPTY; + hr = S_OK; + } + return hr; + } + + HRESULT ChangeType(__in VARTYPE vtNew, __in_opt const VARIANT* pSrc = NULL) + { + VARIANT* pVar = const_cast(pSrc); + // Convert in place if pSrc is NULL + if (pVar == NULL) + pVar = this; + // Do nothing if doing in place convert and vts not different + return ::VariantChangeType(this, pVar, 0, vtNew); + } + + template< typename T > + void SetByRef( __in T* pT ) throw() + { + Clear(); + vt = CVarTypeInfo< T >::VT|VT_BYREF; + byref = pT; + } + + HRESULT WriteToStream(__inout IStream* pStream); + HRESULT WriteToStream(__inout IStream* pStream, VARTYPE vtWrite) + { + if (vtWrite != VT_EMPTY && vtWrite != vt) + { + CComVariant varConv; + HRESULT hr = varConv.ChangeType(vtWrite, this); + if (FAILED(hr)) + { + return hr; + } + return varConv.WriteToStream(pStream); + } + return WriteToStream(pStream); + } + HRESULT ReadFromStream(__inout IStream* pStream, VARTYPE vtExpected = VT_EMPTY); + + // Return the size in bytes of the current contents + ULONG GetSize() const; + +// Implementation +public: + HRESULT InternalClear() + { + HRESULT hr = Clear(); + ATLASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + vt = VT_ERROR; + scode = hr; +#ifndef _ATL_NO_VARIANT_THROW + AtlThrow(hr); +#endif + } + return hr; + } + + void InternalCopy(__in const VARIANT* pSrc) + { + HRESULT hr = Copy(pSrc); + if (FAILED(hr)) + { + vt = VT_ERROR; + scode = hr; +#ifndef _ATL_NO_VARIANT_THROW + AtlThrow(hr); +#endif + } + } +}; + +#pragma warning(push) +#pragma warning(disable: 4702) +inline HRESULT CComVariant::WriteToStream(__inout IStream* pStream) +{ + if(pStream == NULL) + return E_INVALIDARG; + + HRESULT hr = pStream->Write(&vt, sizeof(VARTYPE), NULL); + if (FAILED(hr)) + return hr; + + int cbWrite = 0; + switch (vt) + { + case VT_UNKNOWN: + case VT_DISPATCH: + { + CComPtr spStream; + if (punkVal != NULL) + { + hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); + if (FAILED(hr)) + { + hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); + if (FAILED(hr)) + return hr; + } + } + if (spStream != NULL) + return OleSaveToStream(spStream, pStream); + return WriteClassStm(pStream, CLSID_NULL); + } + case VT_UI1: + case VT_I1: + cbWrite = sizeof(BYTE); + break; + case VT_I2: + case VT_UI2: + case VT_BOOL: + cbWrite = sizeof(short); + break; + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + cbWrite = sizeof(long); + break; + case VT_I8: + case VT_UI8: + cbWrite = sizeof(LONGLONG); + break; + case VT_R8: + case VT_CY: + case VT_DATE: + cbWrite = sizeof(double); + break; + default: + break; + } + if (cbWrite != 0) + return pStream->Write((void*) &bVal, cbWrite, NULL); + + CComBSTR bstrWrite; + CComVariant varBSTR; + if (vt != VT_BSTR) + { + hr = VariantChangeType(&varBSTR, this, VARIANT_NOVALUEPROP, VT_BSTR); + if (FAILED(hr)) + return hr; + bstrWrite.Attach(varBSTR.bstrVal); + } + else + bstrWrite.Attach(bstrVal); + + hr = bstrWrite.WriteToStream(pStream); + bstrWrite.Detach(); + return hr; +} +#pragma warning(pop) // C4702 + +inline HRESULT CComVariant::ReadFromStream(__inout IStream* pStream, VARTYPE vtExpected /* = VT_EMPTY */ ) +{ + ATLASSERT(pStream != NULL); + if(pStream == NULL) + return E_INVALIDARG; + + HRESULT hr; + hr = VariantClear(this); + if (FAILED(hr)) + return hr; + VARTYPE vtRead = VT_EMPTY; + ULONG cbRead = 0; + hr = pStream->Read(&vtRead, sizeof(VARTYPE), &cbRead); + if (hr == S_FALSE || (cbRead != sizeof(VARTYPE) && hr == S_OK)) + hr = E_FAIL; + if (FAILED(hr)) + return hr; + if (vtExpected != VT_EMPTY && vtRead != vtExpected) + return E_FAIL; + + vt = vtRead; + cbRead = 0; + switch (vtRead) + { + case VT_UNKNOWN: + case VT_DISPATCH: + { + punkVal = NULL; + hr = OleLoadFromStream(pStream, + (vtRead == VT_UNKNOWN) ? __uuidof(IUnknown) : __uuidof(IDispatch), + (void**)&punkVal); + // If IPictureDisp or IFontDisp property is not set, + // OleLoadFromStream() will return REGDB_E_CLASSNOTREG. + if (hr == REGDB_E_CLASSNOTREG) + hr = S_OK; + return hr; + } + case VT_UI1: + case VT_I1: + cbRead = sizeof(BYTE); + break; + case VT_I2: + case VT_UI2: + case VT_BOOL: + cbRead = sizeof(short); + break; + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + cbRead = sizeof(long); + break; + case VT_I8: + case VT_UI8: + cbRead = sizeof(LONGLONG); + break; + case VT_R8: + case VT_CY: + case VT_DATE: + cbRead = sizeof(double); + break; + default: + break; + } + if (cbRead != 0) + { + hr = pStream->Read((void*) &bVal, cbRead, NULL); + if (hr == S_FALSE) + hr = E_FAIL; + return hr; + } + CComBSTR bstrRead; + + hr = bstrRead.ReadFromStream(pStream); + if (FAILED(hr)) + { + // If CComBSTR::ReadFromStream failed, reset seek pointer to start of + // variant type. + LARGE_INTEGER nOffset; + nOffset.QuadPart = -(static_cast(sizeof(VARTYPE))); + pStream->Seek(nOffset, STREAM_SEEK_CUR, NULL); + vt = VT_EMPTY; + return hr; + } + vt = VT_BSTR; + bstrVal = bstrRead.Detach(); + if (vtRead != VT_BSTR) + hr = ChangeType(vtRead); + return hr; +} + +inline ULONG CComVariant::GetSize() const +{ + ULONG nSize = sizeof(VARTYPE); + HRESULT hr; + + switch (vt) + { + case VT_UNKNOWN: + case VT_DISPATCH: + { + CComPtr spStream; + if (punkVal != NULL) + { + hr = punkVal->QueryInterface(__uuidof(IPersistStream), (void**)&spStream); + if (FAILED(hr)) + { + hr = punkVal->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spStream); + if (FAILED(hr)) + break; + } + } + if (spStream != NULL) + { + ULARGE_INTEGER nPersistSize; + nPersistSize.QuadPart = 0; + spStream->GetSizeMax(&nPersistSize); + nSize += nPersistSize.LowPart + sizeof(CLSID); + } + else + nSize += sizeof(CLSID); + } + break; + case VT_UI1: + case VT_I1: + nSize += sizeof(BYTE); + break; + case VT_I2: + case VT_UI2: + case VT_BOOL: + nSize += sizeof(short); + break; + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_INT: + case VT_UINT: + case VT_ERROR: + nSize += sizeof(long); + break; + case VT_I8: + case VT_UI8: + nSize += sizeof(LONGLONG); + break; + case VT_R8: + case VT_CY: + case VT_DATE: + nSize += sizeof(double); + break; + default: + break; + } + if (nSize == sizeof(VARTYPE)) + { + VARTYPE vtTmp = vt; + BSTR bstr = NULL; + CComVariant varBSTR; + if (vtTmp != VT_BSTR) + { + hr = VariantChangeType(&varBSTR, const_cast((const VARIANT*)this), VARIANT_NOVALUEPROP, VT_BSTR); + if (SUCCEEDED(hr)) + { + bstr = varBSTR.bstrVal; + vtTmp = VT_BSTR; + } + } else + { + bstr = bstrVal; + } + + if (vtTmp == VT_BSTR) + { + // Add the size of the length + string (in bytes) + NULL terminator. + nSize += CComBSTR::GetStreamSize(bstr); + } + } + return nSize; +} + +__checkReturn inline HRESULT CComPtr::Invoke2(__in DISPID dispid, __in VARIANT* pvarParam1, __in VARIANT* pvarParam2, __out_opt VARIANT* pvarRet) throw() +{ + if(pvarParam1 == NULL || pvarParam2 == NULL) + return E_INVALIDARG; + + CComVariant varArgs[2] = { *pvarParam2, *pvarParam1 }; + DISPPARAMS dispparams = { &varArgs[0], NULL, 2, 0}; + return p->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, pvarRet, NULL, NULL); +} + +} // namespace ATL +#pragma pack(pop) + +#pragma warning (pop) + +#ifndef _ATL_NO_AUTOMATIC_NAMESPACE +using namespace ATL; +#endif //!_ATL_NO_AUTOMATIC_NAMESPACE + +#endif // __ATLCOMCLI_H__ + diff --git a/c/jacob/include/atlconv.h b/c/jacob/include/atlconv.h new file mode 100644 index 0000000..338109d --- /dev/null +++ b/c/jacob/include/atlconv.h @@ -0,0 +1,1302 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLCONV_H__ +#define __ATLCONV_H__ + +#pragma once + +#ifndef _ATL_NO_PRAGMA_WARNINGS +#pragma warning (push) +#pragma warning(disable: 4127) // unreachable code +#endif //!_ATL_NO_PRAGMA_WARNINGS + +// +// [pfx_parse] - workaround for old PREfix/PREfast parser +// +#if (defined(_PREFIX_) || defined(_PREFAST_)) && (_MSC_VER < 1400) +#pragma warning (push) +#pragma warning(disable: 4081) // expected 'newline' +#endif // old PREfast parser + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#include +#include +#include + +#ifndef __wtypes_h__ + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86) +#define _X86_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64) +#define _AMD64_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_M68K) +#define _68K_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_MPPC) +#define _MPPC_ +#endif + +#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_M_IX86) && !defined(_AMD64_) && defined(_M_IA64) +#if !defined(_IA64_) +#define _IA64_ +#endif // !_IA64_ +#endif + +#include +#include +#include +#include + +#if defined(_WIN32) && !defined(OLE2ANSI) + +typedef WCHAR OLECHAR; +typedef OLECHAR *LPOLESTR; +typedef const OLECHAR *LPCOLESTR; +#define OLESTR(str) L##str + +#else + +typedef char OLECHAR; +typedef LPSTR LPOLESTR; +typedef LPCSTR LPCOLESTR; +#define OLESTR(str) str + +#endif // _WIN32 && !OLE2ANSI +#endif // __wtypes_h__ + +#ifndef _OLEAUTO_H_ +typedef LPWSTR BSTR;// must (semantically) match typedef in oleauto.h + +extern "C" +{ +__declspec(dllimport) BSTR __stdcall SysAllocString(const OLECHAR *); +__declspec(dllimport) BSTR __stdcall SysAllocStringLen(const OLECHAR *, UINT); +__declspec(dllimport) INT __stdcall SysReAllocStringLen(BSTR *, const OLECHAR *, UINT); +__declspec(dllimport) void __stdcall SysFreeString(BSTR); +} +#endif + +// we use our own implementation of InterlockedExchangePointer because of problems with the one in system headers +#ifdef _M_IX86 +#undef InterlockedExchangePointer +inline void* WINAPI InterlockedExchangePointer(void** pp, void* pNew) throw() +{ + return( reinterpret_cast(static_cast(::InterlockedExchange(reinterpret_cast(pp), static_cast(reinterpret_cast(pNew))))) ); +} +#endif + +#ifndef _SECURECRT_FILL_BUFFER_PATTERN +#define _SECURECRT_FILL_BUFFER_PATTERN 0xFD +#endif + +#define ATLCONV_DEADLAND_FILL _SECURECRT_FILL_BUFFER_PATTERN + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ +#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE +inline UINT WINAPI _AtlGetConversionACP() throw() +{ + return( CP_THREAD_ACP ); +} + +#else + +inline UINT WINAPI _AtlGetConversionACP() throw() +{ + return( CP_ACP ); +} + +#endif // _CONVERSION_DONT_USE_THREAD_LOCALE +template +inline void AtlConvAllocMemory(__deref_ecount_opt(nLength) _CharType** ppBuff,__in int nLength,__inout_ecount(nFixedBufferLength) _CharType* pszFixedBuffer,__in int nFixedBufferLength) +{ + ATLENSURE_THROW(ppBuff != NULL, E_INVALIDARG); + ATLENSURE_THROW(nLength >= 0, E_INVALIDARG); + ATLENSURE_THROW(pszFixedBuffer != NULL, E_INVALIDARG); + + //if buffer malloced, try to realloc. + if (*ppBuff != pszFixedBuffer) + { + if( nLength > nFixedBufferLength ) + { + _CharType* ppReallocBuf = static_cast< _CharType* >( _recalloc(*ppBuff, nLength,sizeof( _CharType ) ) ); + if (ppReallocBuf == NULL) + { + AtlThrow( E_OUTOFMEMORY ); + } + *ppBuff = ppReallocBuf; + } else + { + free(*ppBuff); + *ppBuff=pszFixedBuffer; + } + + } else //Buffer is not currently malloced. + { + if( nLength > nFixedBufferLength ) + { + *ppBuff = static_cast< _CharType* >( calloc(nLength,sizeof( _CharType ) ) ); + } else + { + *ppBuff=pszFixedBuffer; + } + } + + if (*ppBuff == NULL) + { + AtlThrow( E_OUTOFMEMORY ); + } + +} + +template +inline void AtlConvFreeMemory(_CharType* pBuff,_CharType* pszFixedBuffer,int nFixedBufferLength) +{ + (nFixedBufferLength); + if( pBuff != pszFixedBuffer ) + { + free( pBuff ); + } +#ifdef _DEBUG + else + { + memset(pszFixedBuffer,ATLCONV_DEADLAND_FILL,nFixedBufferLength*sizeof(_CharType)); + } +#endif + +} + +template< int t_nBufferLength = 128 > +class CW2WEX +{ +public: + CW2WEX( __in_opt LPCWSTR psz ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz ); + } + CW2WEX( __in_opt LPCWSTR psz, UINT nCodePage ) throw(...) : + m_psz( m_szBuffer ) + { + (void)nCodePage; // Code page doesn't matter + + Init( psz ); + } + ~CW2WEX() throw() + { + AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); + } + + operator LPWSTR() const throw() + { + return( m_psz ); + } + +private: + void Init( __in_opt LPCWSTR psz ) throw(...) + { + if (psz == NULL) + { + m_psz = NULL; + return; + } + int nLength = lstrlenW( psz )+1; + AtlConvAllocMemory(&m_psz,nLength,m_szBuffer,t_nBufferLength); + Checked::memcpy_s( m_psz, nLength*sizeof( wchar_t ), psz, nLength*sizeof( wchar_t )); + } + +public: + LPWSTR m_psz; + wchar_t m_szBuffer[t_nBufferLength]; + +private: + CW2WEX( const CW2WEX& ) throw(); + CW2WEX& operator=( const CW2WEX& ) throw(); +}; +typedef CW2WEX<> CW2W; + +template< int t_nBufferLength = 128 > +class CA2AEX +{ +public: + CA2AEX( __in_opt LPCSTR psz ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz ); + } + CA2AEX( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) : + m_psz( m_szBuffer ) + { + (void)nCodePage; // Code page doesn't matter + + Init( psz ); + } + ~CA2AEX() throw() + { + AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); + } + + operator LPSTR() const throw() + { + return( m_psz ); + } + +private: + void Init( __in_opt LPCSTR psz ) throw(...) + { + if (psz == NULL) + { + m_psz = NULL; + return; + } + int nLength = lstrlenA( psz )+1; + AtlConvAllocMemory(&m_psz,nLength,m_szBuffer,t_nBufferLength); + Checked::memcpy_s( m_psz, nLength*sizeof( char ), psz, nLength*sizeof( char )); + } + +public: + LPSTR m_psz; + char m_szBuffer[t_nBufferLength]; + +private: + CA2AEX( const CA2AEX& ) throw(); + CA2AEX& operator=( const CA2AEX& ) throw(); +}; +typedef CA2AEX<> CA2A; + +template< int t_nBufferLength = 128 > +class CA2CAEX +{ +public: + CA2CAEX( __in LPCSTR psz ) throw(...) : + m_psz( psz ) + { + } + CA2CAEX( __in LPCSTR psz, UINT nCodePage ) throw(...) : + m_psz( psz ) + { + (void)nCodePage; + } + ~CA2CAEX() throw() + { + } + + operator LPCSTR() const throw() + { + return( m_psz ); + } + +public: + LPCSTR m_psz; + +private: + CA2CAEX( const CA2CAEX& ) throw(); + CA2CAEX& operator=( const CA2CAEX& ) throw(); +}; +typedef CA2CAEX<> CA2CA; + +template< int t_nBufferLength = 128 > +class CW2CWEX +{ +public: + CW2CWEX( __in LPCWSTR psz ) throw(...) : + m_psz( psz ) + { + } + CW2CWEX( __in LPCWSTR psz, UINT nCodePage ) throw(...) : + m_psz( psz ) + { + (void)nCodePage; + } + ~CW2CWEX() throw() + { + } + + operator LPCWSTR() const throw() + { + return( m_psz ); + } + +public: + LPCWSTR m_psz; + +private: + CW2CWEX( const CW2CWEX& ) throw(); + CW2CWEX& operator=( const CW2CWEX& ) throw(); +}; +typedef CW2CWEX<> CW2CW; + +template< int t_nBufferLength = 128 > +class CA2WEX +{ +public: + CA2WEX( __in_opt LPCSTR psz ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz, _AtlGetConversionACP() ); + } + CA2WEX( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz, nCodePage ); + } + ~CA2WEX() throw() + { + AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); + } + + operator LPWSTR() const throw() + { + return( m_psz ); + } + +private: + void Init( __in_opt LPCSTR psz, UINT nCodePage ) throw(...) + { + if (psz == NULL) + { + m_psz = NULL; + return; + } + int nLengthA = lstrlenA( psz )+1; + int nLengthW = nLengthA; + + AtlConvAllocMemory(&m_psz,nLengthW,m_szBuffer,t_nBufferLength); + + BOOL bFailed=(0 == ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW ) ); + if (bFailed) + { + if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) + { + nLengthW = ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, NULL, 0); + AtlConvAllocMemory(&m_psz,nLengthW,m_szBuffer,t_nBufferLength); + bFailed=(0 == ::MultiByteToWideChar( nCodePage, 0, psz, nLengthA, m_psz, nLengthW ) ); + } + } + if (bFailed) + { + AtlThrowLastWin32(); + } + } + +public: + LPWSTR m_psz; + wchar_t m_szBuffer[t_nBufferLength]; + +private: + CA2WEX( const CA2WEX& ) throw(); + CA2WEX& operator=( const CA2WEX& ) throw(); +}; +typedef CA2WEX<> CA2W; + +template< int t_nBufferLength = 128 > +class CW2AEX +{ +public: + CW2AEX( __in_opt LPCWSTR psz ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz, _AtlGetConversionACP() ); + } + CW2AEX( __in_opt LPCWSTR psz, UINT nCodePage ) throw(...) : + m_psz( m_szBuffer ) + { + Init( psz, nCodePage ); + } + ~CW2AEX() throw() + { + AtlConvFreeMemory(m_psz,m_szBuffer,t_nBufferLength); + } + + operator LPSTR() const throw() + { + return( m_psz ); + } + +private: + void Init( __in_opt LPCWSTR psz, __in UINT nConvertCodePage ) throw(...) + { + if (psz == NULL) + { + m_psz = NULL; + return; + } + int nLengthW = lstrlenW( psz )+1; + int nLengthA = nLengthW*4; + + AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength); + + BOOL bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL )); + if (bFailed) + { + if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) + { + nLengthA = ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, NULL, 0, NULL, NULL ); + AtlConvAllocMemory(&m_psz,nLengthA,m_szBuffer,t_nBufferLength); + bFailed=(0 == ::WideCharToMultiByte( nConvertCodePage, 0, psz, nLengthW, m_psz, nLengthA, NULL, NULL )); + } + } + if (bFailed) + { + AtlThrowLastWin32(); + } + } + +public: + LPSTR m_psz; + char m_szBuffer[t_nBufferLength]; + +private: + CW2AEX( const CW2AEX& ) throw(); + CW2AEX& operator=( const CW2AEX& ) throw(); +}; +typedef CW2AEX<> CW2A; + +#ifdef _UNICODE + + #define CW2T CW2W + #define CW2TEX CW2WEX + #define CW2CT CW2CW + #define CW2CTEX CW2CWEX + #define CT2W CW2W + #define CT2WEX CW2WEX + #define CT2CW CW2CW + #define CT2CWEX CW2CWEX + + #define CA2T CA2W + #define CA2TEX CA2WEX + #define CA2CT CA2W + #define CA2CTEX CA2WEX + #define CT2A CW2A + #define CT2AEX CW2AEX + #define CT2CA CW2A + #define CT2CAEX CW2AEX + +#else // !_UNICODE + + #define CW2T CW2A + #define CW2TEX CW2AEX + #define CW2CT CW2A + #define CW2CTEX CW2AEX + #define CT2W CA2W + #define CT2WEX CA2WEX + #define CT2CW CA2W + #define CT2CWEX CA2WEX + + #define CA2T CA2A + #define CA2TEX CA2AEX + #define CA2CT CA2CA + #define CA2CTEX CA2CAEX + #define CT2A CA2A + #define CT2AEX CA2AEX + #define CT2CA CA2CA + #define CT2CAEX CA2CAEX + +#endif // !_UNICODE + +#define COLE2T CW2T +#define COLE2TEX CW2TEX +#define COLE2CT CW2CT +#define COLE2CTEX CW2CTEX +#define CT2OLE CT2W +#define CT2OLEEX CT2WEX +#define CT2COLE CT2CW +#define CT2COLEEX CT2CWEX + +}; // namespace ATL +#pragma pack(pop) + +#pragma pack(push,8) + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + +#ifndef _DEBUG + #define USES_CONVERSION int _convert; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw; (_lpw); LPCSTR _lpa; (_lpa) +#else + #define USES_CONVERSION int _convert = 0; (_convert); UINT _acp = ATL::_AtlGetConversionACP() /*CP_THREAD_ACP*/; (_acp); LPCWSTR _lpw = NULL; (_lpw); LPCSTR _lpa = NULL; (_lpa) +#endif + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#ifndef _DEBUG + #define USES_CONVERSION_EX int _convert_ex; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex; (_lpw_ex); LPCSTR _lpa_ex; (_lpa_ex); USES_ATL_SAFE_ALLOCA +#else + #define USES_CONVERSION_EX int _convert_ex = 0; (_convert_ex); UINT _acp_ex = ATL::_AtlGetConversionACP(); (_acp_ex); LPCWSTR _lpw_ex = NULL; (_lpw_ex); LPCSTR _lpa_ex = NULL; (_lpa_ex); USES_ATL_SAFE_ALLOCA +#endif + +#ifdef _WINGDI_ + ATLAPI_(LPDEVMODEA) AtlDevModeW2A(__out LPDEVMODEA lpDevModeA, __in const DEVMODEW* lpDevModeW); +#endif + +///////////////////////////////////////////////////////////////////////////// +// Global UNICODE<>ANSI translation helpers +inline __out_ecount_z_opt(nChars) LPWSTR WINAPI AtlA2WHelper(__out_ecount_z(nChars) LPWSTR lpw, __in_z LPCSTR lpa, __in int nChars, __in UINT acp) throw() +{ + ATLASSERT(lpa != NULL); + ATLASSERT(lpw != NULL); + if (lpw == NULL || lpa == NULL) + return NULL; + // verify that no illegal character present + // since lpw was allocated based on the size of lpa + // don't worry about the number of chars + lpw[0] = '\0'; + int ret = MultiByteToWideChar(acp, 0, lpa, -1, lpw, nChars); + if(ret == 0) + { + ATLASSERT(FALSE); + return NULL; + } + return lpw; +} + +inline __out_ecount_z_opt(nChars) LPSTR WINAPI AtlW2AHelper(__out_ecount_z(nChars) LPSTR lpa, __in_z LPCWSTR lpw, __in int nChars, __in UINT acp) throw() +{ + ATLASSERT(lpw != NULL); + ATLASSERT(lpa != NULL); + if (lpa == NULL || lpw == NULL) + return NULL; + // verify that no illegal character present + // since lpa was allocated based on the size of lpw + // don't worry about the number of chars + lpa[0] = '\0'; + int ret = WideCharToMultiByte(acp, 0, lpw, -1, lpa, nChars, NULL, NULL); + if(ret == 0) + { + ATLASSERT(FALSE); + return NULL; + } + return lpa; +} +inline __out_ecount_z_opt(nChars) LPWSTR WINAPI AtlA2WHelper(__out_ecount_z(nChars) LPWSTR lpw, __in_z LPCSTR lpa, __in int nChars) throw() +{ + return AtlA2WHelper(lpw, lpa, nChars, CP_ACP); +} + +inline __out_ecount_z_opt(nChars) LPSTR WINAPI AtlW2AHelper(__out_ecount_z(nChars) LPSTR lpa, __in_z LPCWSTR lpw, __in int nChars) throw() +{ + return AtlW2AHelper(lpa, lpw, nChars, CP_ACP); +} + +#ifndef _CONVERSION_DONT_USE_THREAD_LOCALE + #ifdef ATLA2WHELPER + #undef ATLA2WHELPER + #undef ATLW2AHELPER + #endif + #define ATLA2WHELPER AtlA2WHelper + #define ATLW2AHELPER AtlW2AHelper +#else + #ifndef ATLA2WHELPER + #define ATLA2WHELPER AtlA2WHelper + #define ATLW2AHELPER AtlW2AHelper + #endif +#endif + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + +#define A2W(lpa) (\ + ((_lpa = lpa) == NULL) ? NULL : (\ + _convert = (lstrlenA(_lpa)+1),\ + (INT_MAX/2<_convert)? NULL : \ + ATLA2WHELPER((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, _acp))) + +#define W2A(lpw) (\ + ((_lpw = lpw) == NULL) ? NULL : (\ + (_convert = (lstrlenW(_lpw)+1), \ + (_convert>INT_MAX/2) ? NULL : \ + ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), _acp)))) + +#define A2W_CP(lpa, cp) (\ + ((_lpa = lpa) == NULL) ? NULL : (\ + _convert = (lstrlenA(_lpa)+1),\ + (INT_MAX/2<_convert)? NULL : \ + ATLA2WHELPER((LPWSTR) alloca(_convert*sizeof(WCHAR)), _lpa, _convert, (cp)))) + +#define W2A_CP(lpw, cp) (\ + ((_lpw = lpw) == NULL) ? NULL : (\ + (_convert = (lstrlenW(_lpw)+1), \ + (_convert>INT_MAX/2) ? NULL : \ + ATLW2AHELPER((LPSTR) alloca(_convert*sizeof(WCHAR)), _lpw, _convert*sizeof(WCHAR), (cp))))) + +#endif + +// The call to _alloca will not cause stack overflow if _AtlVerifyStackAvailable returns TRUE. +// Notice that nChars is never used in these conversion functions. We cannot change the behavior of +// these functions to actually use nChars because we could potentially break a lot of legacy code. +#define A2W_EX(lpa, nChars) (\ + ((_lpa_ex = lpa) == NULL) ? NULL : (\ + _convert_ex = (lstrlenA(_lpa_ex)+1),\ + FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ + ATLA2WHELPER( \ + (LPWSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ + _lpa_ex, \ + _convert_ex / sizeof(WCHAR), \ + _acp_ex))) + +#define A2W_EX_DEF(lpa) A2W_EX(lpa, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) + +#define W2A_EX(lpw, nChars) (\ + ((_lpw_ex = lpw) == NULL) ? NULL : (\ + _convert_ex = (lstrlenW(_lpw_ex)+1),\ + FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ + ATLW2AHELPER( \ + (LPSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ + _lpw_ex, \ + _convert_ex, \ + _acp_ex))) + +#define W2A_EX_DEF(lpa) W2A_EX(lpa, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) + +#define A2W_CP_EX(lpa, nChars, cp) (\ + ((_lpa_ex = lpa) == NULL) ? NULL : (\ + _convert_ex = (lstrlenA(_lpa_ex)+1),\ + FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ + ATLA2WHELPER( \ + (LPWSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ + _lpa_ex, \ + _convert_ex / sizeof(WCHAR), \ + (cp)))) + +#define W2A_CP_EX(lpw, nChars, cp) (\ + ((_lpw_ex = lpw) == NULL) ? NULL : (\ + _convert_ex = (lstrlenW(_lpw_ex)+1),\ + FAILED(::ATL::AtlMultiply(&_convert_ex, _convert_ex, static_cast(sizeof(WCHAR)))) ? NULL : \ + ATLW2AHELPER( \ + (LPSTR)_ATL_SAFE_ALLOCA(_convert_ex, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), \ + _lpw_ex, \ + _convert_ex, \ + (cp)))) + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + +#define A2CW(lpa) ((LPCWSTR)A2W(lpa)) +#define W2CA(lpw) ((LPCSTR)W2A(lpw)) + +#define A2CW_CP(lpa, cp) ((LPCWSTR)A2W_CP(lpa, (cp))) +#define W2CA_CP(lpw, cp) ((LPCSTR)W2A_CP(lpw, (cp))) + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#define A2CW_EX(lpa, nChar) ((LPCWSTR)A2W_EX(lpa, nChar)) +#define A2CW_EX_DEF(lpa) ((LPCWSTR)A2W_EX_DEF(lpa)) +#define W2CA_EX(lpw, nChar) ((LPCSTR)W2A_EX(lpw, nChar)) +#define W2CA_EX_DEF(lpw) ((LPCSTR)W2A_EX_DEF(lpw)) + +#define A2CW_CP_EX(lpa, nChar, cp) ((LPCWSTR)A2W_CP_EX(lpa, nChar, (cp))) +#define W2CA_CP_EX(lpw, nChar, cp) ((LPCSTR)W2A_CP_EX(lpw, nChar, (cp))) + + inline int ocslen(__in_z LPCOLESTR x) throw() { return lstrlenW(x); } + +#if _SECURE_ATL + inline bool ocscpy_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() + { return 0 == memcpy_s(dest, maxSize*sizeof(WCHAR), src, (ocslen(src)+1)*sizeof(WCHAR)); } + inline bool ocscat_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() + { return 0 == wcscat_s(dest, maxSize,src); } +#else + inline bool ocscpy_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() + { (void)maxSize; memcpy(dest, src, (ocslen(src)+1)*sizeof(WCHAR)); return true; } + inline bool ocscat_s(__out_ecount_z(maxSize) LPOLESTR dest, __in size_t maxSize, __in_z LPCOLESTR src) throw() + { (void)maxSize; wcscat(dest, src); } +#endif + +#if defined(_UNICODE) + +// in these cases the default (TCHAR) is the same as OLECHAR + +#if _SECURE_ATL + _ATL_INSECURE_DEPRECATE("ocscpy is not safe. Intead, use ocscpy_s") + inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { +#pragma warning(push) +#pragma warning(disable:4995) // use of deprecated function +#pragma warning(disable:4996) +#pragma warning(disable:28719) // use of Banned API + return wcscpy(dest, src); +#pragma warning(pop) + } + _ATL_INSECURE_DEPRECATE("ocscat is not safe. Intead, use ocscat_s") + inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { +#pragma warning(push) +#pragma warning(disable:4995) // use of deprecated function +#pragma warning(disable:4996) +#pragma warning(disable:28719) // use of Banned API + return wcscat(dest, src); +#pragma warning(pop) + } +#else +#pragma warning(push) +#pragma warning(disable:4995) // use of deprecated function + inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() { return lstrcpyW(dest, src); } + inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() { return lstrcatW(dest, src); } +#pragma warning(pop) +#endif + + inline LPCOLESTR T2COLE_EX(__in_opt LPCTSTR lp, UINT) { return lp; } + inline LPCOLESTR T2COLE_EX_DEF(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR OLE2CT_EX(__in_opt LPCOLESTR lp, UINT) { return lp; } + inline LPCTSTR OLE2CT_EX_DEF(__in_opt LPCOLESTR lp) { return lp; } + inline LPOLESTR T2OLE_EX(__in_opt LPTSTR lp, UINT) { return lp; } + inline LPOLESTR T2OLE_EX_DEF(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR OLE2T_EX(__in_opt LPOLESTR lp, UINT) { return lp; } + inline LPTSTR OLE2T_EX_DEF(__in_opt LPOLESTR lp) { return lp; } + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + inline LPCOLESTR T2COLE(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR OLE2CT(__in_opt LPCOLESTR lp) { return lp; } + inline LPOLESTR T2OLE(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR OLE2T(__in_opt LPOLESTR lp) { return lp; } + inline LPOLESTR CharNextO(__in LPCOLESTR lp) throw() {return CharNextW(lp);} + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#else // !defined(_UNICODE) + +#if _SECURE_ATL + + _ATL_INSECURE_DEPRECATE("ocscpy is not safe. Intead, use ocscpy_s") + inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { +#pragma warning(push) +#pragma warning(disable:4995) // use of deprecated function +#pragma warning(disable:4996) + return (LPOLESTR) memcpy(dest, src, (lstrlenW(src)+1)*sizeof(WCHAR)); +#pragma warning(pop) + } + _ATL_INSECURE_DEPRECATE("ocscat is not safe. Intead, use ocscat_s") + inline OLECHAR* ocscat(__inout_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { +#pragma warning(push) +#pragma warning(disable:4995) // use of deprecated function +#pragma warning(disable:4996) + return ocscpy(dest+ocslen(dest), src); +#pragma warning(pop) + } + +#else + + //lstrcpyW doesn't work on Win95, so we do this + inline OLECHAR* ocscpy(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { + return (LPOLESTR) memcpy(dest, src, (lstrlenW(src)+1)*sizeof(WCHAR)); + } + inline OLECHAR* ocscat(__out_z LPOLESTR dest, __in_z LPCOLESTR src) throw() + { + return ocscpy(dest+ocslen(dest), src); + } + +#endif + + //CharNextW doesn't work on Win95 so we use this + #define T2COLE_EX(lpa, nChar) A2CW_EX(lpa, nChar) + #define T2COLE_EX_DEF(lpa) A2CW_EX_DEF(lpa) + #define T2OLE_EX(lpa, nChar) A2W_EX(lpa, nChar) + #define T2OLE_EX_DEF(lpa) A2W_EX_DEF(lpa) + #define OLE2CT_EX(lpo, nChar) W2CA_EX(lpo, nChar) + #define OLE2CT_EX_DEF(lpo) W2CA_EX_DEF(lpo) + #define OLE2T_EX(lpo, nChar) W2A_EX(lpo, nChar) + #define OLE2T_EX_DEF(lpo) W2A_EX_DEF(lpo) + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + #define T2COLE(lpa) A2CW(lpa) + #define T2OLE(lpa) A2W(lpa) + #define OLE2CT(lpo) W2CA(lpo) + #define OLE2T(lpo) W2A(lpo) + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + + inline LPOLESTR CharNextO(LPCOLESTR lp) throw() {return (LPOLESTR) ((*lp) ? (lp+1) : lp);} + +#endif // defined(_UNICODE) + + inline LPOLESTR W2OLE_EX(__in_opt LPWSTR lp, UINT) { return lp; } + inline LPOLESTR W2OLE_EX_DEF(__in_opt LPWSTR lp) { return lp; } + inline LPWSTR OLE2W_EX(__in_opt LPOLESTR lp, UINT) { return lp; } + inline LPWSTR OLE2W_EX_DEF(__in_opt LPOLESTR lp) { return lp; } + #define A2OLE_EX A2W_EX + #define A2OLE_EX_DEF A2W_EX_DEF + #define OLE2A_EX W2A_EX + #define OLE2A_EX_DEF W2A_EX_DEF + inline LPCOLESTR W2COLE_EX(__in_opt LPCWSTR lp, UINT) { return lp; } + inline LPCOLESTR W2COLE_EX_DEF(__in_opt LPCWSTR lp) { return lp; } + inline LPCWSTR OLE2CW_EX(__in_opt LPCOLESTR lp, UINT) { return lp; } + inline LPCWSTR OLE2CW_EX_DEF(__in_opt LPCOLESTR lp) { return lp; } + #define A2COLE_EX A2CW_EX + #define A2COLE_EX_DEF A2CW_EX_DEF + #define OLE2CA_EX W2CA_EX + #define OLE2CA_EX_DEF W2CA_EX_DEF + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + inline LPOLESTR W2OLE(__in_opt LPWSTR lp) { return lp; } + inline LPWSTR OLE2W(__in_opt LPOLESTR lp) { return lp; } + #define A2OLE A2W + #define OLE2A W2A + inline LPCOLESTR W2COLE(__in_opt LPCWSTR lp) { return lp; } + inline LPCWSTR OLE2CW(__in_opt LPCOLESTR lp) { return lp; } + #define A2COLE A2CW + #define OLE2CA W2CA + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#if defined(_UNICODE) + + #define T2A_EX W2A_EX + #define T2A_EX_DEF W2A_EX_DEF + #define A2T_EX A2W_EX + #define A2T_EX_DEF A2W_EX_DEF + inline LPWSTR T2W_EX(__in_opt LPTSTR lp, UINT) { return lp; } + inline LPWSTR T2W_EX_DEF(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR W2T_EX(__in_opt LPWSTR lp, UINT) { return lp; } + inline LPTSTR W2T_DEF(__in_opt LPWSTR lp) { return lp; } + #define T2CA_EX W2CA_EX + #define T2CA_EX_DEF W2CA_EX_DEF + #define A2CT_EX A2CW_EX + #define A2CT_EX_DEF A2CW_EX_DEF + inline LPCWSTR T2CW_EX(__in_opt LPCTSTR lp, UINT) { return lp; } + inline LPCWSTR T2CW_EX_DEF(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR W2CT_EX(__in_opt LPCWSTR lp, UINT) { return lp; } + inline LPCTSTR W2CT_EX_DEF(__in_opt LPCWSTR lp) { return lp; } + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + #define T2A W2A + #define A2T A2W + inline LPWSTR T2W(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR W2T(__in_opt LPWSTR lp) { return lp; } + #define T2CA W2CA + #define A2CT A2CW + inline LPCWSTR T2CW(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR W2CT(__in_opt LPCWSTR lp) { return lp; } + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#else // !defined(_UNICODE) + + #define T2W_EX A2W_EX + #define T2W_EX_DEF A2W_EX_DEF + #define W2T_EX W2A_EX + #define W2T_EX_DEF W2A_EX_DEF + inline LPSTR T2A_EX(__in_opt LPTSTR lp, UINT) { return lp; } + inline LPSTR T2A_EX_DEF(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR A2T_EX(__in_opt LPSTR lp, UINT) { return lp; } + inline LPTSTR A2T_EX_DEF(__in_opt LPSTR lp) { return lp; } + #define T2CW_EX A2CW_EX + #define T2CW_EX_DEF A2CW_EX_DEF + #define W2CT_EX W2CA_EX + #define W2CT_EX_DEF W2CA_EX_DEF + inline LPCSTR T2CA_EX(__in_opt LPCTSTR lp, UINT) { return lp; } + inline LPCSTR T2CA_EX_DEF(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR A2CT_EX(__in_opt LPCSTR lp, UINT) { return lp; } + inline LPCTSTR A2CT_EX_DEF(__in_opt LPCSTR lp) { return lp; } + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + #define T2W A2W + #define W2T W2A + inline LPSTR T2A(__in_opt LPTSTR lp) { return lp; } + inline LPTSTR A2T(__in_opt LPSTR lp) { return lp; } + #define T2CW A2CW + #define W2CT W2CA + inline LPCSTR T2CA(__in_opt LPCTSTR lp) { return lp; } + inline LPCTSTR A2CT(__in_opt LPCSTR lp) { return lp; } + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#endif // defined(_UNICODE) + +inline __checkReturn BSTR A2WBSTR(__in_opt LPCSTR lp, int nLen = -1) +{ + if (lp == NULL || nLen == 0) + return NULL; + USES_CONVERSION_EX; + BSTR str = NULL; + int nConvertedLen = MultiByteToWideChar(_acp_ex, 0, lp, + nLen, NULL, NULL); + int nAllocLen = nConvertedLen; + if (nLen == -1) + nAllocLen -= 1; // Don't allocate terminating '\0' + str = ::SysAllocStringLen(NULL, nAllocLen); + + if (str != NULL) + { + int nResult; + nResult = MultiByteToWideChar(_acp_ex, 0, lp, nLen, str, nConvertedLen); + ATLASSERT(nResult == nConvertedLen); + if(nResult != nConvertedLen) + { + SysFreeString(str); + return NULL; + } + + } + return str; +} + +inline BSTR OLE2BSTR(__in_opt LPCOLESTR lp) {return ::SysAllocString(lp);} +#if defined(_UNICODE) +// in these cases the default (TCHAR) is the same as OLECHAR + inline BSTR T2BSTR_EX(__in_opt LPCTSTR lp) {return ::SysAllocString(lp);} + inline BSTR A2BSTR_EX(__in_opt LPCSTR lp) {return A2WBSTR(lp);} + inline BSTR W2BSTR_EX(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + inline BSTR T2BSTR(__in_opt LPCTSTR lp) {return ::SysAllocString(lp);} + inline BSTR A2BSTR(__in_opt LPCSTR lp) {return A2WBSTR(lp);} + inline BSTR W2BSTR(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#else // !defined(_UNICODE) + inline BSTR T2BSTR_EX(__in_opt LPCTSTR lp) {return A2WBSTR(lp);} + inline BSTR A2BSTR_EX(__in_opt LPCSTR lp) {return A2WBSTR(lp);} + inline BSTR W2BSTR_EX(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + + inline BSTR T2BSTR(__in_opt LPCTSTR lp) {return A2WBSTR(lp);} + inline BSTR A2BSTR(__in_opt LPCSTR lp) {return A2WBSTR(lp);} + inline BSTR W2BSTR(__in_opt LPCWSTR lp) {return ::SysAllocString(lp);} + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#endif // defined(_UNICODE) + +#ifdef _WINGDI_ +///////////////////////////////////////////////////////////////////////////// +// Global UNICODE<>ANSI translation helpers +inline LPDEVMODEW AtlDevModeA2W(__out LPDEVMODEW lpDevModeW, __in const DEVMODEA* lpDevModeA) +{ + USES_CONVERSION_EX; + ATLASSERT(lpDevModeW != NULL); + if (lpDevModeA == NULL || lpDevModeW == NULL) + { + return NULL; + } + + AtlA2WHelper(lpDevModeW->dmDeviceName, (LPCSTR)lpDevModeA->dmDeviceName, 32, _acp_ex); + +#if _SECURE_ATL + if(0 != memcpy_s(&lpDevModeW->dmSpecVersion, offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion), + &lpDevModeA->dmSpecVersion, offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion))) + { + return NULL; + } +#else + memcpy(&lpDevModeW->dmSpecVersion, &lpDevModeA->dmSpecVersion, + offsetof(DEVMODEW, dmFormName) - offsetof(DEVMODEW, dmSpecVersion)); +#endif + + AtlA2WHelper(lpDevModeW->dmFormName, (LPCSTR)lpDevModeA->dmFormName, 32, _acp_ex); + +#if _SECURE_ATL + if(0 != memcpy_s(&lpDevModeW->dmLogPixels, sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels), + &lpDevModeA->dmLogPixels, sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels))) + { + return NULL; + } +#else + memcpy(&lpDevModeW->dmLogPixels, &lpDevModeA->dmLogPixels, + sizeof(DEVMODEW) - offsetof(DEVMODEW, dmLogPixels)); +#endif + + if (lpDevModeA->dmDriverExtra != 0) + { + // lpDevModeW holds more info +#pragma warning(push) +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable:26000) +#endif +#if _SECURE_ATL + if(0 != memcpy_s(lpDevModeW+1, lpDevModeA->dmDriverExtra, lpDevModeA+1, lpDevModeA->dmDriverExtra)) + { + return NULL; + } +#else + memcpy(lpDevModeW+1, lpDevModeA+1, lpDevModeA->dmDriverExtra); +#endif +#pragma warning(pop) + } + lpDevModeW->dmSize = sizeof(DEVMODEW); + return lpDevModeW; +} + +inline LPTEXTMETRICW AtlTextMetricA2W(__out LPTEXTMETRICW lptmW, __in LPTEXTMETRICA lptmA) +{ + USES_CONVERSION_EX; + ATLASSERT(lptmW != NULL); + if (lptmA == NULL || lptmW == NULL) + return NULL; + +#if _SECURE_ATL + if(0 != memcpy_s(lptmW, sizeof(LONG) * 11, lptmA, sizeof(LONG) * 11)) + { + return NULL; + } +#else + memcpy(lptmW, lptmA, sizeof(LONG) * 11); +#endif + +#if _SECURE_ATL + if(0 != memcpy_s(&lptmW->tmItalic, sizeof(BYTE) * 5, &lptmA->tmItalic, sizeof(BYTE) * 5)) + { + return NULL; + } +#else + memcpy(&lptmW->tmItalic, &lptmA->tmItalic, sizeof(BYTE) * 5); +#endif + + if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmFirstChar, 1, &lptmW->tmFirstChar, 1) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmLastChar, 1, &lptmW->tmLastChar, 1) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmDefaultChar, 1, &lptmW->tmDefaultChar, 1)== 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(MultiByteToWideChar(_acp_ex, 0, (LPCSTR)&lptmA->tmBreakChar, 1, &lptmW->tmBreakChar, 1) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + return lptmW; +} + +inline LPTEXTMETRICA AtlTextMetricW2A(__out LPTEXTMETRICA lptmA, __in LPTEXTMETRICW lptmW) +{ + USES_CONVERSION_EX; + ATLASSERT(lptmA != NULL); + if (lptmW == NULL || lptmA == NULL) + { + return NULL; + } + +#if _SECURE_ATL + if(0 != memcpy_s(lptmA, sizeof(LONG) * 11, lptmW, sizeof(LONG) * 11)) + { + return NULL; + } +#else + memcpy(lptmA, lptmW, sizeof(LONG) * 11); +#endif + +#if _SECURE_ATL + if(0 != memcpy_s(&lptmA->tmItalic, sizeof(BYTE) * 5, &lptmW->tmItalic, sizeof(BYTE) * 5)) + { + return NULL; + } +#else + memcpy(&lptmA->tmItalic, &lptmW->tmItalic, sizeof(BYTE) * 5); +#endif + + if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmFirstChar, 1, (LPSTR)&lptmA->tmFirstChar, 1, NULL, NULL) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmLastChar, 1, (LPSTR)&lptmA->tmLastChar, 1, NULL, NULL) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmDefaultChar, 1, (LPSTR)&lptmA->tmDefaultChar, 1, NULL, NULL) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + if(WideCharToMultiByte(_acp_ex, 0, &lptmW->tmBreakChar, 1, (LPSTR)&lptmA->tmBreakChar, 1, NULL, NULL) == 0) + { + ATLASSERT(FALSE); + return NULL; + } + + return lptmA; +} + +#ifndef ATLDEVMODEA2W +#define ATLDEVMODEA2W AtlDevModeA2W +#define ATLDEVMODEW2A AtlDevModeW2A +#define ATLTEXTMETRICA2W AtlTextMetricA2W +#define ATLTEXTMETRICW2A AtlTextMetricW2A +#endif + +// Requires USES_CONVERSION_EX or USES_ATL_SAFE_ALLOCA macro before using the _EX versions of the macros +#define DEVMODEW2A_EX(lpw)\ + (((lpw) == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)_ATL_SAFE_ALLOCA(sizeof(DEVMODEA)+(lpw)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpw))) +#define DEVMODEA2W_EX(lpa)\ + (((lpa) == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)_ATL_SAFE_ALLOCA(sizeof(DEVMODEW)+(lpa)->dmDriverExtra, _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lpa))) +#define TEXTMETRICW2A_EX(lptmw)\ + (((lptmw) == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICA), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptmw))) +#define TEXTMETRICA2W_EX(lptma)\ + (((lptma) == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)_ATL_SAFE_ALLOCA(sizeof(TEXTMETRICW), _ATL_SAFE_ALLOCA_DEF_THRESHOLD), (lptma))) + +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + +#define DEVMODEW2A(lpw)\ + ((lpw == NULL) ? NULL : ATLDEVMODEW2A((LPDEVMODEA)alloca(sizeof(DEVMODEA)+lpw->dmDriverExtra), lpw)) +#define DEVMODEA2W(lpa)\ + ((lpa == NULL) ? NULL : ATLDEVMODEA2W((LPDEVMODEW)alloca(sizeof(DEVMODEW)+lpa->dmDriverExtra), lpa)) +#define TEXTMETRICW2A(lptmw)\ + ((lptmw == NULL) ? NULL : ATLTEXTMETRICW2A((LPTEXTMETRICA)alloca(sizeof(TEXTMETRICA)), lptmw)) +#define TEXTMETRICA2W(lptma)\ + ((lptma == NULL) ? NULL : ATLTEXTMETRICA2W((LPTEXTMETRICW)alloca(sizeof(TEXTMETRICW)), lptma)) + +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#define DEVMODEOLE DEVMODEW +#define LPDEVMODEOLE LPDEVMODEW +#define TEXTMETRICOLE TEXTMETRICW +#define LPTEXTMETRICOLE LPTEXTMETRICW + +#if defined(_UNICODE) +// in these cases the default (TCHAR) is the same as OLECHAR + inline LPDEVMODEW DEVMODEOLE2T_EX(LPDEVMODEOLE lp) { return lp; } + inline LPDEVMODEOLE DEVMODET2OLE_EX(LPDEVMODEW lp) { return lp; } + inline LPTEXTMETRICW TEXTMETRICOLE2T_EX(LPTEXTMETRICOLE lp) { return lp; } + inline LPTEXTMETRICOLE TEXTMETRICT2OLE_EX(LPTEXTMETRICW lp) { return lp; } +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + inline LPDEVMODEW DEVMODEOLE2T(LPDEVMODEOLE lp) { return lp; } + inline LPDEVMODEOLE DEVMODET2OLE(LPDEVMODEW lp) { return lp; } + inline LPTEXTMETRICW TEXTMETRICOLE2T(LPTEXTMETRICOLE lp) { return lp; } + inline LPTEXTMETRICOLE TEXTMETRICT2OLE(LPTEXTMETRICW lp) { return lp; } +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#else // !defined(_UNICODE) + #define DEVMODEOLE2T_EX(lpo) DEVMODEW2A_EX(lpo) + #define DEVMODET2OLE_EX(lpa) DEVMODEA2W_EX(lpa) + #define TEXTMETRICOLE2T_EX(lptmw) TEXTMETRICW2A_EX(lptmw) + #define TEXTMETRICT2OLE_EX(lptma) TEXTMETRICA2W_EX(lptma) +#ifndef _ATL_EX_CONVERSION_MACROS_ONLY + #define DEVMODEOLE2T(lpo) DEVMODEW2A(lpo) + #define DEVMODET2OLE(lpa) DEVMODEA2W(lpa) + #define TEXTMETRICOLE2T(lptmw) TEXTMETRICW2A(lptmw) + #define TEXTMETRICT2OLE(lptma) TEXTMETRICA2W(lptma) +#endif // _ATL_EX_CONVERSION_MACROS_ONLY + +#endif // defined(_UNICODE) + +#endif //_WINGDI_ + +#pragma pack(pop) + +///////////////////////////////////////////////////////////////////////////// + +#ifndef _ATL_DLL + +#ifdef _WINGDI_ + +ATLINLINE ATLAPI_(LPDEVMODEA) AtlDevModeW2A(__out LPDEVMODEA lpDevModeA, __in const DEVMODEW* lpDevModeW) +{ + USES_CONVERSION_EX; + ATLASSERT(lpDevModeA != NULL); + if (lpDevModeW == NULL || lpDevModeA == NULL) + return NULL; + + AtlW2AHelper((LPSTR)lpDevModeA->dmDeviceName, lpDevModeW->dmDeviceName, 32, _acp_ex); + +#if _SECURE_ATL + if(0 != memcpy_s(&lpDevModeA->dmSpecVersion, offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion), + &lpDevModeW->dmSpecVersion, offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion))) + { + return NULL; + } +#else + memcpy(&lpDevModeA->dmSpecVersion, &lpDevModeW->dmSpecVersion, + offsetof(DEVMODEA, dmFormName) - offsetof(DEVMODEA, dmSpecVersion)); +#endif + + AtlW2AHelper((LPSTR)lpDevModeA->dmFormName, lpDevModeW->dmFormName, 32, _acp_ex); + +#if _SECURE_ATL + if(0 != memcpy_s(&lpDevModeA->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels), + &lpDevModeW->dmLogPixels, sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels))) + { + return NULL; + } +#else + memcpy(&lpDevModeA->dmLogPixels, &lpDevModeW->dmLogPixels, + sizeof(DEVMODEA) - offsetof(DEVMODEA, dmLogPixels)); +#endif + + if (lpDevModeW->dmDriverExtra != 0) + { + // lpDevModeW holds more info +#pragma warning(push) +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable:26000) +#endif +#if _SECURE_ATL + if(0 != memcpy_s(lpDevModeA+1, lpDevModeW->dmDriverExtra, lpDevModeW+1, lpDevModeW->dmDriverExtra)) + { + return NULL; + } +#else + memcpy(lpDevModeA+1, lpDevModeW+1, lpDevModeW->dmDriverExtra); +#endif +#pragma warning(pop) + } + + lpDevModeA->dmSize = sizeof(DEVMODEA); + return lpDevModeA; +} + +#endif //_WINGDI + +#endif // !_ATL_DLL + +// +// [pfx_parse] - workaround for old PREfix/PREfast parser +// +#if (defined(_PREFIX_) || defined(_PREFAST_)) && (_MSC_VER < 1400) +#pragma warning (pop) +#endif // old PREfast parser + +#ifndef _ATL_NO_PRAGMA_WARNINGS +#pragma warning (pop) +#endif //!_ATL_NO_PRAGMA_WARNINGS + +#endif // __ATLCONV_H__ + diff --git a/c/jacob/include/atlcore.h b/c/jacob/include/atlcore.h new file mode 100644 index 0000000..2313070 --- /dev/null +++ b/c/jacob/include/atlcore.h @@ -0,0 +1,554 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLCORE_H__ +#define __ATLCORE_H__ + +#pragma once + +#ifdef _ATL_ALL_WARNINGS +#pragma warning( push ) +#endif + +#pragma warning(disable: 4786) // identifier was truncated in the debug information +#pragma warning(disable: 4127) // constant expression + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ +///////////////////////////////////////////////////////////////////////////// +// Verify that a null-terminated string points to valid memory +inline BOOL AtlIsValidString(LPCWSTR psz, size_t nMaxLength = INT_MAX) +{ + (nMaxLength); + return (psz != NULL); +} + +// Verify that a null-terminated string points to valid memory +inline BOOL AtlIsValidString(LPCSTR psz, size_t nMaxLength = UINT_MAX) +{ + (nMaxLength); + return (psz != NULL); +} + +// Verify that a pointer points to valid memory +inline BOOL AtlIsValidAddress(const void* p, size_t nBytes, + BOOL bReadWrite = TRUE) +{ + (bReadWrite); + (nBytes); + return (p != NULL); +} + +template +inline void AtlAssertValidObject(const T *pOb) +{ + ATLASSERT(pOb); + ATLASSERT(AtlIsValidAddress(pOb, sizeof(T))); + if(pOb) + pOb->AssertValid(); +} +#ifdef _DEBUG +#define ATLASSERT_VALID(x) ATL::AtlAssertValidObject(x) +#else +#define ATLASSERT_VALID(x) __noop; +#endif + +// COM Sync Classes +class CComCriticalSection +{ +public: + CComCriticalSection() throw() + { + memset(&m_sec, 0, sizeof(CRITICAL_SECTION)); + } + ~CComCriticalSection() + { + } + HRESULT Lock() throw() + { + EnterCriticalSection(&m_sec); + return S_OK; + } + HRESULT Unlock() throw() + { + LeaveCriticalSection(&m_sec); + return S_OK; + } + HRESULT Init() throw() + { + HRESULT hRes = E_FAIL; + __try + { + InitializeCriticalSection(&m_sec); + hRes = S_OK; + } + // structured exception may be raised in low memory situations + __except(STATUS_NO_MEMORY == GetExceptionCode()) + { + hRes = E_OUTOFMEMORY; + } + return hRes; + } + + HRESULT Term() throw() + { + DeleteCriticalSection(&m_sec); + return S_OK; + } + CRITICAL_SECTION m_sec; +}; + +class CComAutoCriticalSection : public CComCriticalSection +{ +public: + CComAutoCriticalSection() + { + HRESULT hr = CComCriticalSection::Init(); + if (FAILED(hr)) + AtlThrow(hr); + } + ~CComAutoCriticalSection() throw() + { + CComCriticalSection::Term(); + } +private : + HRESULT Init(); // Not implemented. CComAutoCriticalSection::Init should never be called + HRESULT Term(); // Not implemented. CComAutoCriticalSection::Term should never be called +}; + +class CComSafeDeleteCriticalSection : public CComCriticalSection +{ +public: + CComSafeDeleteCriticalSection(): m_bInitialized(false) + { + } + + ~CComSafeDeleteCriticalSection() throw() + { + if (!m_bInitialized) + { + return; + } + m_bInitialized = false; + CComCriticalSection::Term(); + } + + HRESULT Init() throw() + { + ATLASSERT( !m_bInitialized ); + HRESULT hr = CComCriticalSection::Init(); + if (SUCCEEDED(hr)) + { + m_bInitialized = true; + } + return hr; + } + + HRESULT Term() throw() + { + if (!m_bInitialized) + { + return S_OK; + } + m_bInitialized = false; + return CComCriticalSection::Term(); + } + + HRESULT Lock() + { + // CComSafeDeleteCriticalSection::Init or CComAutoDeleteCriticalSection::Init + // not called or failed. + // m_critsec member of CComObjectRootEx is now of type + // CComAutoDeleteCriticalSection. It has to be initialized + // by calling CComObjectRootEx::_AtlInitialConstruct + ATLASSUME(m_bInitialized); + return CComCriticalSection::Lock(); + } + +private: + bool m_bInitialized; +}; + +class CComAutoDeleteCriticalSection : public CComSafeDeleteCriticalSection +{ +private: + // CComAutoDeleteCriticalSection::Term should never be called + HRESULT Term() throw(); +}; + +class CComFakeCriticalSection +{ +public: + HRESULT Lock() throw() { return S_OK; } + HRESULT Unlock() throw() { return S_OK; } + HRESULT Init() throw() { return S_OK; } + HRESULT Term() throw() { return S_OK; } +}; + +///////////////////////////////////////////////////////////////////////////// +// Module + +// Used by any project that uses ATL +struct _ATL_BASE_MODULE70 +{ + UINT cbSize; + HINSTANCE m_hInst; + HINSTANCE m_hInstResource; + bool m_bNT5orWin98; + DWORD dwAtlBuildVer; + const GUID* pguidVer; + CComCriticalSection m_csResource; + CSimpleArray m_rgResourceInstance; +}; +typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE; + +class CAtlBaseModule : public _ATL_BASE_MODULE +{ +public : + static bool m_bInitFailed; + CAtlBaseModule() throw(); + ~CAtlBaseModule() throw (); + + HINSTANCE GetModuleInstance() throw() + { + return m_hInst; + } + HINSTANCE GetResourceInstance() throw() + { + return m_hInstResource; + } + HINSTANCE SetResourceInstance(HINSTANCE hInst) throw() + { + return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst)); + } + + bool AddResourceInstance(HINSTANCE hInst) throw(); + bool RemoveResourceInstance(HINSTANCE hInst) throw(); + HINSTANCE GetHInstanceAt(int i) throw(); +}; + +__declspec(selectany) bool CAtlBaseModule::m_bInitFailed = false; +extern CAtlBaseModule _AtlBaseModule; + +///////////////////////////////////////////////////////////////////////////// +// String resource helpers + +#pragma warning(push) +#pragma warning(disable: 4200) + struct ATLSTRINGRESOURCEIMAGE + { + WORD nLength; + __field_ecount(nLength) WCHAR achString[]; + }; +#pragma warning(pop) // C4200 + +inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage( HINSTANCE hInstance, HRSRC hResource, UINT id ) throw() +{ + const ATLSTRINGRESOURCEIMAGE* pImage; + const ATLSTRINGRESOURCEIMAGE* pImageEnd; + ULONG nResourceSize; + HGLOBAL hGlobal; + UINT iIndex; + + hGlobal = ::LoadResource( hInstance, hResource ); + if( hGlobal == NULL ) + { + return( NULL ); + } + + pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource( hGlobal ); + if( pImage == NULL ) + { + return( NULL ); + } + + nResourceSize = ::SizeofResource( hInstance, hResource ); + pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+nResourceSize); + iIndex = id&0x000f; + + while( (iIndex > 0) && (pImage < pImageEnd) ) + { + pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE( pImage )+(sizeof( ATLSTRINGRESOURCEIMAGE )+(pImage->nLength*sizeof( WCHAR )))); + iIndex--; + } + if( pImage >= pImageEnd ) + { + return( NULL ); + } + if( pImage->nLength == 0 ) + { + return( NULL ); + } + + return( pImage ); +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id ) throw() +{ + HRSRC hResource; + + hResource = ::FindResource( hInstance, MAKEINTRESOURCE( ((id>>4)+1) ), RT_STRING ); + if( hResource == NULL ) + { + return( NULL ); + } + + return _AtlGetStringResourceImage( hInstance, hResource, id ); +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( HINSTANCE hInstance, UINT id, WORD wLanguage ) throw() +{ + HRSRC hResource; + + hResource = ::FindResourceEx( hInstance, RT_STRING, MAKEINTRESOURCE( ((id>>4)+1) ), wLanguage ); + if( hResource == NULL ) + { + return( NULL ); + } + + return _AtlGetStringResourceImage( hInstance, hResource, id ); +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id ) throw() +{ + const ATLSTRINGRESOURCEIMAGE* p = NULL; + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + + for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + p = AtlGetStringResourceImage(hInst, id); + } + return p; +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( UINT id, WORD wLanguage ) throw() +{ + const ATLSTRINGRESOURCEIMAGE* p = NULL; + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + + for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + p = AtlGetStringResourceImage(hInst, id, wLanguage); + } + return p; +} + +inline int AtlLoadString(__in UINT nID, __out_ecount_part_z(nBufferMax, return + 1) LPTSTR lpBuffer, __in int nBufferMax) throw() +{ + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + int nRet = 0; + + for (int i = 1; hInst != NULL && nRet == 0; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + nRet = LoadString(hInst, nID, lpBuffer, nBufferMax); + } + return nRet; +} + +inline HINSTANCE AtlFindResourceInstance(LPCTSTR lpName, LPCTSTR lpType, WORD wLanguage = 0) throw() +{ + ATLASSERT(lpType != RT_STRING); // Call AtlFindStringResourceInstance to find the string + if (lpType == RT_STRING) + return NULL; + + if (ATL_IS_INTRESOURCE(lpType)) + { + /* Prefast false warnings caused by bad-shaped definition of MAKEINTRESOURCE macro from PSDK */ + if (lpType == ATL_RT_ICON) + { + lpType = ATL_RT_GROUP_ICON; + } + else if (lpType == ATL_RT_CURSOR) + { + lpType = ATL_RT_GROUP_CURSOR; + } + } + + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + HRSRC hResource = NULL; + + for (int i = 1; hInst != NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + hResource = ::FindResourceEx(hInst, lpType, lpName, wLanguage); + if (hResource != NULL) + { + return hInst; + } + } + + return NULL; +} + +inline HINSTANCE AtlFindResourceInstance(UINT nID, LPCTSTR lpType, WORD wLanguage = 0) throw() +{ + return AtlFindResourceInstance(MAKEINTRESOURCE(nID), lpType, wLanguage); +} + +inline HINSTANCE AtlFindStringResourceInstance(UINT nID, WORD wLanguage = 0) throw() +{ + const ATLSTRINGRESOURCEIMAGE* p = NULL; + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + + for (int i = 1; hInst != NULL && p == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + p = AtlGetStringResourceImage(hInst, nID, wLanguage); + if (p != NULL) + return hInst; + } + + return NULL; +} + +/* +Needed by both atlcomcli and atlsafe, so needs to be in here +*/ +inline HRESULT AtlSafeArrayGetActualVartype +( + SAFEARRAY *psaArray, + VARTYPE *pvtType +) +{ + HRESULT hrSystem=::SafeArrayGetVartype(psaArray, pvtType); + + if(FAILED(hrSystem)) + { + return hrSystem; + } + + /* + When Windows has a SAFEARRAY of type VT_DISPATCH with FADF_HAVEIID, + it returns VT_UNKNOWN instead of VT_DISPATCH. We patch the value to be correct + */ + if(pvtType && *pvtType==VT_UNKNOWN) + { + if(psaArray && ((psaArray->fFeatures & FADF_HAVEIID)!=0)) + { + if(psaArray->fFeatures & FADF_DISPATCH) + { + *pvtType=VT_DISPATCH; + } + } + } + + return hrSystem; +} +template +inline _CharType* AtlCharNext(const _CharType* p) throw() +{ + ATLASSUME(p != NULL); // Too expensive to check separately here + if (*p == '\0') // ::CharNextA won't increment if we're at a \0 already + return const_cast<_CharType*>(p+1); + else + return ::CharNextA(p); +} + +template <> +inline wchar_t* AtlCharNext(const wchar_t* p) throw() +{ + return const_cast< wchar_t* >( p+1 ); +} +template +inline const CharType* AtlstrchrT(const CharType* p, CharType ch) throw() +{ + ATLASSERT(p != NULL); + if(p==NULL) + { + return NULL; + } + while( *p != 0 ) + { + if (*p == ch) + { + return p; + } + p = AtlCharNext(p); + } + //strchr for '\0' should succeed - the while loop terminates + //*p == 0, but ch also == 0, so NULL terminator address is returned + return (*p == ch) ? p : NULL; +} +//Ansi and Unicode versions of printf, used with templated CharType trait classes. +#pragma warning(push) +#pragma warning(disable : 4793) +template +inline int AtlprintfT(const CharType* pszFormat,... ) throw() +{ + int retval=0; + va_list argList; + va_start( argList, pszFormat ); + retval=vprintf(pszFormat,argList); + va_end( argList ); + return retval; +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) +template<> +inline int AtlprintfT(const wchar_t* pszFormat,... ) throw() +{ + int retval=0; + va_list argList; + va_start( argList, pszFormat ); + retval=vwprintf(pszFormat, argList); + va_end( argList ); + return retval; +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4068 28110) + +inline BOOL AtlConvertSystemTimeToVariantTime(const SYSTEMTIME& systimeSrc,double* pVarDtTm) +{ + ATLENSURE(pVarDtTm!=NULL); + //Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then + //convert variant time back to system time and compare to original system time. + + BOOL ok = ::SystemTimeToVariantTime(const_cast(&systimeSrc), pVarDtTm); + + SYSTEMTIME sysTime; + ::ZeroMemory(&sysTime, sizeof(SYSTEMTIME)); + + ok = ok && ::VariantTimeToSystemTime(*pVarDtTm, &sysTime); + ok = ok && (systimeSrc.wYear == sysTime.wYear && + systimeSrc.wMonth == sysTime.wMonth && + systimeSrc.wDay == sysTime.wDay && + systimeSrc.wHour == sysTime.wHour && + systimeSrc.wMinute == sysTime.wMinute && + systimeSrc.wSecond == sysTime.wSecond); + + return ok; +} +#pragma warning(pop) + +///////////////////////////////////////////////////////////////////////////// + +} // namespace ATL +#pragma pack(pop) + +#ifdef _ATL_ALL_WARNINGS +#pragma warning( pop ) +#endif + +#endif // __ATLCORE_H__ + diff --git a/c/jacob/include/atldef.h b/c/jacob/include/atldef.h new file mode 100644 index 0000000..bfd2bce --- /dev/null +++ b/c/jacob/include/atldef.h @@ -0,0 +1,668 @@ + +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLDEF_H__ +#define __ATLDEF_H__ + +#pragma once + +#pragma warning(disable : 4619) // there is no warning number + +#include +#include +#include + +#ifndef RC_INVOKED + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifdef UNDER_CE + #error This version of ATL is not currently supported for CE. Look for the CE specific version. +#endif + +// If you are mixing compilation units that are built as +// native code with those that are built /clr, you must define +// the symbol '_ATL_MIXED'. _ATL_MIXED must be defined for all +// compilation units in an executable or it must be defined for none of them. +#if !defined(_ATL_MIXED) +namespace Inconsistent_definition_of_symbol__ATL_MIXED +{ + struct _Please_define_it_the_same_throughout_your_project { }; +} +#else +namespace Inconsistent_definition_of_symbol__ATL_MIXED +{ +#ifdef _M_IX86 +#pragma comment(linker, "/include:??3@YAXPAX@Z") +#else +#pragma comment(linker, "/include:??3@YAXPEAX@Z") +#endif + struct _Please_define_it_the_same_throughout_your_project { virtual void one(){} }; +} +#endif +namespace Inconsistent_definition_of_symbol__ATL_MIXED +{ + __declspec(selectany) _Please_define_it_the_same_throughout_your_project clash = _Please_define_it_the_same_throughout_your_project (); +} + +#if !defined(_ATL_MIXED) +namespace Define_the_symbol__ATL_MIXED +{ +#if defined(_M_CEE) + struct Thank_you { }; +#else +#ifdef _M_IX86 +#pragma comment(linker, "/include:??3@YAXPAX@Z") +#else +#pragma comment(linker, "/include:??3@YAXPEAX@Z") +#endif + struct Thank_you { virtual void one(){} }; +#endif + __declspec(selectany) Thank_you clash = Thank_you(); +} +#endif + +#if defined(_ATL_MIXED) +#define _ATL_NATIVE_INITIALIZATION +#endif + +#if !defined(_M_CEE) +#define _ATL_NATIVE_INITIALIZATION +#endif + +#ifdef _UNICODE +#ifndef UNICODE +#define UNICODE // UNICODE is used by Windows headers +#endif +#endif + +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE // _UNICODE is used by C-runtime/MFC headers +#endif +#endif + +#ifdef _DEBUG +#ifndef DEBUG +#define DEBUG +#endif +#endif + +#ifdef _WIN64 +#define _ATL_SUPPORT_VT_I8 // Always support VT_I8 on Win64. +#endif + +#if !defined(UNALIGNED) +#if defined(_M_IA64) || defined(_M_AMD64) +#define UNALIGNED __unaligned +#else +#define UNALIGNED +#endif +#endif + +#if !defined(_countof) +#if !defined(__cplusplus) +#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0])) +#else +extern "C++" +{ +template +char (*__countof_helper(UNALIGNED _CountofType (&_Array)[_SizeOfArray]))[_SizeOfArray]; +#define _countof(_Array) sizeof(*__countof_helper(_Array)) +} +#endif +#endif + +#ifndef AtlThrow +#ifndef _ATL_CUSTOM_THROW +#define AtlThrow ATL::AtlThrowImpl +#endif +#endif // AtlThrow + +#ifndef ATLASSERT +#define ATLASSERT(expr) _ASSERTE(expr) +#endif // ATLASSERT + +/* +Why does ATLASSUME exist? + +ATL 8 has two existing validation models + +ATLASSERT/ATLVERIFY - These are used to make sure a debug build reports a problem with the expression/invariant +ATLENSURE - Debug is the same as ATLVERIFY, retail throws a C++ exception + +We added ATLENSURE because there were too many unreported error paths in ATL and we wanted to bail out of more +error conditions rather than just trying to continue in retail. + +There might be a case for changing 'lots' of ATLASSERT to ATLENSURE, but we chose an incremental approach and only +changed over where we saw a problem with code reported from a customer or test case. This reduces code churn in our +code for this version. + +In general, our approach is to try to make sure that when something goes wrong +- the client does not continue to run, because we report an error condition +- debug builds see an assertion about the problem + +Sometimes we have code like + +HRESULT ComMethod(void) +{ + ATLASSUME(m_pFoo); + return m_pFoo->Method(); +} + +We could add + if(!m_pFoo) return E_POINTER; + +But this is very unlikely to help, since it removes the ability of the developer to debug this problem if it's seen in a retail +build of the application. + +We could try something more severe + + if(!m_pFoo) terminate(); // or your favourite shutdown function + +This would ensure good reporting (because VC8 terminate generates a Windows Error Report and crash dump), but hardly seems a big win +over the previous crash. + +ATLENSURE might seem slightly better. It is debuggable and consistent with ATL in general. In fact, many parts of ATL do just this. +But in this specific context, it doesn't look like a great choice. COM methods should not in general be emitting native C++ exceptions +as an error reporting strategy. + +So we find ourselves in a quandry. For these kinds of methods, the traditional code (ATLASSERT followed by a crash), seems be the most +debuggable thing to do in this situation. At least for VS8, we have decided to stick with this shape. + +--- + +Now consider the impact of cl /analyze. We want cl /analyze to not warn about our potential dereferences when they refer to member variables +whose state was previously validated by another method. But we do want to see the impact of function contracts on the parameters of the +function. + +So we've done a broad replace of all the member-related ATLASSERT to ATLASSUME. + +*/ + +#ifndef ATLASSUME +#define ATLASSUME(expr) do { ATLASSERT(expr); __analysis_assume(!!(expr)); } while(0) +#endif // ATLASSERT + +#ifndef ATLVERIFY +#ifdef _DEBUG +#define ATLVERIFY(expr) ATLASSERT(expr) +#else +#define ATLVERIFY(expr) (expr) +#endif // DEBUG +#endif // ATLVERIFY + +#ifndef ATLENSURE_THROW +#define ATLENSURE_THROW(expr, hr) \ +do { \ + int __atl_condVal=!!(expr); \ + ATLASSERT(__atl_condVal); \ + if(!(__atl_condVal)) AtlThrow(hr); \ +} while (0) +#endif // ATLENSURE + +#ifndef ATLENSURE +#define ATLENSURE(expr) ATLENSURE_THROW(expr, E_FAIL) +#endif // ATLENSURE + +#ifndef ATLENSURE_SUCCEEDED +#define ATLENSURE_SUCCEEDED(hr) ATLENSURE_THROW(SUCCEEDED(hr), hr) +#endif // ATLENSURE + +/* Used inside COM methods that do not want to throw */ +#ifndef ATLENSURE_RETURN_HR +#define ATLENSURE_RETURN_HR(expr, hr) \ +do { \ + int __atl_condVal=!!(expr); \ + ATLASSERT(__atl_condVal); \ + if(!(__atl_condVal)) return hr; \ +} while (0) +#endif + +/* Used inside COM methods that do not want to throw */ +#ifndef ATLENSURE_RETURN +#define ATLENSURE_RETURN(expr) ATLENSURE_RETURN_HR(expr, E_FAIL) +#endif + +/* generic version that returns 2nd expr if 1st is false; no implication of HRESULT */ +#ifndef ATLENSURE_RETURN_VAL +#define ATLENSURE_RETURN_VAL ATLENSURE_RETURN_HR +#endif + +#if defined(_SECURE_ATL) +#error Do not define _SECURE_ATL. +#undef _SECURE_ATL +#endif +#define _SECURE_ATL 1 + +#if _SECURE_ATL + +#ifndef ATL_CRT_ERRORCHECK +#define ATL_CRT_ERRORCHECK(expr) AtlCrtErrorCheck(expr) +#endif // ATL_CRT_ERRORCHECK + +#ifndef ATL_CRT_ERRORCHECK_SPRINTF +#define ATL_CRT_ERRORCHECK_SPRINTF(expr) \ +do { \ + errno_t _saveErrno = errno; \ + errno = 0; \ + (expr); \ + if(0 != errno) \ + { \ + AtlCrtErrorCheck(errno); \ + } \ + else \ + { \ + errno = _saveErrno; \ + } \ +} while (0) +#endif // ATL_CRT_ERRORCHECK_SPRINTF + +#else // !_SECURE_ATL + +#define ATL_CRT_ERRORCHECK(expr) do { expr; } while (0) +#define ATL_CRT_ERRORCHECK_SPRINTF(expr) do { expr; } while (0) + +#endif // _SECURE_ATL + +/////////////////////////////////////////////////////////////////////////////// +// __declspec(novtable) is used on a class declaration to prevent the vtable +// pointer from being initialized in the constructor and destructor for the +// class. This has many benefits because the linker can now eliminate the +// vtable and all the functions pointed to by the vtable. Also, the actual +// constructor and destructor code are now smaller. +/////////////////////////////////////////////////////////////////////////////// +// This should only be used on a class that is not directly createable but is +// rather only used as a base class. Additionally, the constructor and +// destructor (if provided by the user) should not call anything that may cause +// a virtual function call to occur back on the object. +/////////////////////////////////////////////////////////////////////////////// +// By default, the wizards will generate new ATL object classes with this +// attribute (through the ATL_NO_VTABLE macro). This is normally safe as long +// the restriction mentioned above is followed. It is always safe to remove +// this macro from your class, so if in doubt, remove it. +/////////////////////////////////////////////////////////////////////////////// + +#ifdef _ATL_DISABLE_NO_VTABLE +#define ATL_NO_VTABLE +#else +#define ATL_NO_VTABLE __declspec(novtable) +#endif + +#ifdef _ATL_DISABLE_NOTHROW +#define ATL_NOTHROW +#else +#define ATL_NOTHROW __declspec(nothrow) +#endif + +#ifdef _ATL_DISABLE_FORCEINLINE +#define ATL_FORCEINLINE +#else +#define ATL_FORCEINLINE __forceinline +#endif + +#ifdef _ATL_DISABLE_NOINLINE +#define ATL_NOINLINE +#else +#define ATL_NOINLINE __declspec( noinline ) +#endif + +#if defined(_ATL_DISABLE_DEPRECATED) || (defined(_PREFAST_) && (_MSC_VER < 1400)) +#define ATL_DEPRECATED(_Message) +#else +#define ATL_DEPRECATED(_Message) __declspec( deprecated(_Message) ) +#endif + +// If ATL80.DLL is being used then _ATL_STATIC_REGISTRY doesn't really make sense +#ifdef _ATL_DLL +#undef _ATL_STATIC_REGISTRY +#else +// If not linking to ATL80.DLL, use the static registrar and not building atl.dll +#ifndef _ATL_DLL_IMPL +#ifndef _ATL_STATIC_REGISTRY +#define _ATL_STATIC_REGISTRY +#endif +#endif +#endif + +#ifdef _ATL_DEBUG_REFCOUNT +#ifndef _ATL_DEBUG_INTERFACES +#define _ATL_DEBUG_INTERFACES +#endif +#endif + +#ifdef _DEBUG +#ifndef _ATL_DEBUG +#define _ATL_DEBUG +#endif // _ATL_DEBUG +#endif // _DEBUG + +#ifdef _ATL_DEBUG_INTERFACES +#ifndef _ATL_DEBUG +#define _ATL_DEBUG +#endif // _ATL_DEBUG +#endif // _ATL_DEBUG_INTERFACES + +#ifndef _ATL_HEAPFLAGS +#ifdef _MALLOC_ZEROINIT +#define _ATL_HEAPFLAGS HEAP_ZERO_MEMORY +#else +#define _ATL_HEAPFLAGS 0 +#endif +#endif + +#ifndef _ATL_PACKING +#define _ATL_PACKING 8 +#endif + +#if defined(_ATL_DLL) + #define ATLAPI extern "C" HRESULT __declspec(dllimport) __stdcall + #define ATLAPI_(x) extern "C" __declspec(dllimport) x __stdcall + #define ATLINLINE + #define ATLAPIINL extern "C" inline HRESULT __stdcall + #define ATLAPIINL_(x) extern "C" inline x __stdcall +#elif defined(_ATL_DLL_IMPL) + #define ATLAPI extern "C" inline HRESULT __stdcall + #define ATLAPI_(x) extern "C" inline x __stdcall + #define ATLAPIINL ATLAPI + #define ATLAPIINL_(x) ATLAPI_(x) + #define ATLINLINE +#else + #define ATLAPI __declspec(nothrow) HRESULT __stdcall + #define ATLAPI_(x) __declspec(nothrow) x __stdcall + #define ATLAPIINL ATLAPI + #define ATLAPIINL_(x) ATLAPI_(x) + #define ATLINLINE inline +#endif + +#ifdef _ATL_NO_EXCEPTIONS + #ifdef _AFX + #error MFC projects cannot define _ATL_NO_EXCEPTIONS + #endif +#else + #ifndef _CPPUNWIND + #define _ATL_NO_EXCEPTIONS + #endif +#endif + +#ifdef _CPPUNWIND + +#ifndef ATLTRYALLOC + +#ifdef _AFX +#define ATLTRYALLOC(x) try{x;} catch(CException* e){e->Delete();} +#else +/* prefast noise VSW 489981 */ +#define ATLTRYALLOC(x) __pragma(warning(push)) __pragma(warning(disable: 4571)) try{x;} catch(...) {} __pragma(warning(pop)) +#endif //__AFX + +#endif //ATLTRYALLOC + +// If you define _ATLTRY before including this file, then +// you should define _ATLCATCH and _ATLRETHROW as well. +#ifndef _ATLTRY +#define _ATLTRY try +#ifdef _AFX +#define _ATLCATCH( e ) catch( CException* e ) +#else +#define _ATLCATCH( e ) catch( CAtlException e ) +#endif + +#define _ATLCATCHALL() __pragma(warning(push)) __pragma(warning(disable: 4571)) catch( ... ) __pragma(warning(pop)) + +#ifdef _AFX +#define _ATLDELETEEXCEPTION(e) e->Delete(); +#else +#define _ATLDELETEEXCEPTION(e) e; +#endif + +#define _ATLRETHROW throw +#endif // _ATLTRY + +/* +COM functions should not throw. Which means we should protect their callers from C++ exceptions leaking out. These macros +can help with that, though they have not yet been applied to the whole of ATL, which uses a variety of patterns to achieve +this end +*/ + +#ifndef _ATL_COM_BEGIN +#define _ATL_COM_BEGIN \ + HRESULT __hrAtlComMethod=S_OK; \ + try \ + { +#endif + +#ifdef _AFX +/* Nice to do something more complex here in future to translate an MFC exception to a better HR */ +#define _AFX_COM_END_PART \ + catch(CException *e) \ + { \ + if(e) \ + { \ + e->Delete(); \ + } \ + __hrAtlComMethod=E_FAIL; \ + } +#else +#define _AFX_COM_END_PART \ + catch(CAtlException e) \ + { \ + __hrAtlComMethod=e.m_hr; \ + } +#endif + +#ifndef _ATL_COM_END +#define _ATL_COM_END \ + _AFX_COM_END_PART \ + catch(...) \ + { \ + __hrAtlComMethod=E_FAIL; \ + } \ + return hr; +#endif + + + +#else //_CPPUNWIND + +#ifndef ATLTRYALLOC +#define ATLTRYALLOC(x) x; +#endif //ATLTRYALLOC + +// if _ATLTRY is defined before including this file then +// _ATLCATCH and _ATLRETHROW should be defined as well. +#ifndef _ATLTRY +#define _ATLTRY +#define _ATLCATCH( e ) __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) +#define _ATLCATCHALL() __pragma(warning(push)) __pragma(warning(disable: 4127)) if( false ) __pragma(warning(pop)) +#define _ATLDELETEEXCEPTION(e) +#define _ATLRETHROW +#endif // _ATLTRY + +#endif //_CPPUNWIND + +#ifndef ATLTRY +#define ATLTRY(x) ATLTRYALLOC(x) +#endif //ATLTRY + +#define offsetofclass(base, derived) ((DWORD_PTR)(static_cast((derived*)_ATL_PACKING))-_ATL_PACKING) + +///////////////////////////////////////////////////////////////////////////// +// Master version numbers + +#define _ATL 1 // Active Template Library +#define _ATL_VER 0x0800 // Active Template Library version 8.00 + +///////////////////////////////////////////////////////////////////////////// +// Threading + +#ifndef _ATL_SINGLE_THREADED +#ifndef _ATL_APARTMENT_THREADED +#ifndef _ATL_FREE_THREADED +#define _ATL_FREE_THREADED +#endif +#endif +#endif + +// UUIDOF +#ifndef _ATL_NO_UUIDOF +#define _ATL_IIDOF(x) __uuidof(x) +#else +#define _ATL_IIDOF(x) IID_##x +#endif + +// Lean and mean +#ifndef ATL_NO_LEAN_AND_MEAN +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMCX +#define NOMCX +#endif +#endif // ATL_NO_LEAN_AND_MEAN + +#ifdef NOSERVICE +#ifndef _ATL_NO_SERVICE +#define _ATL_NO_SERVICE +#endif // _ATL_NO_SERVICE +#else +#ifdef _ATL_NO_SERVICE +#ifndef NOSERVICE +#define NOSERVICE +#endif // NOSERVICE +#endif // _ATL_NO_SERVICE +#endif // NOSERVICE + +#include +#ifdef _DEBUG +#include +#endif +#ifndef _ATL_NO_DEBUG_CRT +// Warning: if you define the above symbol, you will have +// to provide your own definition of the ATLASSERT(x) macro +// in order to compile ATL + #include +#endif + +#endif // RC_INVOKED + +#define ATLAXWIN_CLASS "AtlAxWin80" +#define ATLAXWINLIC_CLASS "AtlAxWinLic80" + +// _ATL_INSECURE_DEPRECATE define +#ifndef _ATL_INSECURE_DEPRECATE +#if defined(_ATL_SECURE_NO_DEPRECATE) || (defined(_PREFAST_) && (_MSC_VER < 1400)) +#define _ATL_INSECURE_DEPRECATE(_Message) +#else +#define _ATL_INSECURE_DEPRECATE(_Message) __declspec(deprecated(_Message)) +#endif // _ATL_SECURE_NO_DEPRECATE +#endif // _ATL_INSECURE_DEPRECATE + +/* +This is called when something really bad happens -- so bad +that we consider it dangerous to even throw an exception +*/ +#ifndef _ATL_FATAL_SHUTDOWN +#define _ATL_FATAL_SHUTDOWN do { ::TerminateProcess(::GetCurrentProcess(), 0); } while(0); +#endif + +//ATL/MFC code should use standard pointer to member standard syntax &MyClass::MyMethod, instead +//of the legacy non-standard syntax - MyMethod. +#ifdef _ATL_ENABLE_PTM_WARNING +#define PTM_WARNING_DISABLE +#define PTM_WARNING_RESTORE +#else +#define PTM_WARNING_DISABLE \ + __pragma(warning( push )) \ + __pragma(warning( disable : 4867 )) +#define PTM_WARNING_RESTORE \ + __pragma(warning( pop )) +#endif //_ATL_ENABLE_PTM_WARNING + +/* we have to define our own versions of MAKEINTRESOURCE and IS_INTRESOURCE to + * fix warning 6268. At least until those macros are not cleanend in PSDK. + Same comes true for those definitions of constants which use the above macros +*/ +#define ATL_MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) +#define ATL_MAKEINTRESOURCEW(i) ((LPWSTR)((ULONG_PTR)((WORD)(i)))) +#ifdef UNICODE +#define ATL_MAKEINTRESOURCE ATL_MAKEINTRESOURCEW +#else +#define ATL_MAKEINTRESOURCE ATL_MAKEINTRESOURCEA +#endif // !UNICODE +#define ATL_IS_INTRESOURCE(_r) ((((ULONG_PTR)(_r)) >> 16) == 0) + +/* + * Predefined Resource Types + */ +#define ATL_RT_CURSOR ATL_MAKEINTRESOURCE(1) +#define ATL_RT_BITMAP ATL_MAKEINTRESOURCE(2) +#define ATL_RT_ICON ATL_MAKEINTRESOURCE(3) +#define ATL_RT_MENU ATL_MAKEINTRESOURCE(4) +#define ATL_RT_DIALOG ATL_MAKEINTRESOURCE(5) +#define ATL_RT_STRING ATL_MAKEINTRESOURCE(6) +#define ATL_RT_FONTDIR ATL_MAKEINTRESOURCE(7) +#define ATL_RT_FONT ATL_MAKEINTRESOURCE(8) +#define ATL_RT_ACCELERATOR ATL_MAKEINTRESOURCE(9) +#define ATL_RT_RCDATA ATL_MAKEINTRESOURCE(10) +#define ATL_RT_MESSAGETABLE ATL_MAKEINTRESOURCE(11) + +#define ATL_DIFFERENCE 11 +#define ATL_RT_GROUP_CURSOR ATL_MAKEINTRESOURCE((ULONG_PTR)ATL_RT_CURSOR + ATL_DIFFERENCE) +#define ATL_RT_GROUP_ICON ATL_MAKEINTRESOURCE((ULONG_PTR)ATL_RT_ICON + ATL_DIFFERENCE) +#define ATL_RT_VERSION ATL_MAKEINTRESOURCE(16) +#define ATL_RT_DLGINCLUDE ATL_MAKEINTRESOURCE(17) +#if(WINVER >= 0x0400) +#define ATL_RT_PLUGPLAY ATL_MAKEINTRESOURCE(19) +#define ATL_RT_VXD ATL_MAKEINTRESOURCE(20) +#define ATL_RT_ANICURSOR ATL_MAKEINTRESOURCE(21) +#define ATL_RT_ANIICON ATL_MAKEINTRESOURCE(22) +#endif /* WINVER >= 0x0400 */ +#define ATL_RT_HTML ATL_MAKEINTRESOURCE(23) +#ifdef RC_INVOKED +#define ATL_RT_MANIFEST 24 +#define ATL_CREATEPROCESS_MANIFEST_RESOURCE_ID 1 +#define ATL_ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2 +#define ATL_ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3 +#define ATL_MINIMUM_RESERVED_MANIFEST_RESOURCE_ID 1 /* inclusive */ +#define ATL_MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID 16 /* inclusive */ +#else /* RC_INVOKED */ +#define ATL_RT_MANIFEST ATL_MAKEINTRESOURCE(24) +#define ATL_CREATEPROCESS_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE( 1) +#define ATL_ISOLATIONAWARE_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(2) +#define ATL_ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(3) +#define ATL_MINIMUM_RESERVED_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE( 1 /*inclusive*/) +#define ATL_MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID ATL_MAKEINTRESOURCE(16 /*inclusive*/) +#endif /* RC_INVOKED */ + +/* sal.h stuff that is not in the current LKG */ +#ifndef __out_ecount_part_z +#define __out_ecount_part_z(size,length) __out_ecount_part(size,length) __post __nullterminated +#endif + +#ifndef __out_ecount_part_z_opt +#define __out_ecount_part_z_opt(size,length) __out_ecount_part_opt(size,length) __post __nullterminated +#endif + +#ifndef __deref_opt_out_z +#define __deref_opt_out_z __deref_opt_out __post __deref __nullterminated +#endif + +#ifndef __out_bcount_part_z +#define __out_bcount_part_z(size,length) __out_bcount_part(size,length) __post __nullterminated +#endif + +#endif // __ATLDEF_H__ + +///////////////////////////////////////////////////////////////////////////// + diff --git a/c/jacob/include/atlexcept.h b/c/jacob/include/atlexcept.h new file mode 100644 index 0000000..119208b --- /dev/null +++ b/c/jacob/include/atlexcept.h @@ -0,0 +1,123 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLEXCEPT_H__ +#define __ATLEXCEPT_H__ + +#pragma once + +#include +#include + + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ + +///////////////////////////////////////////////////////////////////////////// +// Exception raise (for functions that cannot return an error code) + +inline void __declspec(noreturn) _AtlRaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags = EXCEPTION_NONCONTINUABLE ) +{ + RaiseException( dwExceptionCode, dwExceptionFlags, 0, NULL ); +} + +class CAtlException +{ +public: + CAtlException() throw() : + m_hr( E_FAIL ) + { + } + + CAtlException( HRESULT hr ) throw() : + m_hr( hr ) + { + } + + operator HRESULT() const throw() + { + return( m_hr ); + } + +public: + HRESULT m_hr; +}; + +#ifndef _ATL_NO_EXCEPTIONS + +// Throw a CAtlException with the given HRESULT +#if defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow to throw a custom exception. +#ifdef _AFX +#error MFC projects must use default implementation of AtlThrow() +#endif +#else +ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrowImpl( HRESULT hr ) +{ + ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); +#ifdef _AFX + if( hr == E_OUTOFMEMORY ) + { + AfxThrowMemoryException(); + } + else + { + AfxThrowOleException( hr ); + } +#else + throw CAtlException( hr ); +#endif +}; +#endif + +// Throw a CAtlException corresponding to the result of ::GetLastError +ATL_NOINLINE __declspec(noreturn) inline void WINAPI AtlThrowLastWin32() +{ + DWORD dwError = ::GetLastError(); + AtlThrow( HRESULT_FROM_WIN32( dwError ) ); +} + +#else // no exception handling + +// Throw a CAtlException with the given HRESULT +#if !defined( _ATL_CUSTOM_THROW ) // You can define your own AtlThrow + +ATL_NOINLINE inline void WINAPI AtlThrowImpl( HRESULT hr ) +{ + ATLTRACE(atlTraceException, 0, _T("AtlThrow: hr = 0x%x\n"), hr ); + ATLASSERT( false ); + DWORD dwExceptionCode; + switch(hr) + { + case E_OUTOFMEMORY: + dwExceptionCode = DWORD(STATUS_NO_MEMORY); + break; + default: + dwExceptionCode = DWORD(EXCEPTION_ILLEGAL_INSTRUCTION); + break; + } + _AtlRaiseException(dwExceptionCode); +} +#endif + +// Throw a CAtlException corresponding to the result of ::GetLastError +ATL_NOINLINE inline void WINAPI AtlThrowLastWin32() +{ + DWORD dwError = ::GetLastError(); + AtlThrow( HRESULT_FROM_WIN32( dwError ) ); +} + +#endif // no exception handling + +}; // namespace ATL +#pragma pack(pop) + +#endif // __ATLEXCEPT_H__ + diff --git a/c/jacob/include/atliface.h b/c/jacob/include/atliface.h new file mode 100644 index 0000000..3736c90 --- /dev/null +++ b/c/jacob/include/atliface.h @@ -0,0 +1,2956 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0342 */ +/* at Mon Feb 12 21:31:09 2001 + */ +/* Compiler settings for atliface.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __atliface_h__ +#define __atliface_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IRegistrarBase_FWD_DEFINED__ +#define __IRegistrarBase_FWD_DEFINED__ +typedef interface IRegistrarBase IRegistrarBase; +#endif /* __IRegistrarBase_FWD_DEFINED__ */ + + +#ifndef __IRegistrar_FWD_DEFINED__ +#define __IRegistrar_FWD_DEFINED__ +typedef interface IRegistrar IRegistrar; +#endif /* __IRegistrar_FWD_DEFINED__ */ + + +#ifndef __IDocHostUIHandlerDispatch_FWD_DEFINED__ +#define __IDocHostUIHandlerDispatch_FWD_DEFINED__ +typedef interface IDocHostUIHandlerDispatch IDocHostUIHandlerDispatch; +#endif /* __IDocHostUIHandlerDispatch_FWD_DEFINED__ */ + + +#ifndef __IAxWinHostWindow_FWD_DEFINED__ +#define __IAxWinHostWindow_FWD_DEFINED__ +typedef interface IAxWinHostWindow IAxWinHostWindow; +#endif /* __IAxWinHostWindow_FWD_DEFINED__ */ + + +#ifndef __IAxWinHostWindowLic_FWD_DEFINED__ +#define __IAxWinHostWindowLic_FWD_DEFINED__ +typedef interface IAxWinHostWindowLic IAxWinHostWindowLic; +#endif /* __IAxWinHostWindowLic_FWD_DEFINED__ */ + + +#ifndef __IAxWinAmbientDispatch_FWD_DEFINED__ +#define __IAxWinAmbientDispatch_FWD_DEFINED__ +typedef interface IAxWinAmbientDispatch IAxWinAmbientDispatch; +#endif /* __IAxWinAmbientDispatch_FWD_DEFINED__ */ + + +#ifndef __IAxWinAmbientDispatchEx_FWD_DEFINED__ +#define __IAxWinAmbientDispatchEx_FWD_DEFINED__ +typedef interface IAxWinAmbientDispatchEx IAxWinAmbientDispatchEx; +#endif /* __IAxWinAmbientDispatchEx_FWD_DEFINED__ */ + + +#ifndef __IInternalConnection_FWD_DEFINED__ +#define __IInternalConnection_FWD_DEFINED__ +typedef interface IInternalConnection IInternalConnection; +#endif /* __IInternalConnection_FWD_DEFINED__ */ + + +#ifndef __IAccessibleProxy_FWD_DEFINED__ +#define __IAccessibleProxy_FWD_DEFINED__ +typedef interface IAccessibleProxy IAccessibleProxy; +#endif /* __IAccessibleProxy_FWD_DEFINED__ */ + + +#ifndef __IAccessibleServer_FWD_DEFINED__ +#define __IAccessibleServer_FWD_DEFINED__ +typedef interface IAccessibleServer IAccessibleServer; +#endif /* __IAccessibleServer_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oaidl.h" +#include "ocidl.h" +#include "oleacc.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t size); +void __RPC_USER MIDL_user_free(__inout void * ); + +/* interface __MIDL_itf_atliface_0000 */ +/* [local] */ + +EXTERN_C const CLSID CLSID_Registrar; + + +extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_atliface_0000_v0_0_s_ifspec; + +#ifndef __IRegistrarBase_INTERFACE_DEFINED__ +#define __IRegistrarBase_INTERFACE_DEFINED__ + +/* interface IRegistrarBase */ +/* [unique][helpstring][uuid][object] */ + + +EXTERN_C const IID IID_IRegistrarBase; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("e21f8a85-b05d-4243-8183-c7cb405588f7") + IRegistrarBase : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddReplacement( + /* [in] */ LPCOLESTR key, + /* [in] */ LPCOLESTR item) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearReplacements( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRegistrarBaseVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IRegistrarBase * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IRegistrarBase * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IRegistrarBase * This); + + HRESULT ( STDMETHODCALLTYPE *AddReplacement )( + IRegistrarBase * This, + /* [in] */ LPCOLESTR key, + /* [in] */ LPCOLESTR item); + + HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( + IRegistrarBase * This); + + END_INTERFACE + } IRegistrarBaseVtbl; + + interface IRegistrarBase + { + CONST_VTBL struct IRegistrarBaseVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRegistrarBase_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IRegistrarBase_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IRegistrarBase_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IRegistrarBase_AddReplacement(This,key,item) \ + (This)->lpVtbl -> AddReplacement(This,key,item) + +#define IRegistrarBase_ClearReplacements(This) \ + (This)->lpVtbl -> ClearReplacements(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IRegistrarBase_AddReplacement_Proxy( + IRegistrarBase * This, + /* [in] */ LPCOLESTR key, + /* [in] */ LPCOLESTR item); + + +void __RPC_STUB IRegistrarBase_AddReplacement_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrarBase_ClearReplacements_Proxy( + IRegistrarBase * This); + + +void __RPC_STUB IRegistrarBase_ClearReplacements_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IRegistrarBase_INTERFACE_DEFINED__ */ + + +#ifndef __IRegistrar_INTERFACE_DEFINED__ +#define __IRegistrar_INTERFACE_DEFINED__ + +/* interface IRegistrar */ +/* [unique][helpstring][uuid][object] */ + + +EXTERN_C const IID IID_IRegistrar; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("44EC053B-400F-11D0-9DCD-00A0C90391D3") + IRegistrar : public IRegistrarBase + { + public: + virtual HRESULT STDMETHODCALLTYPE ResourceRegisterSz( + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResourceUnregisterSz( + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType) = 0; + + virtual HRESULT STDMETHODCALLTYPE FileRegister( + /* [in] */ LPCOLESTR fileName) = 0; + + virtual HRESULT STDMETHODCALLTYPE FileUnregister( + /* [in] */ LPCOLESTR fileName) = 0; + + virtual HRESULT STDMETHODCALLTYPE StringRegister( + /* [in] */ LPCOLESTR data) = 0; + + virtual HRESULT STDMETHODCALLTYPE StringUnregister( + /* [in] */ LPCOLESTR data) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResourceRegister( + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResourceUnregister( + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRegistrarVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IRegistrar * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IRegistrar * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IRegistrar * This); + + HRESULT ( STDMETHODCALLTYPE *AddReplacement )( + IRegistrar * This, + /* [in] */ LPCOLESTR key, + /* [in] */ LPCOLESTR item); + + HRESULT ( STDMETHODCALLTYPE *ClearReplacements )( + IRegistrar * This); + + HRESULT ( STDMETHODCALLTYPE *ResourceRegisterSz )( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType); + + HRESULT ( STDMETHODCALLTYPE *ResourceUnregisterSz )( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType); + + HRESULT ( STDMETHODCALLTYPE *FileRegister )( + IRegistrar * This, + /* [in] */ LPCOLESTR fileName); + + HRESULT ( STDMETHODCALLTYPE *FileUnregister )( + IRegistrar * This, + /* [in] */ LPCOLESTR fileName); + + HRESULT ( STDMETHODCALLTYPE *StringRegister )( + IRegistrar * This, + /* [in] */ LPCOLESTR data); + + HRESULT ( STDMETHODCALLTYPE *StringUnregister )( + IRegistrar * This, + /* [in] */ LPCOLESTR data); + + HRESULT ( STDMETHODCALLTYPE *ResourceRegister )( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType); + + HRESULT ( STDMETHODCALLTYPE *ResourceUnregister )( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType); + + END_INTERFACE + } IRegistrarVtbl; + + interface IRegistrar + { + CONST_VTBL struct IRegistrarVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRegistrar_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IRegistrar_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IRegistrar_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IRegistrar_AddReplacement(This,key,item) \ + (This)->lpVtbl -> AddReplacement(This,key,item) + +#define IRegistrar_ClearReplacements(This) \ + (This)->lpVtbl -> ClearReplacements(This) + + +#define IRegistrar_ResourceRegisterSz(This,resFileName,szID,szType) \ + (This)->lpVtbl -> ResourceRegisterSz(This,resFileName,szID,szType) + +#define IRegistrar_ResourceUnregisterSz(This,resFileName,szID,szType) \ + (This)->lpVtbl -> ResourceUnregisterSz(This,resFileName,szID,szType) + +#define IRegistrar_FileRegister(This,fileName) \ + (This)->lpVtbl -> FileRegister(This,fileName) + +#define IRegistrar_FileUnregister(This,fileName) \ + (This)->lpVtbl -> FileUnregister(This,fileName) + +#define IRegistrar_StringRegister(This,data) \ + (This)->lpVtbl -> StringRegister(This,data) + +#define IRegistrar_StringUnregister(This,data) \ + (This)->lpVtbl -> StringUnregister(This,data) + +#define IRegistrar_ResourceRegister(This,resFileName,nID,szType) \ + (This)->lpVtbl -> ResourceRegister(This,resFileName,nID,szType) + +#define IRegistrar_ResourceUnregister(This,resFileName,nID,szType) \ + (This)->lpVtbl -> ResourceUnregister(This,resFileName,nID,szType) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegisterSz_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType); + + +void __RPC_STUB IRegistrar_ResourceRegisterSz_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregisterSz_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ LPCOLESTR szID, + /* [in] */ LPCOLESTR szType); + + +void __RPC_STUB IRegistrar_ResourceUnregisterSz_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_FileRegister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR fileName); + + +void __RPC_STUB IRegistrar_FileRegister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_FileUnregister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR fileName); + + +void __RPC_STUB IRegistrar_FileUnregister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_StringRegister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR data); + + +void __RPC_STUB IRegistrar_StringRegister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_StringUnregister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR data); + + +void __RPC_STUB IRegistrar_StringUnregister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_ResourceRegister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType); + + +void __RPC_STUB IRegistrar_ResourceRegister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IRegistrar_ResourceUnregister_Proxy( + IRegistrar * This, + /* [in] */ LPCOLESTR resFileName, + /* [in] */ UINT nID, + /* [in] */ LPCOLESTR szType); + + +void __RPC_STUB IRegistrar_ResourceUnregister_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IRegistrar_INTERFACE_DEFINED__ */ + + +#ifndef __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ +#define __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ + +/* interface IDocHostUIHandlerDispatch */ +/* [object][unique][helpstring][uuid][local] */ + +typedef +enum tagDOCHOSTUIDBLCLKDispatch + { docHostUIDblClkDEFAULT = 0, + docHostUIDblClkSHOWPROPERTIES = 1, + docHostUIDblClkSHOWCODE = 2 + } DOCHOSTUIDBLCLKDispatch; + +typedef +enum tagDocHostUIFlagDispatch + { docHostUIFlagDIALOG = 1, + docHostUIFlagDISABLE_HELP_MENU = 2, + docHostUIFlagNO3DBORDER = 4, + docHostUIFlagSCROLL_NO = 8, + docHostUIFlagDISABLE_SCRIPT_INACTIVE = 16, + docHostUIFlagOPENNEWWIN = 32, + docHostUIFlagDISABLE_OFFSCREEN = 64, + docHostUIFlagFLAT_SCROLLBAR = 128, + docHostUIFlagDIV_BLOCKDEFAULT = 256, + docHostUIFlagACTIVATE_CLIENTHIT_ONLY = 512 + } DocHostUIFlagDispatch; + + +EXTERN_C const IID IID_IDocHostUIHandlerDispatch; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("425B5AF0-65F1-11d1-9611-0000F81E0D0D") + IDocHostUIHandlerDispatch : public IDispatch + { + public: + virtual HRESULT STDMETHODCALLTYPE ShowContextMenu( + /* [in] */ DWORD dwID, + /* [in] */ DWORD x, + /* [in] */ DWORD y, + /* [in] */ IUnknown *pcmdtReserved, + /* [in] */ IDispatch *pdispReserved, + /* [retval][out] */ HRESULT *dwRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHostInfo( + /* [out][in] */ DWORD *pdwFlags, + /* [out][in] */ DWORD *pdwDoubleClick) = 0; + + virtual HRESULT STDMETHODCALLTYPE ShowUI( + /* [in] */ DWORD dwID, + /* [in] */ IUnknown *pActiveObject, + /* [in] */ IUnknown *pCommandTarget, + /* [in] */ IUnknown *pFrame, + /* [in] */ IUnknown *pDoc, + /* [retval][out] */ HRESULT *dwRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE HideUI( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE UpdateUI( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE EnableModeless( + /* [in] */ VARIANT_BOOL fEnable) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnDocWindowActivate( + /* [in] */ VARIANT_BOOL fActivate) = 0; + + virtual HRESULT STDMETHODCALLTYPE OnFrameWindowActivate( + /* [in] */ VARIANT_BOOL fActivate) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResizeBorder( + /* [in] */ long left, + /* [in] */ long top, + /* [in] */ long right, + /* [in] */ long bottom, + /* [in] */ IUnknown *pUIWindow, + /* [in] */ VARIANT_BOOL fFrameWindow) = 0; + + virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator( + /* [in] */ DWORD_PTR hWnd, + /* [in] */ DWORD nMessage, + /* [in] */ DWORD_PTR wParam, + /* [in] */ DWORD_PTR lParam, + /* [in] */ BSTR bstrGuidCmdGroup, + /* [in] */ DWORD nCmdID, + /* [retval][out] */ HRESULT *dwRetVal) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetOptionKeyPath( + /* [out] */ BSTR *pbstrKey, + /* [in] */ DWORD dw) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetDropTarget( + /* [in] */ IUnknown *pDropTarget, + /* [out] */ IUnknown **ppDropTarget) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetExternal( + /* [out] */ IDispatch **ppDispatch) = 0; + + virtual HRESULT STDMETHODCALLTYPE TranslateUrl( + /* [in] */ DWORD dwTranslate, + /* [in] */ BSTR bstrURLIn, + /* [out] */ BSTR *pbstrURLOut) = 0; + + virtual HRESULT STDMETHODCALLTYPE FilterDataObject( + /* [in] */ IUnknown *pDO, + /* [out] */ IUnknown **ppDORet) = 0; + + }; + +#else /* C style interface */ + + typedef struct IDocHostUIHandlerDispatchVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDocHostUIHandlerDispatch * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDocHostUIHandlerDispatch * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IDocHostUIHandlerDispatch * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IDocHostUIHandlerDispatch * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IDocHostUIHandlerDispatch * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IDocHostUIHandlerDispatch * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IDocHostUIHandlerDispatch * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + HRESULT ( STDMETHODCALLTYPE *ShowContextMenu )( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwID, + /* [in] */ DWORD x, + /* [in] */ DWORD y, + /* [in] */ IUnknown *pcmdtReserved, + /* [in] */ IDispatch *pdispReserved, + /* [retval][out] */ HRESULT *dwRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetHostInfo )( + IDocHostUIHandlerDispatch * This, + /* [out][in] */ DWORD *pdwFlags, + /* [out][in] */ DWORD *pdwDoubleClick); + + HRESULT ( STDMETHODCALLTYPE *ShowUI )( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwID, + /* [in] */ IUnknown *pActiveObject, + /* [in] */ IUnknown *pCommandTarget, + /* [in] */ IUnknown *pFrame, + /* [in] */ IUnknown *pDoc, + /* [retval][out] */ HRESULT *dwRetVal); + + HRESULT ( STDMETHODCALLTYPE *HideUI )( + IDocHostUIHandlerDispatch * This); + + HRESULT ( STDMETHODCALLTYPE *UpdateUI )( + IDocHostUIHandlerDispatch * This); + + HRESULT ( STDMETHODCALLTYPE *EnableModeless )( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fEnable); + + HRESULT ( STDMETHODCALLTYPE *OnDocWindowActivate )( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fActivate); + + HRESULT ( STDMETHODCALLTYPE *OnFrameWindowActivate )( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fActivate); + + HRESULT ( STDMETHODCALLTYPE *ResizeBorder )( + IDocHostUIHandlerDispatch * This, + /* [in] */ long left, + /* [in] */ long top, + /* [in] */ long right, + /* [in] */ long bottom, + /* [in] */ IUnknown *pUIWindow, + /* [in] */ VARIANT_BOOL fFrameWindow); + + HRESULT ( STDMETHODCALLTYPE *TranslateAccelerator )( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD_PTR hWnd, + /* [in] */ DWORD nMessage, + /* [in] */ DWORD_PTR wParam, + /* [in] */ DWORD_PTR lParam, + /* [in] */ BSTR bstrGuidCmdGroup, + /* [in] */ DWORD nCmdID, + /* [retval][out] */ HRESULT *dwRetVal); + + HRESULT ( STDMETHODCALLTYPE *GetOptionKeyPath )( + IDocHostUIHandlerDispatch * This, + /* [out] */ BSTR *pbstrKey, + /* [in] */ DWORD dw); + + HRESULT ( STDMETHODCALLTYPE *GetDropTarget )( + IDocHostUIHandlerDispatch * This, + /* [in] */ IUnknown *pDropTarget, + /* [out] */ IUnknown **ppDropTarget); + + HRESULT ( STDMETHODCALLTYPE *GetExternal )( + IDocHostUIHandlerDispatch * This, + /* [out] */ IDispatch **ppDispatch); + + HRESULT ( STDMETHODCALLTYPE *TranslateUrl )( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwTranslate, + /* [in] */ BSTR bstrURLIn, + /* [out] */ BSTR *pbstrURLOut); + + HRESULT ( STDMETHODCALLTYPE *FilterDataObject )( + IDocHostUIHandlerDispatch * This, + /* [in] */ IUnknown *pDO, + /* [out] */ IUnknown **ppDORet); + + END_INTERFACE + } IDocHostUIHandlerDispatchVtbl; + + interface IDocHostUIHandlerDispatch + { + CONST_VTBL struct IDocHostUIHandlerDispatchVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDocHostUIHandlerDispatch_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IDocHostUIHandlerDispatch_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IDocHostUIHandlerDispatch_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IDocHostUIHandlerDispatch_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IDocHostUIHandlerDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IDocHostUIHandlerDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IDocHostUIHandlerDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IDocHostUIHandlerDispatch_ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) \ + (This)->lpVtbl -> ShowContextMenu(This,dwID,x,y,pcmdtReserved,pdispReserved,dwRetVal) + +#define IDocHostUIHandlerDispatch_GetHostInfo(This,pdwFlags,pdwDoubleClick) \ + (This)->lpVtbl -> GetHostInfo(This,pdwFlags,pdwDoubleClick) + +#define IDocHostUIHandlerDispatch_ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) \ + (This)->lpVtbl -> ShowUI(This,dwID,pActiveObject,pCommandTarget,pFrame,pDoc,dwRetVal) + +#define IDocHostUIHandlerDispatch_HideUI(This) \ + (This)->lpVtbl -> HideUI(This) + +#define IDocHostUIHandlerDispatch_UpdateUI(This) \ + (This)->lpVtbl -> UpdateUI(This) + +#define IDocHostUIHandlerDispatch_EnableModeless(This,fEnable) \ + (This)->lpVtbl -> EnableModeless(This,fEnable) + +#define IDocHostUIHandlerDispatch_OnDocWindowActivate(This,fActivate) \ + (This)->lpVtbl -> OnDocWindowActivate(This,fActivate) + +#define IDocHostUIHandlerDispatch_OnFrameWindowActivate(This,fActivate) \ + (This)->lpVtbl -> OnFrameWindowActivate(This,fActivate) + +#define IDocHostUIHandlerDispatch_ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) \ + (This)->lpVtbl -> ResizeBorder(This,left,top,right,bottom,pUIWindow,fFrameWindow) + +#define IDocHostUIHandlerDispatch_TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) \ + (This)->lpVtbl -> TranslateAccelerator(This,hWnd,nMessage,wParam,lParam,bstrGuidCmdGroup,nCmdID,dwRetVal) + +#define IDocHostUIHandlerDispatch_GetOptionKeyPath(This,pbstrKey,dw) \ + (This)->lpVtbl -> GetOptionKeyPath(This,pbstrKey,dw) + +#define IDocHostUIHandlerDispatch_GetDropTarget(This,pDropTarget,ppDropTarget) \ + (This)->lpVtbl -> GetDropTarget(This,pDropTarget,ppDropTarget) + +#define IDocHostUIHandlerDispatch_GetExternal(This,ppDispatch) \ + (This)->lpVtbl -> GetExternal(This,ppDispatch) + +#define IDocHostUIHandlerDispatch_TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) \ + (This)->lpVtbl -> TranslateUrl(This,dwTranslate,bstrURLIn,pbstrURLOut) + +#define IDocHostUIHandlerDispatch_FilterDataObject(This,pDO,ppDORet) \ + (This)->lpVtbl -> FilterDataObject(This,pDO,ppDORet) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowContextMenu_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwID, + /* [in] */ DWORD x, + /* [in] */ DWORD y, + /* [in] */ IUnknown *pcmdtReserved, + /* [in] */ IDispatch *pdispReserved, + /* [retval][out] */ HRESULT *dwRetVal); + + +void __RPC_STUB IDocHostUIHandlerDispatch_ShowContextMenu_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetHostInfo_Proxy( + IDocHostUIHandlerDispatch * This, + /* [out][in] */ DWORD *pdwFlags, + /* [out][in] */ DWORD *pdwDoubleClick); + + +void __RPC_STUB IDocHostUIHandlerDispatch_GetHostInfo_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ShowUI_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwID, + /* [in] */ IUnknown *pActiveObject, + /* [in] */ IUnknown *pCommandTarget, + /* [in] */ IUnknown *pFrame, + /* [in] */ IUnknown *pDoc, + /* [retval][out] */ HRESULT *dwRetVal); + + +void __RPC_STUB IDocHostUIHandlerDispatch_ShowUI_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_HideUI_Proxy( + IDocHostUIHandlerDispatch * This); + + +void __RPC_STUB IDocHostUIHandlerDispatch_HideUI_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_UpdateUI_Proxy( + IDocHostUIHandlerDispatch * This); + + +void __RPC_STUB IDocHostUIHandlerDispatch_UpdateUI_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_EnableModeless_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fEnable); + + +void __RPC_STUB IDocHostUIHandlerDispatch_EnableModeless_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnDocWindowActivate_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fActivate); + + +void __RPC_STUB IDocHostUIHandlerDispatch_OnDocWindowActivate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_OnFrameWindowActivate_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ VARIANT_BOOL fActivate); + + +void __RPC_STUB IDocHostUIHandlerDispatch_OnFrameWindowActivate_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_ResizeBorder_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ long left, + /* [in] */ long top, + /* [in] */ long right, + /* [in] */ long bottom, + /* [in] */ IUnknown *pUIWindow, + /* [in] */ VARIANT_BOOL fFrameWindow); + + +void __RPC_STUB IDocHostUIHandlerDispatch_ResizeBorder_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateAccelerator_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD_PTR hWnd, + /* [in] */ DWORD nMessage, + /* [in] */ DWORD_PTR wParam, + /* [in] */ DWORD_PTR lParam, + /* [in] */ BSTR bstrGuidCmdGroup, + /* [in] */ DWORD nCmdID, + /* [retval][out] */ HRESULT *dwRetVal); + + +void __RPC_STUB IDocHostUIHandlerDispatch_TranslateAccelerator_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetOptionKeyPath_Proxy( + IDocHostUIHandlerDispatch * This, + /* [out] */ BSTR *pbstrKey, + /* [in] */ DWORD dw); + + +void __RPC_STUB IDocHostUIHandlerDispatch_GetOptionKeyPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetDropTarget_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ IUnknown *pDropTarget, + /* [out] */ IUnknown **ppDropTarget); + + +void __RPC_STUB IDocHostUIHandlerDispatch_GetDropTarget_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_GetExternal_Proxy( + IDocHostUIHandlerDispatch * This, + /* [out] */ IDispatch **ppDispatch); + + +void __RPC_STUB IDocHostUIHandlerDispatch_GetExternal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_TranslateUrl_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ DWORD dwTranslate, + /* [in] */ BSTR bstrURLIn, + /* [out] */ BSTR *pbstrURLOut); + + +void __RPC_STUB IDocHostUIHandlerDispatch_TranslateUrl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IDocHostUIHandlerDispatch_FilterDataObject_Proxy( + IDocHostUIHandlerDispatch * This, + /* [in] */ IUnknown *pDO, + /* [out] */ IUnknown **ppDORet); + + +void __RPC_STUB IDocHostUIHandlerDispatch_FilterDataObject_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IDocHostUIHandlerDispatch_INTERFACE_DEFINED__ */ + + +#ifndef __IAxWinHostWindow_INTERFACE_DEFINED__ +#define __IAxWinHostWindow_INTERFACE_DEFINED__ + +/* interface IAxWinHostWindow */ +/* [object][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IAxWinHostWindow; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B6EA2050-048A-11d1-82B9-00C04FB9942E") + IAxWinHostWindow : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateControl( + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateControlEx( + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise) = 0; + + virtual HRESULT STDMETHODCALLTYPE AttachControl( + /* [in] */ IUnknown *pUnkControl, + /* [in] */ HWND hWnd) = 0; + + virtual HRESULT STDMETHODCALLTYPE QueryControl( + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetExternalDispatch( + /* [in] */ IDispatch *pDisp) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetExternalUIHandler( + /* [in] */ IDocHostUIHandlerDispatch *pDisp) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAxWinHostWindowVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAxWinHostWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAxWinHostWindow * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAxWinHostWindow * This); + + HRESULT ( STDMETHODCALLTYPE *CreateControl )( + IAxWinHostWindow * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream); + + HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( + IAxWinHostWindow * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise); + + HRESULT ( STDMETHODCALLTYPE *AttachControl )( + IAxWinHostWindow * This, + /* [in] */ IUnknown *pUnkControl, + /* [in] */ HWND hWnd); + + HRESULT ( STDMETHODCALLTYPE *QueryControl )( + IAxWinHostWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( + IAxWinHostWindow * This, + /* [in] */ IDispatch *pDisp); + + HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( + IAxWinHostWindow * This, + /* [in] */ IDocHostUIHandlerDispatch *pDisp); + + END_INTERFACE + } IAxWinHostWindowVtbl; + + interface IAxWinHostWindow + { + CONST_VTBL struct IAxWinHostWindowVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAxWinHostWindow_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAxWinHostWindow_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAxWinHostWindow_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAxWinHostWindow_CreateControl(This,lpTricsData,hWnd,pStream) \ + (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) + +#define IAxWinHostWindow_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ + (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) + +#define IAxWinHostWindow_AttachControl(This,pUnkControl,hWnd) \ + (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) + +#define IAxWinHostWindow_QueryControl(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryControl(This,riid,ppvObject) + +#define IAxWinHostWindow_SetExternalDispatch(This,pDisp) \ + (This)->lpVtbl -> SetExternalDispatch(This,pDisp) + +#define IAxWinHostWindow_SetExternalUIHandler(This,pDisp) \ + (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControl_Proxy( + IAxWinHostWindow * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream); + + +void __RPC_STUB IAxWinHostWindow_CreateControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_CreateControlEx_Proxy( + IAxWinHostWindow * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise); + + +void __RPC_STUB IAxWinHostWindow_CreateControlEx_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_AttachControl_Proxy( + IAxWinHostWindow * This, + /* [in] */ IUnknown *pUnkControl, + /* [in] */ HWND hWnd); + + +void __RPC_STUB IAxWinHostWindow_AttachControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_QueryControl_Proxy( + IAxWinHostWindow * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + +void __RPC_STUB IAxWinHostWindow_QueryControl_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalDispatch_Proxy( + IAxWinHostWindow * This, + /* [in] */ IDispatch *pDisp); + + +void __RPC_STUB IAxWinHostWindow_SetExternalDispatch_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindow_SetExternalUIHandler_Proxy( + IAxWinHostWindow * This, + /* [in] */ IDocHostUIHandlerDispatch *pDisp); + + +void __RPC_STUB IAxWinHostWindow_SetExternalUIHandler_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAxWinHostWindow_INTERFACE_DEFINED__ */ + + +#ifndef __IAxWinHostWindowLic_INTERFACE_DEFINED__ +#define __IAxWinHostWindowLic_INTERFACE_DEFINED__ + +/* interface IAxWinHostWindowLic */ +/* [object][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IAxWinHostWindowLic; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3935BDA8-4ED9-495c-8650-E01FC1E38A4B") + IAxWinHostWindowLic : public IAxWinHostWindow + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateControlLic( + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [in] */ BSTR bstrLic) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateControlLicEx( + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise, + /* [in] */ BSTR bstrLic) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAxWinHostWindowLicVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAxWinHostWindowLic * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAxWinHostWindowLic * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAxWinHostWindowLic * This); + + HRESULT ( STDMETHODCALLTYPE *CreateControl )( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream); + + HRESULT ( STDMETHODCALLTYPE *CreateControlEx )( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise); + + HRESULT ( STDMETHODCALLTYPE *AttachControl )( + IAxWinHostWindowLic * This, + /* [in] */ IUnknown *pUnkControl, + /* [in] */ HWND hWnd); + + HRESULT ( STDMETHODCALLTYPE *QueryControl )( + IAxWinHostWindowLic * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + HRESULT ( STDMETHODCALLTYPE *SetExternalDispatch )( + IAxWinHostWindowLic * This, + /* [in] */ IDispatch *pDisp); + + HRESULT ( STDMETHODCALLTYPE *SetExternalUIHandler )( + IAxWinHostWindowLic * This, + /* [in] */ IDocHostUIHandlerDispatch *pDisp); + + HRESULT ( STDMETHODCALLTYPE *CreateControlLic )( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [in] */ BSTR bstrLic); + + HRESULT ( STDMETHODCALLTYPE *CreateControlLicEx )( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise, + /* [in] */ BSTR bstrLic); + + END_INTERFACE + } IAxWinHostWindowLicVtbl; + + interface IAxWinHostWindowLic + { + CONST_VTBL struct IAxWinHostWindowLicVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAxWinHostWindowLic_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAxWinHostWindowLic_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAxWinHostWindowLic_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAxWinHostWindowLic_CreateControl(This,lpTricsData,hWnd,pStream) \ + (This)->lpVtbl -> CreateControl(This,lpTricsData,hWnd,pStream) + +#define IAxWinHostWindowLic_CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) \ + (This)->lpVtbl -> CreateControlEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise) + +#define IAxWinHostWindowLic_AttachControl(This,pUnkControl,hWnd) \ + (This)->lpVtbl -> AttachControl(This,pUnkControl,hWnd) + +#define IAxWinHostWindowLic_QueryControl(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryControl(This,riid,ppvObject) + +#define IAxWinHostWindowLic_SetExternalDispatch(This,pDisp) \ + (This)->lpVtbl -> SetExternalDispatch(This,pDisp) + +#define IAxWinHostWindowLic_SetExternalUIHandler(This,pDisp) \ + (This)->lpVtbl -> SetExternalUIHandler(This,pDisp) + + +#define IAxWinHostWindowLic_CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) \ + (This)->lpVtbl -> CreateControlLic(This,lpTricsData,hWnd,pStream,bstrLic) + +#define IAxWinHostWindowLic_CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) \ + (This)->lpVtbl -> CreateControlLicEx(This,lpTricsData,hWnd,pStream,ppUnk,riidAdvise,punkAdvise,bstrLic) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLic_Proxy( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [in] */ BSTR bstrLic); + + +void __RPC_STUB IAxWinHostWindowLic_CreateControlLic_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAxWinHostWindowLic_CreateControlLicEx_Proxy( + IAxWinHostWindowLic * This, + /* [in] */ LPCOLESTR lpTricsData, + /* [in] */ HWND hWnd, + /* [in] */ IStream *pStream, + /* [out] */ IUnknown **ppUnk, + /* [in] */ REFIID riidAdvise, + /* [in] */ IUnknown *punkAdvise, + /* [in] */ BSTR bstrLic); + + +void __RPC_STUB IAxWinHostWindowLic_CreateControlLicEx_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAxWinHostWindowLic_INTERFACE_DEFINED__ */ + + +#ifndef __IAxWinAmbientDispatch_INTERFACE_DEFINED__ +#define __IAxWinAmbientDispatch_INTERFACE_DEFINED__ + +/* interface IAxWinAmbientDispatch */ +/* [unique][helpstring][uuid][dual][object] */ + + +EXTERN_C const IID IID_IAxWinAmbientDispatch; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B6EA2051-048A-11d1-82B9-00C04FB9942E") + IAxWinAmbientDispatch : public IDispatch + { + public: + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowWindowlessActivation( + /* [in] */ VARIANT_BOOL bCanWindowlessActivate) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowWindowlessActivation( + /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_BackColor( + /* [in] */ OLE_COLOR clrBackground) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BackColor( + /* [retval][out] */ OLE_COLOR *pclrBackground) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_ForeColor( + /* [in] */ OLE_COLOR clrForeground) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ForeColor( + /* [retval][out] */ OLE_COLOR *pclrForeground) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_LocaleID( + /* [in] */ LCID lcidLocaleID) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LocaleID( + /* [retval][out] */ LCID *plcidLocaleID) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_UserMode( + /* [in] */ VARIANT_BOOL bUserMode) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_UserMode( + /* [retval][out] */ VARIANT_BOOL *pbUserMode) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DisplayAsDefault( + /* [in] */ VARIANT_BOOL bDisplayAsDefault) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DisplayAsDefault( + /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_Font( + /* [in] */ IFontDisp *pFont) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Font( + /* [retval][out] */ IFontDisp **pFont) = 0; + + virtual /* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_MessageReflect( + /* [in] */ VARIANT_BOOL bMsgReflect) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MessageReflect( + /* [retval][out] */ VARIANT_BOOL *pbMsgReflect) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowGrabHandles( + /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles) = 0; + + virtual /* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ShowHatching( + /* [retval][out] */ VARIANT_BOOL *pbShowHatching) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostFlags( + /* [in] */ DWORD dwDocHostFlags) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostFlags( + /* [retval][out] */ DWORD *pdwDocHostFlags) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_DocHostDoubleClickFlags( + /* [in] */ DWORD dwDocHostDoubleClickFlags) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_DocHostDoubleClickFlags( + /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowContextMenu( + /* [in] */ VARIANT_BOOL bAllowContextMenu) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowContextMenu( + /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_AllowShowUI( + /* [in] */ VARIANT_BOOL bAllowShowUI) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_AllowShowUI( + /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_OptionKeyPath( + /* [in] */ BSTR bstrOptionKeyPath) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_OptionKeyPath( + /* [retval][out] */ BSTR *pbstrOptionKeyPath) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAxWinAmbientDispatchVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAxWinAmbientDispatch * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAxWinAmbientDispatch * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAxWinAmbientDispatch * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IAxWinAmbientDispatch * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IAxWinAmbientDispatch * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IAxWinAmbientDispatch * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IAxWinAmbientDispatch * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bCanWindowlessActivate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( + IAxWinAmbientDispatch * This, + /* [in] */ OLE_COLOR clrBackground); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ OLE_COLOR *pclrBackground); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( + IAxWinAmbientDispatch * This, + /* [in] */ OLE_COLOR clrForeground); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ OLE_COLOR *pclrForeground); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( + IAxWinAmbientDispatch * This, + /* [in] */ LCID lcidLocaleID); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ LCID *plcidLocaleID); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bUserMode); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbUserMode); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bDisplayAsDefault); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( + IAxWinAmbientDispatch * This, + /* [in] */ IFontDisp *pFont); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ IFontDisp **pFont); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bMsgReflect); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbShowHatching); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( + IAxWinAmbientDispatch * This, + /* [in] */ DWORD dwDocHostFlags); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ DWORD *pdwDocHostFlags); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( + IAxWinAmbientDispatch * This, + /* [in] */ DWORD dwDocHostDoubleClickFlags); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bAllowContextMenu); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bAllowShowUI); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( + IAxWinAmbientDispatch * This, + /* [in] */ BSTR bstrOptionKeyPath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( + IAxWinAmbientDispatch * This, + /* [retval][out] */ BSTR *pbstrOptionKeyPath); + + END_INTERFACE + } IAxWinAmbientDispatchVtbl; + + interface IAxWinAmbientDispatch + { + CONST_VTBL struct IAxWinAmbientDispatchVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAxWinAmbientDispatch_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAxWinAmbientDispatch_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAxWinAmbientDispatch_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAxWinAmbientDispatch_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IAxWinAmbientDispatch_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IAxWinAmbientDispatch_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IAxWinAmbientDispatch_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IAxWinAmbientDispatch_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ + (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) + +#define IAxWinAmbientDispatch_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ + (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) + +#define IAxWinAmbientDispatch_put_BackColor(This,clrBackground) \ + (This)->lpVtbl -> put_BackColor(This,clrBackground) + +#define IAxWinAmbientDispatch_get_BackColor(This,pclrBackground) \ + (This)->lpVtbl -> get_BackColor(This,pclrBackground) + +#define IAxWinAmbientDispatch_put_ForeColor(This,clrForeground) \ + (This)->lpVtbl -> put_ForeColor(This,clrForeground) + +#define IAxWinAmbientDispatch_get_ForeColor(This,pclrForeground) \ + (This)->lpVtbl -> get_ForeColor(This,pclrForeground) + +#define IAxWinAmbientDispatch_put_LocaleID(This,lcidLocaleID) \ + (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) + +#define IAxWinAmbientDispatch_get_LocaleID(This,plcidLocaleID) \ + (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) + +#define IAxWinAmbientDispatch_put_UserMode(This,bUserMode) \ + (This)->lpVtbl -> put_UserMode(This,bUserMode) + +#define IAxWinAmbientDispatch_get_UserMode(This,pbUserMode) \ + (This)->lpVtbl -> get_UserMode(This,pbUserMode) + +#define IAxWinAmbientDispatch_put_DisplayAsDefault(This,bDisplayAsDefault) \ + (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) + +#define IAxWinAmbientDispatch_get_DisplayAsDefault(This,pbDisplayAsDefault) \ + (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) + +#define IAxWinAmbientDispatch_put_Font(This,pFont) \ + (This)->lpVtbl -> put_Font(This,pFont) + +#define IAxWinAmbientDispatch_get_Font(This,pFont) \ + (This)->lpVtbl -> get_Font(This,pFont) + +#define IAxWinAmbientDispatch_put_MessageReflect(This,bMsgReflect) \ + (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) + +#define IAxWinAmbientDispatch_get_MessageReflect(This,pbMsgReflect) \ + (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) + +#define IAxWinAmbientDispatch_get_ShowGrabHandles(This,pbShowGrabHandles) \ + (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) + +#define IAxWinAmbientDispatch_get_ShowHatching(This,pbShowHatching) \ + (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) + +#define IAxWinAmbientDispatch_put_DocHostFlags(This,dwDocHostFlags) \ + (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) + +#define IAxWinAmbientDispatch_get_DocHostFlags(This,pdwDocHostFlags) \ + (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) + +#define IAxWinAmbientDispatch_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ + (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) + +#define IAxWinAmbientDispatch_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ + (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) + +#define IAxWinAmbientDispatch_put_AllowContextMenu(This,bAllowContextMenu) \ + (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) + +#define IAxWinAmbientDispatch_get_AllowContextMenu(This,pbAllowContextMenu) \ + (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) + +#define IAxWinAmbientDispatch_put_AllowShowUI(This,bAllowShowUI) \ + (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) + +#define IAxWinAmbientDispatch_get_AllowShowUI(This,pbAllowShowUI) \ + (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) + +#define IAxWinAmbientDispatch_put_OptionKeyPath(This,bstrOptionKeyPath) \ + (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) + +#define IAxWinAmbientDispatch_get_OptionKeyPath(This,pbstrOptionKeyPath) \ + (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowWindowlessActivation_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bCanWindowlessActivate); + + +void __RPC_STUB IAxWinAmbientDispatch_put_AllowWindowlessActivation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowWindowlessActivation_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); + + +void __RPC_STUB IAxWinAmbientDispatch_get_AllowWindowlessActivation_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_BackColor_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ OLE_COLOR clrBackground); + + +void __RPC_STUB IAxWinAmbientDispatch_put_BackColor_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_BackColor_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ OLE_COLOR *pclrBackground); + + +void __RPC_STUB IAxWinAmbientDispatch_get_BackColor_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_ForeColor_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ OLE_COLOR clrForeground); + + +void __RPC_STUB IAxWinAmbientDispatch_put_ForeColor_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ForeColor_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ OLE_COLOR *pclrForeground); + + +void __RPC_STUB IAxWinAmbientDispatch_get_ForeColor_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_LocaleID_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ LCID lcidLocaleID); + + +void __RPC_STUB IAxWinAmbientDispatch_put_LocaleID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_LocaleID_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ LCID *plcidLocaleID); + + +void __RPC_STUB IAxWinAmbientDispatch_get_LocaleID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_UserMode_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bUserMode); + + +void __RPC_STUB IAxWinAmbientDispatch_put_UserMode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_UserMode_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbUserMode); + + +void __RPC_STUB IAxWinAmbientDispatch_get_UserMode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DisplayAsDefault_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bDisplayAsDefault); + + +void __RPC_STUB IAxWinAmbientDispatch_put_DisplayAsDefault_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DisplayAsDefault_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); + + +void __RPC_STUB IAxWinAmbientDispatch_get_DisplayAsDefault_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_Font_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ IFontDisp *pFont); + + +void __RPC_STUB IAxWinAmbientDispatch_put_Font_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_Font_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ IFontDisp **pFont); + + +void __RPC_STUB IAxWinAmbientDispatch_get_Font_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_MessageReflect_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bMsgReflect); + + +void __RPC_STUB IAxWinAmbientDispatch_put_MessageReflect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_MessageReflect_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); + + +void __RPC_STUB IAxWinAmbientDispatch_get_MessageReflect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowGrabHandles_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); + + +void __RPC_STUB IAxWinAmbientDispatch_get_ShowGrabHandles_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_ShowHatching_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbShowHatching); + + +void __RPC_STUB IAxWinAmbientDispatch_get_ShowHatching_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostFlags_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ DWORD dwDocHostFlags); + + +void __RPC_STUB IAxWinAmbientDispatch_put_DocHostFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostFlags_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ DWORD *pdwDocHostFlags); + + +void __RPC_STUB IAxWinAmbientDispatch_get_DocHostFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ DWORD dwDocHostDoubleClickFlags); + + +void __RPC_STUB IAxWinAmbientDispatch_put_DocHostDoubleClickFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); + + +void __RPC_STUB IAxWinAmbientDispatch_get_DocHostDoubleClickFlags_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowContextMenu_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bAllowContextMenu); + + +void __RPC_STUB IAxWinAmbientDispatch_put_AllowContextMenu_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowContextMenu_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); + + +void __RPC_STUB IAxWinAmbientDispatch_get_AllowContextMenu_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_AllowShowUI_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ VARIANT_BOOL bAllowShowUI); + + +void __RPC_STUB IAxWinAmbientDispatch_put_AllowShowUI_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_AllowShowUI_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); + + +void __RPC_STUB IAxWinAmbientDispatch_get_AllowShowUI_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_put_OptionKeyPath_Proxy( + IAxWinAmbientDispatch * This, + /* [in] */ BSTR bstrOptionKeyPath); + + +void __RPC_STUB IAxWinAmbientDispatch_put_OptionKeyPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatch_get_OptionKeyPath_Proxy( + IAxWinAmbientDispatch * This, + /* [retval][out] */ BSTR *pbstrOptionKeyPath); + + +void __RPC_STUB IAxWinAmbientDispatch_get_OptionKeyPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAxWinAmbientDispatch_INTERFACE_DEFINED__ */ + + +#ifndef __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ +#define __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ + +/* interface IAxWinAmbientDispatchEx */ +/* [unique][helpstring][uuid][dual][object] */ + + +EXTERN_C const IID IID_IAxWinAmbientDispatchEx; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("B2D0778B-AC99-4c58-A5C8-E7724E5316B5") + IAxWinAmbientDispatchEx : public IAxWinAmbientDispatch + { + public: + virtual /* [id] */ HRESULT STDMETHODCALLTYPE SetAmbientDispatch( + /* [in] */ IDispatch *pDispatch) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAxWinAmbientDispatchExVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAxWinAmbientDispatchEx * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAxWinAmbientDispatchEx * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAxWinAmbientDispatchEx * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IAxWinAmbientDispatchEx * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IAxWinAmbientDispatchEx * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IAxWinAmbientDispatchEx * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IAxWinAmbientDispatchEx * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowWindowlessActivation )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bCanWindowlessActivate); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowWindowlessActivation )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbCanWindowlessActivate); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_BackColor )( + IAxWinAmbientDispatchEx * This, + /* [in] */ OLE_COLOR clrBackground); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BackColor )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ OLE_COLOR *pclrBackground); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_ForeColor )( + IAxWinAmbientDispatchEx * This, + /* [in] */ OLE_COLOR clrForeground); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ForeColor )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ OLE_COLOR *pclrForeground); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_LocaleID )( + IAxWinAmbientDispatchEx * This, + /* [in] */ LCID lcidLocaleID); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocaleID )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ LCID *plcidLocaleID); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_UserMode )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bUserMode); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_UserMode )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbUserMode); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DisplayAsDefault )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bDisplayAsDefault); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DisplayAsDefault )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbDisplayAsDefault); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_Font )( + IAxWinAmbientDispatchEx * This, + /* [in] */ IFontDisp *pFont); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Font )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ IFontDisp **pFont); + + /* [id][helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_MessageReflect )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bMsgReflect); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MessageReflect )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbMsgReflect); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowGrabHandles )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbShowGrabHandles); + + /* [id][helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ShowHatching )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbShowHatching); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostFlags )( + IAxWinAmbientDispatchEx * This, + /* [in] */ DWORD dwDocHostFlags); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostFlags )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ DWORD *pdwDocHostFlags); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_DocHostDoubleClickFlags )( + IAxWinAmbientDispatchEx * This, + /* [in] */ DWORD dwDocHostDoubleClickFlags); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_DocHostDoubleClickFlags )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ DWORD *pdwDocHostDoubleClickFlags); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowContextMenu )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bAllowContextMenu); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowContextMenu )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowContextMenu); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_AllowShowUI )( + IAxWinAmbientDispatchEx * This, + /* [in] */ VARIANT_BOOL bAllowShowUI); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_AllowShowUI )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ VARIANT_BOOL *pbAllowShowUI); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_OptionKeyPath )( + IAxWinAmbientDispatchEx * This, + /* [in] */ BSTR bstrOptionKeyPath); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OptionKeyPath )( + IAxWinAmbientDispatchEx * This, + /* [retval][out] */ BSTR *pbstrOptionKeyPath); + + /* [id] */ HRESULT ( STDMETHODCALLTYPE *SetAmbientDispatch )( + IAxWinAmbientDispatchEx * This, + /* [in] */ IDispatch *pDispatch); + + END_INTERFACE + } IAxWinAmbientDispatchExVtbl; + + interface IAxWinAmbientDispatchEx + { + CONST_VTBL struct IAxWinAmbientDispatchExVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAxWinAmbientDispatchEx_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAxWinAmbientDispatchEx_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAxWinAmbientDispatchEx_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAxWinAmbientDispatchEx_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IAxWinAmbientDispatchEx_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IAxWinAmbientDispatchEx_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IAxWinAmbientDispatchEx_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IAxWinAmbientDispatchEx_put_AllowWindowlessActivation(This,bCanWindowlessActivate) \ + (This)->lpVtbl -> put_AllowWindowlessActivation(This,bCanWindowlessActivate) + +#define IAxWinAmbientDispatchEx_get_AllowWindowlessActivation(This,pbCanWindowlessActivate) \ + (This)->lpVtbl -> get_AllowWindowlessActivation(This,pbCanWindowlessActivate) + +#define IAxWinAmbientDispatchEx_put_BackColor(This,clrBackground) \ + (This)->lpVtbl -> put_BackColor(This,clrBackground) + +#define IAxWinAmbientDispatchEx_get_BackColor(This,pclrBackground) \ + (This)->lpVtbl -> get_BackColor(This,pclrBackground) + +#define IAxWinAmbientDispatchEx_put_ForeColor(This,clrForeground) \ + (This)->lpVtbl -> put_ForeColor(This,clrForeground) + +#define IAxWinAmbientDispatchEx_get_ForeColor(This,pclrForeground) \ + (This)->lpVtbl -> get_ForeColor(This,pclrForeground) + +#define IAxWinAmbientDispatchEx_put_LocaleID(This,lcidLocaleID) \ + (This)->lpVtbl -> put_LocaleID(This,lcidLocaleID) + +#define IAxWinAmbientDispatchEx_get_LocaleID(This,plcidLocaleID) \ + (This)->lpVtbl -> get_LocaleID(This,plcidLocaleID) + +#define IAxWinAmbientDispatchEx_put_UserMode(This,bUserMode) \ + (This)->lpVtbl -> put_UserMode(This,bUserMode) + +#define IAxWinAmbientDispatchEx_get_UserMode(This,pbUserMode) \ + (This)->lpVtbl -> get_UserMode(This,pbUserMode) + +#define IAxWinAmbientDispatchEx_put_DisplayAsDefault(This,bDisplayAsDefault) \ + (This)->lpVtbl -> put_DisplayAsDefault(This,bDisplayAsDefault) + +#define IAxWinAmbientDispatchEx_get_DisplayAsDefault(This,pbDisplayAsDefault) \ + (This)->lpVtbl -> get_DisplayAsDefault(This,pbDisplayAsDefault) + +#define IAxWinAmbientDispatchEx_put_Font(This,pFont) \ + (This)->lpVtbl -> put_Font(This,pFont) + +#define IAxWinAmbientDispatchEx_get_Font(This,pFont) \ + (This)->lpVtbl -> get_Font(This,pFont) + +#define IAxWinAmbientDispatchEx_put_MessageReflect(This,bMsgReflect) \ + (This)->lpVtbl -> put_MessageReflect(This,bMsgReflect) + +#define IAxWinAmbientDispatchEx_get_MessageReflect(This,pbMsgReflect) \ + (This)->lpVtbl -> get_MessageReflect(This,pbMsgReflect) + +#define IAxWinAmbientDispatchEx_get_ShowGrabHandles(This,pbShowGrabHandles) \ + (This)->lpVtbl -> get_ShowGrabHandles(This,pbShowGrabHandles) + +#define IAxWinAmbientDispatchEx_get_ShowHatching(This,pbShowHatching) \ + (This)->lpVtbl -> get_ShowHatching(This,pbShowHatching) + +#define IAxWinAmbientDispatchEx_put_DocHostFlags(This,dwDocHostFlags) \ + (This)->lpVtbl -> put_DocHostFlags(This,dwDocHostFlags) + +#define IAxWinAmbientDispatchEx_get_DocHostFlags(This,pdwDocHostFlags) \ + (This)->lpVtbl -> get_DocHostFlags(This,pdwDocHostFlags) + +#define IAxWinAmbientDispatchEx_put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) \ + (This)->lpVtbl -> put_DocHostDoubleClickFlags(This,dwDocHostDoubleClickFlags) + +#define IAxWinAmbientDispatchEx_get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) \ + (This)->lpVtbl -> get_DocHostDoubleClickFlags(This,pdwDocHostDoubleClickFlags) + +#define IAxWinAmbientDispatchEx_put_AllowContextMenu(This,bAllowContextMenu) \ + (This)->lpVtbl -> put_AllowContextMenu(This,bAllowContextMenu) + +#define IAxWinAmbientDispatchEx_get_AllowContextMenu(This,pbAllowContextMenu) \ + (This)->lpVtbl -> get_AllowContextMenu(This,pbAllowContextMenu) + +#define IAxWinAmbientDispatchEx_put_AllowShowUI(This,bAllowShowUI) \ + (This)->lpVtbl -> put_AllowShowUI(This,bAllowShowUI) + +#define IAxWinAmbientDispatchEx_get_AllowShowUI(This,pbAllowShowUI) \ + (This)->lpVtbl -> get_AllowShowUI(This,pbAllowShowUI) + +#define IAxWinAmbientDispatchEx_put_OptionKeyPath(This,bstrOptionKeyPath) \ + (This)->lpVtbl -> put_OptionKeyPath(This,bstrOptionKeyPath) + +#define IAxWinAmbientDispatchEx_get_OptionKeyPath(This,pbstrOptionKeyPath) \ + (This)->lpVtbl -> get_OptionKeyPath(This,pbstrOptionKeyPath) + + +#define IAxWinAmbientDispatchEx_SetAmbientDispatch(This,pDispatch) \ + (This)->lpVtbl -> SetAmbientDispatch(This,pDispatch) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [id] */ HRESULT STDMETHODCALLTYPE IAxWinAmbientDispatchEx_SetAmbientDispatch_Proxy( + IAxWinAmbientDispatchEx * This, + /* [in] */ IDispatch *pDispatch); + + +void __RPC_STUB IAxWinAmbientDispatchEx_SetAmbientDispatch_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAxWinAmbientDispatchEx_INTERFACE_DEFINED__ */ + + +#ifndef __IInternalConnection_INTERFACE_DEFINED__ +#define __IInternalConnection_INTERFACE_DEFINED__ + +/* interface IInternalConnection */ +/* [object][unique][helpstring][uuid] */ + + +EXTERN_C const IID IID_IInternalConnection; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("72AD0770-6A9F-11d1-BCEC-0060088F444E") + IInternalConnection : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE AddConnection( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReleaseConnection( void) = 0; + + }; + +#else /* C style interface */ + + typedef struct IInternalConnectionVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IInternalConnection * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IInternalConnection * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IInternalConnection * This); + + HRESULT ( STDMETHODCALLTYPE *AddConnection )( + IInternalConnection * This); + + HRESULT ( STDMETHODCALLTYPE *ReleaseConnection )( + IInternalConnection * This); + + END_INTERFACE + } IInternalConnectionVtbl; + + interface IInternalConnection + { + CONST_VTBL struct IInternalConnectionVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IInternalConnection_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IInternalConnection_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IInternalConnection_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IInternalConnection_AddConnection(This) \ + (This)->lpVtbl -> AddConnection(This) + +#define IInternalConnection_ReleaseConnection(This) \ + (This)->lpVtbl -> ReleaseConnection(This) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IInternalConnection_AddConnection_Proxy( + IInternalConnection * This); + + +void __RPC_STUB IInternalConnection_AddConnection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IInternalConnection_ReleaseConnection_Proxy( + IInternalConnection * This); + + +void __RPC_STUB IInternalConnection_ReleaseConnection_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IInternalConnection_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_atliface_0257 */ +/* [local] */ + + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ +#ifdef __cplusplus +#include +#else +#define ATLAPI EXTERN_C HRESULT __declspec(dllimport) __stdcall +#define ATLAPI_(x) EXTERN_C __declspec(dllimport) x __stdcall +#define ATLINLINE +#endif // __cplusplus + +ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); +ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); +#ifdef UNICODE +#define AtlAxDialogBox AtlAxDialogBoxW +#else +#define AtlAxDialogBox AtlAxDialogBoxA +#endif + +ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); +ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam); +#ifdef UNICODE +#define AtlAxCreateDialog AtlAxCreateDialogW +#else +#define AtlAxCreateDialog AtlAxCreateDialogA +#endif + +ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer); +#ifdef __cplusplus +ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, + IUnknown** ppUnkContainer, IUnknown** ppUnkControl, + REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL); +ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic = NULL); +ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, + IUnknown** ppUnkContainer, IUnknown** ppUnkControl, + REFIID iidSink=IID_NULL, IUnknown* punkSink=NULL, BSTR bstrLic = NULL); +#else +ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, + IUnknown** ppUnkContainer, IUnknown** ppUnkControl, + REFIID iidSink, IUnknown* punkSink); +ATLAPI AtlAxCreateControlLic(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer, BSTR bstrLic); +ATLAPI AtlAxCreateControlLicEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, + IUnknown** ppUnkContainer, IUnknown** ppUnkControl, + REFIID iidSink, IUnknown* punkSink, BSTR bstrLic); +#endif // __cplusplus +ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer); +ATLAPI_(BOOL) AtlAxWinInit(); + +ATLAPI AtlAxGetHost(HWND h, IUnknown** pp); +ATLAPI AtlAxGetControl(HWND h, IUnknown** pp); + +}; //namespace ATL +#pragma pack(pop) + +extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_atliface_0257_v0_0_s_ifspec; + +#ifndef __IAccessibleProxy_INTERFACE_DEFINED__ +#define __IAccessibleProxy_INTERFACE_DEFINED__ + +/* interface IAccessibleProxy */ +/* [unique][helpstring][dual][uuid][object] */ + + +EXTERN_C const IID IID_IAccessibleProxy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("7A7D9DCF-B7A1-4019-9031-258268846980") + IAccessibleProxy : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetServer( + /* [in] */ IAccessible *pAccessible, + /* [in] */ IAccessibleServer *pServer) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAccessibleProxyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAccessibleProxy * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAccessibleProxy * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAccessibleProxy * This); + + HRESULT ( STDMETHODCALLTYPE *SetServer )( + IAccessibleProxy * This, + /* [in] */ IAccessible *pAccessible, + /* [in] */ IAccessibleServer *pServer); + + END_INTERFACE + } IAccessibleProxyVtbl; + + interface IAccessibleProxy + { + CONST_VTBL struct IAccessibleProxyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAccessibleProxy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAccessibleProxy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAccessibleProxy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAccessibleProxy_SetServer(This,pAccessible,pServer) \ + (This)->lpVtbl -> SetServer(This,pAccessible,pServer) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAccessibleProxy_SetServer_Proxy( + IAccessibleProxy * This, + /* [in] */ IAccessible *pAccessible, + /* [in] */ IAccessibleServer *pServer); + + +void __RPC_STUB IAccessibleProxy_SetServer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAccessibleProxy_INTERFACE_DEFINED__ */ + + +#ifndef __IAccessibleServer_INTERFACE_DEFINED__ +#define __IAccessibleServer_INTERFACE_DEFINED__ + +/* interface IAccessibleServer */ +/* [unique][helpstring][uuid][object] */ + + +EXTERN_C const IID IID_IAccessibleServer; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("52C8FB5E-D779-4e77-AE9F-F611FA7E9D7A") + IAccessibleServer : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProxy( + /* [in] */ IAccessibleProxy *pUnknown) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetHWND( + /* [out] */ HWND *phWnd) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetEnumVariant( + /* [out] */ IEnumVARIANT **ppEnumVariant) = 0; + + }; + +#else /* C style interface */ + + typedef struct IAccessibleServerVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IAccessibleServer * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IAccessibleServer * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IAccessibleServer * This); + + HRESULT ( STDMETHODCALLTYPE *SetProxy )( + IAccessibleServer * This, + /* [in] */ IAccessibleProxy *pUnknown); + + HRESULT ( STDMETHODCALLTYPE *GetHWND )( + IAccessibleServer * This, + /* [out] */ HWND *phWnd); + + HRESULT ( STDMETHODCALLTYPE *GetEnumVariant )( + IAccessibleServer * This, + /* [out] */ IEnumVARIANT **ppEnumVariant); + + END_INTERFACE + } IAccessibleServerVtbl; + + interface IAccessibleServer + { + CONST_VTBL struct IAccessibleServerVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IAccessibleServer_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IAccessibleServer_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IAccessibleServer_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IAccessibleServer_SetProxy(This,pUnknown) \ + (This)->lpVtbl -> SetProxy(This,pUnknown) + +#define IAccessibleServer_GetHWND(This,phWnd) \ + (This)->lpVtbl -> GetHWND(This,phWnd) + +#define IAccessibleServer_GetEnumVariant(This,ppEnumVariant) \ + (This)->lpVtbl -> GetEnumVariant(This,ppEnumVariant) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IAccessibleServer_SetProxy_Proxy( + IAccessibleServer * This, + /* [in] */ IAccessibleProxy *pUnknown); + + +void __RPC_STUB IAccessibleServer_SetProxy_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAccessibleServer_GetHWND_Proxy( + IAccessibleServer * This, + /* [out] */ HWND *phWnd); + + +void __RPC_STUB IAccessibleServer_GetHWND_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IAccessibleServer_GetEnumVariant_Proxy( + IAccessibleServer * This, + /* [out] */ IEnumVARIANT **ppEnumVariant); + + +void __RPC_STUB IAccessibleServer_GetEnumVariant_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IAccessibleServer_INTERFACE_DEFINED__ */ + + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); +unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); +unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); +void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); + +unsigned long __RPC_USER HWND_UserSize( unsigned long *, unsigned long , HWND * ); +unsigned char * __RPC_USER HWND_UserMarshal( unsigned long *, unsigned char *, HWND * ); +unsigned char * __RPC_USER HWND_UserUnmarshal(unsigned long *, unsigned char *, HWND * ); +void __RPC_USER HWND_UserFree( unsigned long *, HWND * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/c/jacob/include/atlrc.h b/c/jacob/include/atlrc.h new file mode 100644 index 0000000..a231b99 --- /dev/null +++ b/c/jacob/include/atlrc.h @@ -0,0 +1,28 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#pragma once + +#ifndef __ATLRC_H__ + +#define ATL_RESID_BASE 0xD800 +#define ATL_STRING_BASE ATL_RESID_BASE + +#define ATL_IDS_DATETIME_INVALID (ATL_STRING_BASE + 0) +#define ATL_IDS_DATETIMESPAN_INVALID (ATL_STRING_BASE + 1) + +#define ATL_SERVICE_MANAGER_OPEN_ERROR (ATL_STRING_BASE + 10) +#define ATL_SERVICE_START_ERROR (ATL_STRING_BASE + 11) +#define ATL_SERVICE_OPEN_ERROR (ATL_STRING_BASE + 12) +#define ATL_SERVICE_DELETE_ERROR (ATL_STRING_BASE + 13) +#define ATL_SERVICE_STOP_ERROR (ATL_STRING_BASE + 14) + +#endif // __ATLRC_H__ + diff --git a/c/jacob/include/atlsimpcoll.h b/c/jacob/include/atlsimpcoll.h new file mode 100644 index 0000000..8a5277d --- /dev/null +++ b/c/jacob/include/atlsimpcoll.h @@ -0,0 +1,489 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLSIMPCOLL_H__ +#define __ATLSIMPCOLL_H__ + +#pragma once + +#include +#include +#include + +#pragma push_macro("malloc") +#undef malloc +#pragma push_macro("calloc") +#undef calloc +#pragma push_macro("realloc") +#undef realloc +#pragma push_macro("_recalloc") +#undef _recalloc +#pragma push_macro("free") +#undef free + +#pragma warning(push) +#pragma warning(disable: 4800) // forcing 'int' value to bool + + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ + +#pragma push_macro("new") +#undef new + +///////////////////////////////////////////////////////////////////////////// +// Collection helpers - CSimpleArray & CSimpleMap + +// template class helpers with functions for comparing elements +// override if using complex types without operator== +template +class CSimpleArrayEqualHelper +{ +public: + static bool IsEqual(const T& t1, const T& t2) + { + return (t1 == t2); + } +}; + +template +class CSimpleArrayEqualHelperFalse +{ +public: + static bool IsEqual(const T&, const T&) + { + ATLASSERT(false); + return false; + } +}; + +template +class CSimpleMapEqualHelper +{ +public: + static bool IsEqualKey(const TKey& k1, const TKey& k2) + { + return CSimpleArrayEqualHelper::IsEqual(k1, k2); + } + + static bool IsEqualValue(const TVal& v1, const TVal& v2) + { + return CSimpleArrayEqualHelper::IsEqual(v1, v2); + } +}; + +template +class CSimpleMapEqualHelperFalse +{ +public: + static bool IsEqualKey(const TKey& k1, const TKey& k2) + { + return CSimpleArrayEqualHelper::IsEqual(k1, k2); + } + + static bool IsEqualValue(const TVal&, const TVal&) + { + ATLASSERT(FALSE); + return false; + } +}; + +template > +class CSimpleArray +{ +public: +// Construction/destruction + CSimpleArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0) + { } + + ~CSimpleArray(); + + CSimpleArray(const CSimpleArray< T, TEqual >& src) : m_aT(NULL), m_nSize(0), m_nAllocSize(0) + { + if (src.GetSize()) + { + m_aT = (T*)calloc(src.GetSize(), sizeof(T)); + if (m_aT != NULL) + { + m_nAllocSize = src.GetSize(); + for (int i=0; i& operator=(const CSimpleArray< T, TEqual >& src) + { + if (GetSize() != src.GetSize()) + { + RemoveAll(); + m_aT = (T*)calloc(src.GetSize(), sizeof(T)); + if (m_aT != NULL) + m_nAllocSize = src.GetSize(); + } + else + { + for (int i = GetSize(); i > 0; i--) + RemoveAt(i - 1); + } + for (int i=0; iINT_MAX/sizeof(T)) + { + + + return FALSE; + + } + + + + aT = (T*)_recalloc(m_aT, nNewAllocSize, sizeof(T)); + if(aT == NULL) + return FALSE; + m_nAllocSize = nNewAllocSize; + m_aT = aT; + + } + InternalSetAtIndex(m_nSize, t); + m_nSize++; + return TRUE; + } + BOOL Remove(const T& t) + { + int nIndex = Find(t); + if(nIndex == -1) + return FALSE; + return RemoveAt(nIndex); + } + BOOL RemoveAt(int nIndex) + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if (nIndex < 0 || nIndex >= m_nSize) + return FALSE; + m_aT[nIndex].~T(); + if(nIndex != (m_nSize - 1)) + Checked::memmove_s((void*)(m_aT + nIndex), (m_nSize - nIndex) * sizeof(T), (void*)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T)); + m_nSize--; + return TRUE; + } + void RemoveAll() + { + if(m_aT != NULL) + { + for(int i = 0; i < m_nSize; i++) + m_aT[i].~T(); + free(m_aT); + m_aT = NULL; + } + m_nSize = 0; + m_nAllocSize = 0; + } + const T& operator[] (int nIndex) const + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if(nIndex < 0 || nIndex >= m_nSize) + { + _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); + } + return m_aT[nIndex]; + } + T& operator[] (int nIndex) + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if(nIndex < 0 || nIndex >= m_nSize) + { + _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); + } + return m_aT[nIndex]; + } + T* GetData() const + { + return m_aT; + } + + int Find(const T& t) const + { + for(int i = 0; i < m_nSize; i++) + { + if(TEqual::IsEqual(m_aT[i], t)) + return i; + } + return -1; // not found + } + + BOOL SetAtIndex(int nIndex, const T& t) + { + if (nIndex < 0 || nIndex >= m_nSize) + return FALSE; + InternalSetAtIndex(nIndex, t); + return TRUE; + } + +// Implementation + class Wrapper + { + public: + Wrapper(const T& _t) : t(_t) + { + } + template + void * __cdecl operator new(size_t, _Ty* p) + { + return p; + } + template + void __cdecl operator delete(void* /* pv */, _Ty* /* p */) + { + } + T t; + }; + +// Implementation + void InternalSetAtIndex(int nIndex, const T& t) + { + new(m_aT + nIndex) Wrapper(t); + } + + typedef T _ArrayElementType; + T* m_aT; + int m_nSize; + int m_nAllocSize; + +}; + +#define CSimpleValArray CSimpleArray + + template inline CSimpleArray::~CSimpleArray() + { + RemoveAll(); + } + +// intended for small number of simple types or pointers +template > +class CSimpleMap +{ +public: + TKey* m_aKey; + TVal* m_aVal; + int m_nSize; + + typedef TKey _ArrayKeyType; + typedef TVal _ArrayElementType; + +// Construction/destruction + CSimpleMap() : m_aKey(NULL), m_aVal(NULL), m_nSize(0) + { } + + ~CSimpleMap() + { + RemoveAll(); + } + +// Operations + int GetSize() const + { + return m_nSize; + } + BOOL Add(const TKey& key, const TVal& val) + { + TKey* pKey; + pKey = (TKey*)_recalloc(m_aKey, (m_nSize + 1), sizeof(TKey)); + if(pKey == NULL) + return FALSE; + m_aKey = pKey; + TVal* pVal; + pVal = (TVal*)_recalloc(m_aVal, (m_nSize + 1), sizeof(TVal)); + if(pVal == NULL) + return FALSE; + m_aVal = pVal; + InternalSetAtIndex(m_nSize, key, val); + m_nSize++; + return TRUE; + } + BOOL Remove(const TKey& key) + { + int nIndex = FindKey(key); + if(nIndex == -1) + return FALSE; + return RemoveAt(nIndex); + } + BOOL RemoveAt(int nIndex) + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if (nIndex < 0 || nIndex >= m_nSize) + return FALSE; + m_aKey[nIndex].~TKey(); + m_aVal[nIndex].~TVal(); + if(nIndex != (m_nSize - 1)) + { + Checked::memmove_s((void*)(m_aKey + nIndex), (m_nSize - nIndex) * sizeof(TKey), (void*)(m_aKey + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TKey)); + Checked::memmove_s((void*)(m_aVal + nIndex), (m_nSize - nIndex) * sizeof(TVal), (void*)(m_aVal + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(TVal)); + } + TKey* pKey; + pKey = (TKey*)_recalloc(m_aKey, (m_nSize - 1), sizeof(TKey)); + if(pKey != NULL || m_nSize == 1) + m_aKey = pKey; + TVal* pVal; + pVal = (TVal*)_recalloc(m_aVal, (m_nSize - 1), sizeof(TVal)); + if(pVal != NULL || m_nSize == 1) + m_aVal = pVal; + m_nSize--; + return TRUE; + } + void RemoveAll() + { + if(m_aKey != NULL) + { + for(int i = 0; i < m_nSize; i++) + { + m_aKey[i].~TKey(); + m_aVal[i].~TVal(); + } + free(m_aKey); + m_aKey = NULL; + } + if(m_aVal != NULL) + { + free(m_aVal); + m_aVal = NULL; + } + + m_nSize = 0; + } + BOOL SetAt(const TKey& key, const TVal& val) + { + int nIndex = FindKey(key); + if(nIndex == -1) + return FALSE; + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + m_aKey[nIndex].~TKey(); + m_aVal[nIndex].~TVal(); + InternalSetAtIndex(nIndex, key, val); + return TRUE; + } + TVal Lookup(const TKey& key) const + { + int nIndex = FindKey(key); + if(nIndex == -1) + return NULL; // must be able to convert + return GetValueAt(nIndex); + } + TKey ReverseLookup(const TVal& val) const + { + int nIndex = FindVal(val); + if(nIndex == -1) + return NULL; // must be able to convert + return GetKeyAt(nIndex); + } + TKey& GetKeyAt(int nIndex) const + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if(nIndex < 0 || nIndex >= m_nSize) + _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); + + return m_aKey[nIndex]; + } + TVal& GetValueAt(int nIndex) const + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if(nIndex < 0 || nIndex >= m_nSize) + _AtlRaiseException((DWORD)EXCEPTION_ARRAY_BOUNDS_EXCEEDED); + + return m_aVal[nIndex]; + } + + int FindKey(const TKey& key) const + { + for(int i = 0; i < m_nSize; i++) + { + if(TEqual::IsEqualKey(m_aKey[i], key)) + return i; + } + return -1; // not found + } + int FindVal(const TVal& val) const + { + for(int i = 0; i < m_nSize; i++) + { + if(TEqual::IsEqualValue(m_aVal[i], val)) + return i; + } + return -1; // not found + } + + BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val) + { + if (nIndex < 0 || nIndex >= m_nSize) + return FALSE; + InternalSetAtIndex(nIndex, key, val); + return TRUE; + } + + +// Implementation + + template + class Wrapper + { + public: + Wrapper(const T& _t) : t(_t) + { + } + template + void *operator new(size_t, _Ty* p) + { + return p; + } + template + void operator delete(void* /* pv */, _Ty* /* p */) + { + } + T t; + }; + void InternalSetAtIndex(int nIndex, const TKey& key, const TVal& val) + { + new(m_aKey + nIndex) Wrapper(key); + new(m_aVal + nIndex) Wrapper(val); + } +}; + +#pragma pop_macro("new") + +}; // namespace ATL +#pragma pack(pop) + +#pragma warning(pop) + +#pragma pop_macro("free") +#pragma pop_macro("realloc") +#pragma pop_macro("_recalloc") +#pragma pop_macro("malloc") +#pragma pop_macro("calloc") + + +#endif // __ATLSIMPCOLL_H__ + diff --git a/c/jacob/include/atltrace.h b/c/jacob/include/atltrace.h new file mode 100644 index 0000000..bcd05b3 --- /dev/null +++ b/c/jacob/include/atltrace.h @@ -0,0 +1,450 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __ATLTRACE_H__ +#define __ATLTRACE_H__ + +#pragma once + +#include +#include + +#ifdef _DEBUG +#include +#include +#endif + +#ifdef _DEBUG +#include + +extern "C" IMAGE_DOS_HEADER __ImageBase; +#endif // _DEBUG + + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ + +// Declare a global instance of this class to automatically register a custom trace category at startup +class CTraceCategory +{ +public: + explicit CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel = 0 ) throw(); + +#ifdef _DEBUG + UINT GetLevel() const throw(); + void SetLevel( UINT nLevel ) throw(); + ATLTRACESTATUS GetStatus() const throw(); + void SetStatus( ATLTRACESTATUS eStatus) throw(); +#endif + + operator DWORD_PTR() const throw(); + +public: +#ifdef _DEBUG + DWORD_PTR m_dwCategory; +#endif +}; + +#ifdef _DEBUG + +class CTrace +{ +public: + typedef int (__cdecl *fnCrtDbgReport_t)(int,const char *,int,const char *,const char *,...); + +private: + CTrace( +#ifdef _ATL_NO_DEBUG_CRT + fnCrtDbgReport_t pfnCrtDbgReport = NULL) +#else + fnCrtDbgReport_t pfnCrtDbgReport = _CrtDbgReport) +#endif + : m_hInst(reinterpret_cast(&__ImageBase)), + m_dwModule( 0 ) + { + m_dwModule = AtlTraceRegister(m_hInst, pfnCrtDbgReport); + } + + ~CTrace() + { + AtlTraceUnregister(m_dwModule); + } + +public: + bool ChangeCategory(DWORD_PTR dwCategory, UINT nLevel, ATLTRACESTATUS eStatus) + { + return 0 != + AtlTraceModifyCategory(0, dwCategory, nLevel, eStatus); + } + + bool GetCategory(DWORD_PTR dwCategory, UINT *pnLevel, ATLTRACESTATUS *peStatus) + { + ATLASSERT(pnLevel && peStatus); + return 0 != AtlTraceGetCategory(0, dwCategory, pnLevel, peStatus); + } + UINT GetLevel() + { + ATLTRACESTATUS eStatus; + UINT nLevel; + AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); + + return nLevel; + } + void SetLevel(UINT nLevel) + { + AtlTraceModifyModule(0, m_dwModule, nLevel, ATLTRACESTATUS_ENABLED); + } + ATLTRACESTATUS GetStatus() + { + ATLTRACESTATUS eStatus; + UINT nLevel; + AtlTraceGetModule(0, m_dwModule, &nLevel, &eStatus); + + return eStatus; + } + void SetStatus(ATLTRACESTATUS eStatus) + { + ATLTRACESTATUS eOldStatus; + UINT nLevel; + AtlTraceGetModule(0, m_dwModule, &nLevel, &eOldStatus); + AtlTraceModifyModule(0, m_dwModule, nLevel, eStatus); + } + void __cdecl TraceV(const char *pszFileName, int nLine, + DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const; + void __cdecl TraceV(const char *pszFileName, int nLine, + DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const; + + DWORD_PTR RegisterCategory(LPCSTR pszCategory) + {return(AtlTraceRegisterCategoryA(m_dwModule, pszCategory));} +#ifdef _UNICODE + DWORD_PTR RegisterCategory(LPCWSTR pszCategory) + {return(AtlTraceRegisterCategoryU(m_dwModule, pszCategory));} +#endif + + bool LoadSettings(LPCTSTR pszFileName = NULL) const + {return 0 != AtlTraceLoadSettings(pszFileName);} + void SaveSettings(LPCTSTR pszFileName = NULL) const + {AtlTraceSaveSettings(pszFileName);} + +public: + static CTrace s_trace; + +protected: + HINSTANCE m_hInst; + DWORD_PTR m_dwModule; +}; + + inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine, + DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFmt, va_list args) const + { + AtlTraceVA(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); + } + inline void __cdecl CTrace::TraceV(const char *pszFileName, int nLine, + DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFmt, va_list args) const + { + AtlTraceVU(m_dwModule, pszFileName, nLine, dwCategory, nLevel, pszFmt, args); + } + +extern CTraceCategory atlTraceGeneral; + +class CTraceFileAndLineInfo +{ +public: + CTraceFileAndLineInfo(const char *pszFileName, int nLineNo) + : m_pszFileName(pszFileName), m_nLineNo(nLineNo) + {} + +#pragma warning(push) +#pragma warning(disable : 4793) + void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const char *pszFmt, ...) const + { + va_list ptr; va_start(ptr, pszFmt); + ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); + va_end(ptr); + } +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) + void __cdecl operator()(DWORD_PTR dwCategory, UINT nLevel, const wchar_t *pszFmt, ...) const + { + va_list ptr; va_start(ptr, pszFmt); + ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, dwCategory, nLevel, pszFmt, ptr); + va_end(ptr); + } +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) + void __cdecl operator()(const char *pszFmt, ...) const + { + va_list ptr; va_start(ptr, pszFmt); + ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); + va_end(ptr); + } +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) + void __cdecl operator()(const wchar_t *pszFmt, ...) const + { + va_list ptr; va_start(ptr, pszFmt); + ATL::CTrace::s_trace.TraceV(m_pszFileName, m_nLineNo, atlTraceGeneral, 0, pszFmt, ptr); + va_end(ptr); + } +#pragma warning(pop) + +private: + /* unimplemented */ + CTraceFileAndLineInfo &__cdecl operator=(const CTraceFileAndLineInfo &right); + + const char *const m_pszFileName; + const int m_nLineNo; +}; + +#endif // _DEBUG + +#ifdef _DEBUG + +inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() : + m_dwCategory( 0 ) +{ + m_dwCategory = ATL::CTrace::s_trace.RegisterCategory( pszCategoryName ); + ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nStartingLevel, ATLTRACESTATUS_INHERIT); +} + +inline CTraceCategory::operator DWORD_PTR() const throw() +{ + return( m_dwCategory ); +} + +inline UINT CTraceCategory::GetLevel() const throw() +{ + UINT nLevel; + ATLTRACESTATUS eStatus; + ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); + + return( nLevel ); +} + +inline void CTraceCategory::SetLevel( UINT nLevel ) throw() +{ + ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, ATLTRACESTATUS_ENABLED ); +} + +inline ATLTRACESTATUS CTraceCategory::GetStatus() const throw() +{ + UINT nLevel; + ATLTRACESTATUS eStatus; + ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eStatus ); + + return( eStatus ); +} + +inline void CTraceCategory::SetStatus( ATLTRACESTATUS eStatus ) throw() +{ + UINT nLevel; + ATLTRACESTATUS eOldStatus; + ATL::CTrace::s_trace.GetCategory( m_dwCategory, &nLevel, &eOldStatus ); + ATL::CTrace::s_trace.ChangeCategory( m_dwCategory, nLevel, eStatus ); +} + +#else // !_DEBUG + +inline CTraceCategory::CTraceCategory( LPCTSTR pszCategoryName, UINT nStartingLevel ) throw() +{ + (void)pszCategoryName; + (void)nStartingLevel; +} + +inline CTraceCategory::operator DWORD_PTR() const throw() +{ + return( 0 ); +} + +#endif // _DEBUG + +} // namespace ATL + +namespace ATL +{ + +#ifdef _DEBUG +#define DECLARE_TRACE_CATEGORY( name ) extern ATL::CTraceCategory name; +#else +#define DECLARE_TRACE_CATEGORY( name ) const DWORD_PTR name = 0; +#endif + +DECLARE_TRACE_CATEGORY( atlTraceGeneral ) +DECLARE_TRACE_CATEGORY( atlTraceCOM ) +DECLARE_TRACE_CATEGORY( atlTraceQI ) +DECLARE_TRACE_CATEGORY( atlTraceRegistrar ) +DECLARE_TRACE_CATEGORY( atlTraceRefcount ) +DECLARE_TRACE_CATEGORY( atlTraceWindowing ) +DECLARE_TRACE_CATEGORY( atlTraceControls ) +DECLARE_TRACE_CATEGORY( atlTraceHosting ) +DECLARE_TRACE_CATEGORY( atlTraceDBClient ) +DECLARE_TRACE_CATEGORY( atlTraceDBProvider ) +DECLARE_TRACE_CATEGORY( atlTraceSnapin ) +DECLARE_TRACE_CATEGORY( atlTraceNotImpl ) +DECLARE_TRACE_CATEGORY( atlTraceAllocation ) +DECLARE_TRACE_CATEGORY( atlTraceException ) +DECLARE_TRACE_CATEGORY( atlTraceTime ) +DECLARE_TRACE_CATEGORY( atlTraceCache ) +DECLARE_TRACE_CATEGORY( atlTraceStencil ) +DECLARE_TRACE_CATEGORY( atlTraceString ) +DECLARE_TRACE_CATEGORY( atlTraceMap ) +DECLARE_TRACE_CATEGORY( atlTraceUtil ) +DECLARE_TRACE_CATEGORY( atlTraceSecurity ) +DECLARE_TRACE_CATEGORY( atlTraceSync ) +DECLARE_TRACE_CATEGORY( atlTraceISAPI ) + +// atlTraceUser categories are no longer needed. Just declare your own trace category using CTraceCategory. +DECLARE_TRACE_CATEGORY( atlTraceUser ) +DECLARE_TRACE_CATEGORY( atlTraceUser2 ) +DECLARE_TRACE_CATEGORY( atlTraceUser3 ) +DECLARE_TRACE_CATEGORY( atlTraceUser4 ) + +#pragma deprecated( atlTraceUser ) +#pragma deprecated( atlTraceUser2 ) +#pragma deprecated( atlTraceUser3 ) +#pragma deprecated( atlTraceUser4 ) + +#ifdef _DEBUG + +#ifndef _ATL_NO_DEBUG_CRT +class CNoUIAssertHook +{ +public: + CNoUIAssertHook() + { + ATLASSERT( s_pfnPrevHook == NULL ); + s_pfnPrevHook = _CrtSetReportHook(CrtHookProc); + } + ~CNoUIAssertHook() + { + _CrtSetReportHook(s_pfnPrevHook); + s_pfnPrevHook = NULL; + } + +private: + static int __cdecl CrtHookProc(__in int eReportType, __in_z char* pszMessage, __out int* pnRetVal) + { + + if (eReportType == _CRT_ASSERT) + { + ::OutputDebugStringA( "ASSERTION FAILED\n" ); + ::OutputDebugStringA( pszMessage ); + //If caller doesn't want retVal, so be it. + if (pnRetVal != NULL) + { + *pnRetVal = 1; + } + return TRUE; + } + + if (s_pfnPrevHook != NULL) + { + return s_pfnPrevHook(eReportType, pszMessage, pnRetVal); + } + else + { + return FALSE; + } + } + +private: + static _CRT_REPORT_HOOK s_pfnPrevHook; +}; + +__declspec( selectany ) _CRT_REPORT_HOOK CNoUIAssertHook::s_pfnPrevHook = NULL; + +#define DECLARE_NOUIASSERT() ATL::CNoUIAssertHook _g_NoUIAssertHook; + +#endif // _ATL_NO_DEBUG_CRT + +#ifndef ATLTRACE +#define ATLTRACE ATL::CTraceFileAndLineInfo(__FILE__, __LINE__) +#define ATLTRACE2 ATLTRACE +#endif + +#pragma warning(push) +#pragma warning(disable : 4793) +inline void __cdecl AtlTrace(LPCSTR pszFormat, ...) +{ + va_list ptr; + va_start(ptr, pszFormat); + ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); + va_end(ptr); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) +inline void __cdecl AtlTrace(LPCWSTR pszFormat, ...) +{ + va_list ptr; + va_start(ptr, pszFormat); + ATL::CTrace::s_trace.TraceV(NULL, -1, atlTraceGeneral, 0, pszFormat, ptr); + va_end(ptr); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) +inline void __cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCSTR pszFormat, ...) +{ + va_list ptr; + va_start(ptr, pszFormat); + ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); + va_end(ptr); +} +#pragma warning(pop) + +#pragma warning(push) +#pragma warning(disable : 4793) +inline void __cdecl AtlTrace2(DWORD_PTR dwCategory, UINT nLevel, LPCWSTR pszFormat, ...) +{ + va_list ptr; + va_start(ptr, pszFormat); + ATL::CTrace::s_trace.TraceV(NULL, -1, dwCategory, nLevel, pszFormat, ptr); + va_end(ptr); +} +#pragma warning(pop) + +#define ATLTRACENOTIMPL(funcname) do { ATLTRACE(ATL::atlTraceNotImpl, 0, _T("ATL: %s not implemented.\n"), funcname); return E_NOTIMPL; } while(0) + +#else // !DEBUG + +#pragma warning(push) +#pragma warning(disable : 4793) +inline void __cdecl AtlTraceNull(...){} +inline void __cdecl AtlTrace(LPCSTR , ...){} +inline void __cdecl AtlTrace2(DWORD_PTR, UINT, LPCSTR , ...){} +inline void __cdecl AtlTrace(LPCWSTR , ...){} +inline void __cdecl AtlTrace2(DWORD_PTR, UINT, LPCWSTR , ...){} +#pragma warning(pop) + +#ifndef ATLTRACE + +#define ATLTRACE __noop +#define ATLTRACE2 __noop +#endif //ATLTRACE +#define ATLTRACENOTIMPL(funcname) return E_NOTIMPL +#define DECLARE_NOUIASSERT() + +#endif //!_DEBUG + +}; // namespace ATL +#pragma pack(pop) + +#endif // __ATLTRACE_H__ + diff --git a/c/jacob/include/statreg.h b/c/jacob/include/statreg.h new file mode 100644 index 0000000..2dc76aa --- /dev/null +++ b/c/jacob/include/statreg.h @@ -0,0 +1,1509 @@ +// This is a part of the Active Template Library. +// Copyright (C) Microsoft Corporation +// All rights reserved. +// +// This source code is only intended as a supplement to the +// Active Template Library Reference and related +// electronic documentation provided with the library. +// See these sources for detailed information regarding the +// Active Template Library product. + +#ifndef __STATREG_H__ +#define __STATREG_H__ + +#pragma once + +#ifndef __cplusplus + #error ATL requires C++ compilation (use a .cpp suffix) +#endif + +#ifndef __ATLBASE_H__ + #error statreg.h requires atlbase.h to be included first +#endif + +#pragma warning(push) +#pragma warning(disable:4571) //catch(...) blocks compiled with /EHs do NOT catch or re-throw Structured Exceptions + +// SAL requires macro definition +#define MAX_VALUE_VALUE 4096 + +#define E_ATL_REGISTRAR_DESC 0x0201 +#define E_ATL_NOT_IN_MAP 0x0202 +#define E_ATL_UNEXPECTED_EOS 0x0203 +#define E_ATL_VALUE_SET_FAILED 0x0204 +#define E_ATL_RECURSE_DELETE_FAILED 0x0205 +#define E_ATL_EXPECTING_EQUAL 0x0206 +#define E_ATL_CREATE_KEY_FAILED 0x0207 +#define E_ATL_DELETE_KEY_FAILED 0x0208 +#define E_ATL_OPEN_KEY_FAILED 0x0209 +#define E_ATL_CLOSE_KEY_FAILED 0x020A +#define E_ATL_UNABLE_TO_COERCE 0x020B +#define E_ATL_BAD_HKEY 0x020C +#define E_ATL_MISSING_OPENKEY_TOKEN 0x020D +#define E_ATL_CONVERT_FAILED 0x020E +#define E_ATL_TYPE_NOT_SUPPORTED 0x020F +#define E_ATL_COULD_NOT_CONCAT 0x0210 +#define E_ATL_COMPOUND_KEY 0x0211 +#define E_ATL_INVALID_MAPKEY 0x0212 +#define E_ATL_UNSUPPORTED_VT 0x0213 +#define E_ATL_VALUE_GET_FAILED 0x0214 +#define E_ATL_VALUE_TOO_LARGE 0x0215 +#define E_ATL_MISSING_VALUE_DELIMETER 0x0216 +#define E_ATL_DATA_NOT_BYTE_ALIGNED 0x0217 + +#pragma pack(push,_ATL_PACKING) +namespace ATL +{ +const TCHAR chDirSep = _T('\\'); +const TCHAR chRightBracket = _T('}'); +const TCHAR chLeftBracket = _T('{'); +const TCHAR chQuote = _T('\''); +const TCHAR chEquals = _T('='); +const LPCTSTR szStringVal = _T("S"); +const LPCTSTR multiszStringVal = _T("M"); +const LPCTSTR szDwordVal = _T("D"); +const LPCTSTR szBinaryVal = _T("B"); +const LPCTSTR szValToken = _T("Val"); +const LPCTSTR szForceRemove = _T("ForceRemove"); +const LPCTSTR szNoRemove = _T("NoRemove"); +const LPCTSTR szDelete = _T("Delete"); + + +// Implementation helper +class CExpansionVectorEqualHelper +{ +public: + static bool IsEqualKey(__in_z const LPTSTR k1, __in_z const LPTSTR k2) + { + if (lstrcmpi(k1, k2) == 0) + return true; + return false; + } + + // Not used + static bool IsEqualValue(const LPCOLESTR /*v1*/, const LPCOLESTR /*v2*/) + { + return false; + } +}; + +// Implementation helper +class CExpansionVector : public CSimpleMap +{ +public: + ~CExpansionVector() + { + ClearReplacements(); + } + + BOOL Add(LPCTSTR lpszKey, LPCOLESTR lpszValue) + { + ATLASSERT(lpszKey != NULL && lpszValue != NULL); + if (lpszKey == NULL || lpszValue == NULL) + return FALSE; + + HRESULT hRes = S_OK; + + size_t cbKey = (lstrlen(lpszKey)+1)*sizeof(TCHAR); + TCHAR* szKey = NULL; + +#pragma warning(push) +#pragma warning(disable: 28197 28198) + + ATLTRY(szKey = new TCHAR[cbKey];) + +#pragma warning(pop) + + CAutoVectorPtr spKey; + spKey.Attach(szKey); + + size_t cbValue = (ocslen(lpszValue)+1)*sizeof(OLECHAR); + LPOLESTR szValue = NULL; + +#pragma warning(push) +#pragma warning(disable: 28197) + + ATLTRY(szValue = new OLECHAR[cbValue];) + +#pragma warning(pop) + + CAutoVectorPtr spValue; + spValue.Attach(szValue); + + if (szKey == NULL || szValue == NULL) + hRes = E_OUTOFMEMORY; + else + { + Checked::memcpy_s(szKey, cbKey, lpszKey, cbKey); + Checked::memcpy_s(szValue, cbValue, lpszValue, cbValue); + if (!CSimpleMap::Add(szKey, szValue)) + hRes = E_OUTOFMEMORY; + } + if (SUCCEEDED(hRes)) + { + spKey.Detach(); + spValue.Detach(); + } + return SUCCEEDED(hRes); + } + HRESULT ClearReplacements() + { + for (int i = 0; i < GetSize(); i++) + { + delete []GetKeyAt(i); + delete []GetValueAt(i); + } + RemoveAll(); + return S_OK; + } +}; + +class CRegObject; + +class CRegParser +{ +public: + CRegParser(CRegObject* pRegObj); + + HRESULT PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z LPTSTR* ppszReg); + HRESULT RegisterBuffer(__in_z LPTSTR szReg, BOOL bRegister); + +protected: + + void SkipWhiteSpace(); + HRESULT NextToken(__out_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken); + HRESULT AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR szValueName, __out_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken); + BOOL CanForceRemoveKey(LPCTSTR szKey); + BOOL HasSubKeys(HKEY hkey); + BOOL HasValues(HKEY hkey); + HRESULT RegisterSubkeys(__out_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken, __in HKEY hkParent, __in BOOL bRegister, __in BOOL bInRecovery = FALSE); + BOOL IsSpace(TCHAR ch); + LPTSTR m_pchCur; + + CRegObject* m_pRegObj; + + HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} + //HRESULT HandleReplacements(LPTSTR& szToken); + HRESULT SkipAssignment(__inout_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken); + + BOOL EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pchCur); } + static LPTSTR StrChr(__in_z LPTSTR lpsz, __in TCHAR ch); + static HKEY HKeyFromString(__in_z LPTSTR szToken); + static BYTE ChToByte(const TCHAR ch); + static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt); + static const TCHAR* const rgszNeverDelete[]; + static const int cbNeverDelete; + static const int MAX_VALUE = MAX_VALUE_VALUE; + static const int MAX_TYPE = 4096; + + + // Implementation Helper + class CParseBuffer + { + public: + int nPos; + int nSize; + __field_ecount(nSize) LPTSTR p; + CParseBuffer(int nInitial) + { + if (nInitial < 100) + nInitial = 1000; + nPos = 0; + nSize = nInitial; + p = (LPTSTR) ::ATL::AtlCoTaskMemCAlloc(nSize,static_cast(sizeof(TCHAR))); + if (p != NULL) + *p = NULL; + } + ~CParseBuffer() + { + CoTaskMemFree(p); + } + BOOL Append(const TCHAR* pch, int nChars) + { + ATLASSERT(p != NULL); + int newSize = nPos + nChars + 1; + if ((newSize <= nPos) || (newSize <= nChars)) + return FALSE; + + if (newSize >= nSize) + { + int nTempSize = nSize; + while (newSize >= nTempSize) { + if (nTempSize > INT_MAX / 2) + return FALSE; + nTempSize *= 2; + } + LPTSTR pTemp = (LPTSTR)::ATL::AtlCoTaskMemRecalloc(p, nTempSize, sizeof(TCHAR)); + if (pTemp == NULL) + return FALSE; + p = pTemp; + nSize = nTempSize; + } + if ((nPos < 0) || (nPos >= nSize) || nSize - nPos > nSize) + return FALSE; + +#pragma warning(push) +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if ((defined(_PREFIX_)) || (defined(_PREFAST_))) && (_MSC_VER < 1400) + // do nothing, this pragma not understood by PREfix 5.1 +#else // !_PREFIX_ +#pragma warning(disable: 22008) +#endif + /* Prefast false warning is fired here despite the all above checks */ + Checked::memcpy_s(p + nPos, (nSize-nPos) * sizeof(TCHAR), pch, int(nChars * sizeof(TCHAR))); + nPos += nChars; + *(p + nPos) = NULL; +#pragma warning(pop) + return TRUE; + } + + BOOL AddChar(const TCHAR* pch) + { +#ifndef _UNICODE + int nChars = int(CharNext(pch) - pch); +#else + int nChars = 1; +#endif + return Append(pch, nChars); + + } + BOOL AddString(LPCOLESTR lpsz) + { + if (lpsz == NULL) + { + return FALSE; + } + USES_CONVERSION_EX; + LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + if (lpszT == NULL) + { + return FALSE; + } + return Append(lpszT, (int)lstrlen(lpszT)); + } + LPTSTR Detach() + { + LPTSTR lp = p; + p = NULL; + nSize = nPos = 0; + return lp; + } + + }; +}; + +#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) +class ATL_NO_VTABLE CRegObject + : public IRegistrar +#else +class CRegObject : public IRegistrarBase +#endif +{ +public: + +#if defined(_ATL_DLL) || defined(_ATL_DLL_IMPL) + +#else + STDMETHOD(QueryInterface)(const IID &,void **ppv) + { + ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); + if (ppv) *ppv = NULL; + return E_NOTIMPL; + } + + STDMETHOD_(ULONG, AddRef)(void) + { + ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); + return 1; + } + STDMETHOD_(ULONG, Release)(void) + { + ATLASSERT(_T("statically linked in CRegObject is not a com object. Do not callthis function")); + return 0; + } +#endif + virtual ~CRegObject(){ClearReplacements();} + HRESULT FinalConstruct() { return m_csMap.Init(); } + void FinalRelease() {} + + + // Map based methods + HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem); + HRESULT STDMETHODCALLTYPE ClearReplacements(); + LPCOLESTR StrFromMap(__in_z LPTSTR lpszKey); + + // Register via a given mechanism + HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); + HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); + HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR pszFileName, UINT nID, LPCOLESTR pszType); + HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR pszFileName, LPCOLESTR pszID, LPCOLESTR pszType); + HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR bstrFileName) + { + return CommonFileRegister(bstrFileName, TRUE); + } + + HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR bstrFileName) + { + return CommonFileRegister(bstrFileName, FALSE); + } + + HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR bstrData) + { + return RegisterWithString(bstrData, TRUE); + } + + HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR bstrData) + { + return RegisterWithString(bstrData, FALSE); + } + +protected: + + HRESULT CommonFileRegister(LPCOLESTR pszFileName, BOOL bRegister); + HRESULT RegisterFromResource(LPCOLESTR pszFileName, LPCTSTR pszID, LPCTSTR pszType, BOOL bRegister); + HRESULT RegisterWithString(LPCOLESTR pszData, BOOL bRegister); + + static HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} + + CExpansionVector m_RepMap; + CComObjectThreadModel::AutoDeleteCriticalSection m_csMap; +}; + +inline HRESULT STDMETHODCALLTYPE CRegObject::AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem) +{ + if (lpszKey == NULL || lpszItem == NULL) + return E_INVALIDARG; + m_csMap.Lock(); + USES_CONVERSION_EX; + + LPCTSTR lpszT = OLE2CT_EX(lpszKey, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + +#ifndef _UNICODE + if(lpszT == NULL) { + m_csMap.Unlock(); + return E_OUTOFMEMORY; + } +#endif + + BOOL bRet = m_RepMap.Add(lpszT, lpszItem); + m_csMap.Unlock(); + return bRet ? S_OK : E_OUTOFMEMORY; +} + +inline HRESULT CRegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR szID, + LPCTSTR szType, BOOL bRegister) +{ + USES_CONVERSION_EX; + + HRESULT hr; + CRegParser parser(this); + HINSTANCE hInstResDll; + HRSRC hrscReg; + HGLOBAL hReg; + DWORD dwSize; + LPSTR szRegA; + CTempBuffer szReg; + + LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszBSTRFileName == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + + hInstResDll = LoadLibraryEx(lpszBSTRFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); + + if (NULL == hInstResDll) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadLibrary on %s\n"), bstrFileName); + hr = AtlHresultFromLastError(); + goto ReturnHR; + } + + hrscReg =FindResource((HMODULE)hInstResDll, szID, szType); + + if (NULL == hrscReg) + { + ATLTRACE(atlTraceRegistrar, 0, (HIWORD(szID) == NULL) ? + _T("Failed to FindResource on ID:%d TYPE:%s\n") : + _T("Failed to FindResource on ID:%s TYPE:%s\n"), + szID, szType); + hr = AtlHresultFromLastError(); + goto ReturnHR; + } + hReg = LoadResource((HMODULE)hInstResDll, hrscReg); + + if (NULL == hReg) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadResource\n")); + hr = AtlHresultFromLastError(); + goto ReturnHR; + } + + dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg); + szRegA = (LPSTR)hReg; + + // Allocate extra space for NULL. + if (dwSize + 1 < dwSize) + return E_OUTOFMEMORY; + ATLTRY(szReg.Allocate(dwSize + 1)); + if (szReg == NULL) + { + hr = E_OUTOFMEMORY; + goto ReturnHR; + } + +#ifdef _UNICODE + DWORD uniSize = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, szRegA, dwSize, szReg, dwSize); + if (uniSize == 0) + { + hr = AtlHresultFromLastError(); + goto ReturnHR; + } + // Append a NULL at the end. + szReg[uniSize] = NULL; +#else + Checked::memcpy_s(szReg, dwSize, szRegA, dwSize); + // Append a NULL at the end. + szReg[dwSize] = NULL; +#endif + + + + hr = parser.RegisterBuffer(szReg, bRegister); + +ReturnHR: + + if (NULL != hInstResDll) + FreeLibrary((HMODULE)hInstResDll); + return hr; +} + +inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) +{ + USES_CONVERSION_EX; + + LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszT == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + + return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, TRUE); +} + +inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceRegisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) +{ + USES_CONVERSION_EX; + if (szID == NULL || szType == NULL) + return E_INVALIDARG; + + LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszID == NULL || lpszType==NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + return RegisterFromResource(szFileName, lpszID, lpszType, TRUE); +} + +inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregister(LPCOLESTR szFileName, UINT nID, LPCOLESTR szType) +{ + USES_CONVERSION_EX; + + LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszT == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, FALSE); +} + +inline HRESULT STDMETHODCALLTYPE CRegObject::ResourceUnregisterSz(LPCOLESTR szFileName, LPCOLESTR szID, LPCOLESTR szType) +{ + USES_CONVERSION_EX; + if (szID == NULL || szType == NULL) + return E_INVALIDARG; + + LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszID == NULL || lpszType == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + + return RegisterFromResource(szFileName, lpszID, lpszType, FALSE); +} + +inline HRESULT CRegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister) +{ + USES_CONVERSION_EX; + CRegParser parser(this); + + LPCTSTR szReg = OLE2CT_EX(bstrData, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (szReg == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + + HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister); + + return hr; +} + +inline HRESULT CRegObject::ClearReplacements() +{ + m_csMap.Lock(); + HRESULT hr = m_RepMap.ClearReplacements(); + m_csMap.Unlock(); + return hr; +} + + +inline LPCOLESTR CRegObject::StrFromMap(__in_z LPTSTR lpszKey) +{ + m_csMap.Lock(); + LPCOLESTR lpsz = m_RepMap.Lookup(lpszKey); + if (lpsz == NULL) // not found!! + ATLTRACE(atlTraceRegistrar, 0, _T("Map Entry not found\n")); + m_csMap.Unlock(); + return lpsz; +} + +inline HRESULT CRegObject::CommonFileRegister(LPCOLESTR bstrFileName, BOOL bRegister) +{ + USES_CONVERSION_EX; + + CRegParser parser(this); + + LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); +#ifndef _UNICODE + if (lpszBSTRFileName == NULL) + { + return E_OUTOFMEMORY; + } +#endif // _UNICODE + + HANDLE hFile = CreateFile(lpszBSTRFileName, GENERIC_READ, 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, + NULL); + if (INVALID_HANDLE_VALUE == hFile) + { + ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to CreateFile on %s\n"), lpszBSTRFileName); + return AtlHresultFromLastError(); + } + + HRESULT hRes = S_OK; + DWORD cbRead; + DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required + + CTempBuffer szReg; + // Extra space for NULL. + ATLTRY(szReg.Allocate(cbFile + 1)); + if (szReg == NULL) + { + hRes = E_OUTOFMEMORY; + goto ReturnHR; + } + + if (ReadFile(hFile, szReg, cbFile, &cbRead, NULL) == 0) + { + ATLTRACE2(atlTraceRegistrar, 0, "Read Failed on file%s\n", lpszBSTRFileName); + hRes = AtlHresultFromLastError(); + } + if (SUCCEEDED(hRes)) + { + szReg[cbRead] = NULL; + +#ifdef _UNICODE + CTempBuffer szConverted; + ATLTRY(szConverted.Allocate(cbFile + 1)); + if (szConverted == NULL) + { + hRes = E_OUTOFMEMORY; + goto ReturnHR; + + } + if (::MultiByteToWideChar(_AtlGetConversionACP(), 0, szReg, cbFile + 1, szConverted, cbFile + 1) == 0) + { + hRes = AtlHresultFromLastError(); + goto ReturnHR; + } + + + + +#else + LPTSTR szConverted = szReg; +#endif + hRes = parser.RegisterBuffer(szConverted, bRegister); + } +ReturnHR: + CloseHandle(hFile); + return hRes; +} + +__declspec(selectany) const TCHAR* const CRegParser::rgszNeverDelete[] = +{ + _T("AppID"), + _T("CLSID"), + _T("Component Categories"), + _T("FileType"), + _T("Interface"), + _T("Hardware"), + _T("Mime"), + _T("SAM"), + _T("SECURITY"), + _T("SYSTEM"), + _T("Software"), + _T("TypeLib") +}; + +__declspec(selectany) const int CRegParser::cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*); + + +inline BOOL CRegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt) +{ +// +// [pfx_parse] - workaround for PREfix parse problem +// +#if defined(_PREFIX_) || defined(_PREFAST_) + UNREFERENCED_PARAMETER(szValueType); + UNREFERENCED_PARAMETER(vt); + return FALSE; +#else + + struct typemap + { + LPCTSTR lpsz; + VARTYPE vt; + }; +#pragma warning (push) +#pragma warning (disable : 4640) // construction of local static object is not thread-safe + + static const typemap map[] = { + {szStringVal, VT_BSTR}, + {multiszStringVal, VT_BSTR | VT_BYREF}, + {szDwordVal, VT_UI4}, + {szBinaryVal, VT_UI1} + }; + +#pragma warning (pop) + + for (int i=0;i= szOrig + MAX_VALUE) + return GenerateError(E_ATL_VALUE_TOO_LARGE); + + for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) + *szToken = *pchPrev; + } + + if (NULL == *m_pchCur) + { + ATLTRACE(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File\n")); + return GenerateError(E_ATL_UNEXPECTED_EOS); + } + + *szToken = NULL; + m_pchCur = CharNext(m_pchCur); + } + + else + { + // Handle non-quoted ie parse up till first "White Space" + while (NULL != *m_pchCur && !IsSpace(*m_pchCur)) + { + LPTSTR pchPrev = m_pchCur; + m_pchCur = CharNext(m_pchCur); + + INT_PTR nChars = m_pchCur - pchPrev; + + // Make sure we have room for nChars plus terminating NULL + if ((szToken + nChars + 1) >= szOrig + MAX_VALUE) + return GenerateError(E_ATL_VALUE_TOO_LARGE); + + for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) + *szToken = *pchPrev; + } + + *szToken = NULL; + } + return S_OK; +} + +inline HRESULT CRegParser::AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR szValueName, __out_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken) +{ + HRESULT hr; + + TCHAR szValue[MAX_VALUE]; + VARTYPE vt = VT_EMPTY; + LONG lRes = ERROR_SUCCESS; + UINT nIDRes = 0; + + if (FAILED(hr = NextToken(szValue))) + return hr; + if (!VTFromRegType(szValue, vt)) + { + ATLTRACE(atlTraceRegistrar, 0, _T("%s Type not supported\n"), szValue); + return GenerateError(E_ATL_TYPE_NOT_SUPPORTED); + } + + SkipWhiteSpace(); + if (FAILED(hr = NextToken(szValue))) + return hr; + + switch (vt) + { + case VT_BSTR: + { + lRes = rkParent.SetStringValue(szValueName, szValue); + ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); + break; + } + case VT_BSTR | VT_BYREF: + { + ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !szValueName ? _T("default") : szValueName); + int nLen = lstrlen(szValue) + 2; //Allocate space for double null termination. + CTempBuffer pszDestValue; + //nLen should be >= the max size of the target buffer. + ATLTRY(pszDestValue.Allocate(nLen)); + if (pszDestValue != NULL) + { + TCHAR* p = pszDestValue; + TCHAR* q = szValue; + nLen = 0; + while (*q != _T('\0')) + { + TCHAR* r = CharNext(q); + if (*q == _T('\\') && *r == _T('0')) + { + *p++ = NULL; + q = CharNext(r); + } + else + { + *p = *q; +#ifndef _UNICODE + if (IsDBCSLeadByte(*q)) + { + p++; + q++; + //Protect from Lead byte followed by the zero terminator.May skip beyond the end of the string. + if (*q == _T('\0')) { break; } + *p = *q; + } +#endif + p++; + q++; + } + nLen ++; + } + //Always terminate with 2 NULLs. + *p = NULL; + p++; + *p = NULL; + lRes = rkParent.SetMultiStringValue(szValueName, pszDestValue); + } + else + { + lRes = ERROR_OUTOFMEMORY; + } + } + break; + case VT_UI4: + { + ULONG ulVal; + USES_CONVERSION_EX; + + LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); + #ifndef _UNICODE + if(lpszV == NULL) + return E_OUTOFMEMORY; + #endif + VarUI4FromStr(lpszV, 0, 0, &ulVal); + + lRes = rkParent.SetDWORDValue(szValueName, ulVal); + ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %d at %s\n"), ulVal, !szValueName ? _T("default") : szValueName); + break; + } + case VT_UI1: + { + int cbValue = lstrlen(szValue); + if (cbValue & 0x00000001) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries\n")); + return E_FAIL; + } + int cbValDiv2 = cbValue/2; + CTempBuffer rgBinary; + ATLTRY(rgBinary.Allocate(cbValDiv2)); + if (rgBinary == NULL) + return E_FAIL; + memset(rgBinary, 0, cbValDiv2); + for (int irg = 0; irg < cbValue; irg++) + rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x00000001))); + lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbValDiv2); + break; + } + } + + if (ERROR_SUCCESS != lRes) + { + nIDRes = E_ATL_VALUE_SET_FAILED; + return AtlHresultFromWin32(lRes); + } + + if (FAILED(hr = NextToken(szToken))) + return hr; + + return S_OK; +} + +inline BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey) +{ + for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++) + if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel])) + return FALSE; // We cannot delete it + + return TRUE; +} + +inline BOOL CRegParser::HasSubKeys(HKEY hkey) +{ + DWORD cbSubKeys = 0; + + if (RegQueryInfoKey(hkey, NULL, NULL, NULL, + &cbSubKeys, NULL, NULL, + NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Should not be here!!\n")); + ATLASSERT(FALSE); + return FALSE; + } + + return cbSubKeys > 0; +} + +inline BOOL CRegParser::HasValues(HKEY hkey) +{ + DWORD cbValues = 0; + + LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL, + NULL, NULL, NULL, + &cbValues, NULL, NULL, NULL, NULL); + if (ERROR_SUCCESS != lResult) + { + ATLTRACE(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed ")); + ATLASSERT(FALSE); + return FALSE; + } + + if (1 == cbValues) + { + DWORD cbMaxName= MAX_VALUE; + TCHAR szValueName[MAX_VALUE]; + // Check to see if the Value is default or named + lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, NULL); + if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL)) + return TRUE; // Named Value means we have a value + return FALSE; + } + + return cbValues > 0; // More than 1 means we have a non-default value +} + +inline HRESULT CRegParser::SkipAssignment(__inout_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken) +{ + HRESULT hr; + TCHAR szValue[MAX_VALUE]; + + if (*szToken == chEquals) + { + if (FAILED(hr = NextToken(szToken))) + return hr; + // Skip assignment + SkipWhiteSpace(); + if (FAILED(hr = NextToken(szValue))) + return hr; + if (FAILED(hr = NextToken(szToken))) + return hr; + } + + return S_OK; +} + +inline HRESULT CRegParser::PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z LPTSTR* ppszReg) +{ + ATLASSERT(lpszReg != NULL); + ATLASSERT(ppszReg != NULL); + + if (lpszReg == NULL || ppszReg == NULL) + return E_POINTER; + + *ppszReg = NULL; + int nSize = lstrlen(lpszReg)*2; + CParseBuffer pb(nSize); + if (pb.p == NULL) + return E_OUTOFMEMORY; + m_pchCur = lpszReg; + HRESULT hr = S_OK; + + while (*m_pchCur != NULL) // look for end + { + if (*m_pchCur == _T('%')) + { + m_pchCur = CharNext(m_pchCur); + if (*m_pchCur == _T('%')) + { + if (!pb.AddChar(m_pchCur)) + { + hr = E_OUTOFMEMORY; + break; + } + } + else + { + LPTSTR lpszNext = StrChr(m_pchCur, _T('%')); + if (lpszNext == NULL) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Error no closing %% found\n")); + hr = GenerateError(E_ATL_UNEXPECTED_EOS); + break; + } + if ((lpszNext-m_pchCur) > 31) + { + hr = E_FAIL; + break; + } + int nLength = int(lpszNext - m_pchCur); + TCHAR buf[32]; + Checked::tcsncpy_s(buf, _countof(buf), m_pchCur, nLength); + LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf); + if (lpszVar == NULL) + { + hr = GenerateError(E_ATL_NOT_IN_MAP); + break; + } + if (!pb.AddString(lpszVar)) + { + hr = E_OUTOFMEMORY; + break; + } + + while (m_pchCur != lpszNext) + m_pchCur = CharNext(m_pchCur); + } + } + else + { + if (!pb.AddChar(m_pchCur)) + { + hr = E_OUTOFMEMORY; + break; + } + } + + m_pchCur = CharNext(m_pchCur); + } + if (SUCCEEDED(hr)) + *ppszReg = pb.Detach(); + return hr; +} + +inline HRESULT CRegParser::RegisterBuffer(__in_z LPTSTR szBuffer, __in BOOL bRegister) +{ + TCHAR szToken[MAX_VALUE]; + HRESULT hr = S_OK; + + LPTSTR szReg = NULL; + hr = PreProcessBuffer(szBuffer, &szReg); + if (FAILED(hr)) + return hr; + + ATLTRACE(atlTraceRegistrar, 0, _T("%s\n"), szReg); + + m_pchCur = szReg; + + // Preprocess szReg + + while (NULL != *m_pchCur) + { + if (FAILED(hr = NextToken(szToken))) + break; + HKEY hkBase; + if ((hkBase = HKeyFromString(szToken)) == NULL) + { + ATLTRACE(atlTraceRegistrar, 0, _T("HKeyFromString failed on %s\n"), szToken); + hr = GenerateError(E_ATL_BAD_HKEY); + break; + } + + if (FAILED(hr = NextToken(szToken))) + break; + + if (chLeftBracket != *szToken) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s\n"), szToken); + hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN); + break; + } + if (bRegister) + { + LPTSTR szRegAtRegister = m_pchCur; + hr = RegisterSubkeys(szToken, hkBase, bRegister); + if (FAILED(hr)) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Failed to register, cleaning up!\n")); + m_pchCur = szRegAtRegister; + RegisterSubkeys(szToken, hkBase, FALSE); + break; + } + } + else + { + if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister))) + break; + } + + SkipWhiteSpace(); + } + CoTaskMemFree(szReg); + return hr; +} + +inline HRESULT CRegParser::RegisterSubkeys(__out_ecount_z(MAX_VALUE_VALUE) LPTSTR szToken, __in HKEY hkParent, __in BOOL bRegister, __in BOOL bRecover) +{ + CRegKey keyCur; + LONG lRes; + TCHAR szKey[_MAX_PATH]; + BOOL bDelete = TRUE; + BOOL bInRecovery = bRecover; + HRESULT hr = S_OK; + + ATLTRACE(atlTraceRegistrar, 2, _T("Num Els = %d\n"), cbNeverDelete); + if (FAILED(hr = NextToken(szToken))) + return hr; + + + while (*szToken != chRightBracket) // Continue till we see a } + { + + + bDelete = TRUE; + BOOL bTokenDelete = !lstrcmpi(szToken, szDelete); + + if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete) + { + if (FAILED(hr = NextToken(szToken))) + break; + + if (bRegister) + { + CRegKey rkForceRemove; + + if (StrChr(szToken, chDirSep) != NULL) + return GenerateError(E_ATL_COMPOUND_KEY); + + if (CanForceRemoveKey(szToken)) + { + rkForceRemove.Attach(hkParent); + // Error not returned. We will overwrite the values any way. + rkForceRemove.RecurseDeleteKey(szToken); + rkForceRemove.Detach(); + } + if (bTokenDelete) + { + if (FAILED(hr = NextToken(szToken))) + break; + if (FAILED(hr = SkipAssignment(szToken))) + break; + goto EndCheck; + } + } + + } + + if (!lstrcmpi(szToken, szNoRemove)) + { + bDelete = FALSE; // set even for register + if (FAILED(hr = NextToken(szToken))) + break; + } + + if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent + { + TCHAR szValueName[MAX_VALUE]; + + if (FAILED(hr = NextToken(szValueName))) + break; + if (FAILED(hr = NextToken(szToken))) + break; + + if (*szToken != chEquals) + return GenerateError(E_ATL_EXPECTING_EQUAL); + + if (bRegister) + { + CRegKey rk; + + rk.Attach(hkParent); + hr = AddValue(rk, szValueName, szToken); + rk.Detach(); + + if (FAILED(hr)) + return hr; + + goto EndCheck; + } + else + { + if (!bRecover && bDelete) + { + ATLTRACE(atlTraceRegistrar, 1, _T("Deleting %s\n"), szValueName); + // We have to open the key for write to be able to delete. + CRegKey rkParent; + lRes = rkParent.Open(hkParent, NULL, KEY_WRITE); + if (lRes == ERROR_SUCCESS) + { + lRes = rkParent.DeleteValue(szValueName); + if (lRes != ERROR_SUCCESS && lRes != ERROR_FILE_NOT_FOUND) + { + // Key not present is not an error + hr = AtlHresultFromWin32(lRes); + break; + } + } + else + { + hr = AtlHresultFromWin32(lRes); + break; + } + } + if (FAILED(hr = SkipAssignment(szToken))) + break; + continue; // can never have a subkey + } + } + + if (StrChr(szToken, chDirSep) != NULL) + return GenerateError(E_ATL_COMPOUND_KEY); + + if (bRegister) + { + lRes = keyCur.Open(hkParent, szToken, KEY_READ | KEY_WRITE); + if (ERROR_SUCCESS != lRes) + { + // Failed all access try read only + lRes = keyCur.Open(hkParent, szToken, KEY_READ); + if (ERROR_SUCCESS != lRes) + { + // Finally try creating it + ATLTRACE(atlTraceRegistrar, 2, _T("Creating key %s\n"), szToken); + lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + } + } + + if (FAILED(hr = NextToken(szToken))) + break; + + + if (*szToken == chEquals) + { + if (FAILED(hr = AddValue(keyCur, NULL, szToken))) // NULL == default + break; + } + } + else //Unregister + { + if (!bRecover) + { + lRes = keyCur.Open(hkParent, szToken, KEY_READ); + + } + else + lRes = ERROR_FILE_NOT_FOUND; + + + // Open failed set recovery mode + if (lRes != ERROR_SUCCESS) + bRecover = true; + + // TRACE out Key open status and if in recovery mode +#ifdef _DEBUG + if (!bRecover) + ATLTRACE(atlTraceRegistrar, 1, _T("Opened Key %s\n"), szToken); + else + ATLTRACE(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery mode\n"), szToken); +#endif //_DEBUG + + // Remember Subkey + Checked::tcsncpy_s(szKey, _countof(szKey), szToken, _TRUNCATE); + + if (FAILED(hr = NextToken(szToken))) + break; + if (FAILED(hr = SkipAssignment(szToken))) + break; + + if (*szToken == chLeftBracket && lstrlen(szToken) == 1) + { + hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover); + // In recover mode ignore error + if (FAILED(hr) && !bRecover) + break; + // Skip the } + if (FAILED(hr = NextToken(szToken))) + break; + } + +#ifdef _DEBUG + if (bRecover != bInRecovery) + ATLTRACE(atlTraceRegistrar, 0, _T("Ending Recovery Mode\n")); +#endif + bRecover = bInRecovery; + + if (lRes == ERROR_FILE_NOT_FOUND) + // Key already not present so not an error. + continue; + + if (lRes != ERROR_SUCCESS) + { + // We are recovery mode continue on errors else break + if (bRecover) + continue; + else + { + hr = AtlHresultFromWin32(lRes); + break; + } + } + + // If in recovery mode + if (bRecover && HasSubKeys(keyCur)) + { + // See if the KEY is in the NeverDelete list and if so, don't + if (CanForceRemoveKey(szKey) && bDelete) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by force\n"), szKey); + // Error not returned since we are in recovery mode. The error that caused recovery mode is returned + keyCur.RecurseDeleteKey(szKey); + } + continue; + } + + BOOL bHasSubKeys=HasSubKeys(keyCur); + lRes = keyCur.Close(); + if (lRes != ERROR_SUCCESS) + return AtlHresultFromWin32(lRes); + + if (bDelete&& !bHasSubKeys) + { + ATLTRACE(atlTraceRegistrar, 0, _T("Deleting Key %s\n"), szKey); + CRegKey rkParent; + rkParent.Attach(hkParent); + lRes = rkParent.DeleteSubKey(szKey); + rkParent.Detach(); + if (lRes != ERROR_SUCCESS) + { + + hr = AtlHresultFromWin32(lRes); + break; + } + } + + + + + } + +EndCheck: + + if (bRegister) + { + if (*szToken == chLeftBracket && lstrlen(szToken) == 1) + { + if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE))) + break; + if (FAILED(hr = NextToken(szToken))) + break; + } + } + } + + return hr; +} + +}; //namespace ATL + +#pragma pack(pop) +#pragma warning(pop) + +#endif //__STATREG_H__ + diff --git a/c/jacob/lib/atls.lib b/c/jacob/lib/atls.lib new file mode 100644 index 0000000..48cd9c0 Binary files /dev/null and b/c/jacob/lib/atls.lib differ diff --git a/c/jacob/msvc/copy.bat b/c/jacob/msvc/copy.bat new file mode 100644 index 0000000..b10047c --- /dev/null +++ b/c/jacob/msvc/copy.bat @@ -0,0 +1 @@ +copy Release\jacob.dll ..\..\..\java\native\ \ No newline at end of file diff --git a/c/jacob/msvc/jacob.sln b/c/jacob/msvc/jacob.sln new file mode 100644 index 0000000..50ae3e2 --- /dev/null +++ b/c/jacob/msvc/jacob.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual C++ Express 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jacob", "jacob.vcxproj", "{745CA8EA-176E-46A7-B2A5-55260DF5639B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {745CA8EA-176E-46A7-B2A5-55260DF5639B}.Debug|Win32.ActiveCfg = Debug|Win32 + {745CA8EA-176E-46A7-B2A5-55260DF5639B}.Debug|Win32.Build.0 = Debug|Win32 + {745CA8EA-176E-46A7-B2A5-55260DF5639B}.Release|Win32.ActiveCfg = Release|Win32 + {745CA8EA-176E-46A7-B2A5-55260DF5639B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/c/jacob/msvc/jacob.suo b/c/jacob/msvc/jacob.suo new file mode 100644 index 0000000..706c50c Binary files /dev/null and b/c/jacob/msvc/jacob.suo differ diff --git a/c/jacob/msvc/jacob.vcxproj b/c/jacob/msvc/jacob.vcxproj new file mode 100644 index 0000000..8c3a22c --- /dev/null +++ b/c/jacob/msvc/jacob.vcxproj @@ -0,0 +1,105 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {745CA8EA-176E-46A7-B2A5-55260DF5639B} + Win32Proj + jacob + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + true + + + false + ..\include;C:\Program Files %28x86%29\Java\jdk1.6.0_23\include;C:\Program Files %28x86%29\Java\jdk1.6.0_23\include\win32;$(IncludePath) + ..\lib;$(LibraryPath) + + + + NotUsing + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;JACOB_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + + + + + Level3 + NotUsing + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;JACOB_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/c/jacob/msvc/jacob.vcxproj.filters b/c/jacob/msvc/jacob.vcxproj.filters new file mode 100644 index 0000000..5729cab --- /dev/null +++ b/c/jacob/msvc/jacob.vcxproj.filters @@ -0,0 +1,87 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/c/jacob/msvc/jacob.vcxproj.user b/c/jacob/msvc/jacob.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/c/jacob/msvc/jacob.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/c/jacob/util.cpp b/c/jacob/util.cpp new file mode 100644 index 0000000..b0f6c19 --- /dev/null +++ b/c/jacob/util.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "Dispatch.h" +// Win32 support for Ole Automation +#include +#include +#include +#include +#include +#include +#include "util.h" + +extern "C" +{ + +void ThrowComFail(JNIEnv *env, const char* desc, jint hr) +{ + jclass failClass = env->FindClass("com/jacob/com/ComFailException"); + // call the constructor that takes hr and message + jmethodID failCons = + env->GetMethodID(failClass, "", "(ILjava/lang/String;)V"); + if (!desc) { + desc = "Java/COM Error"; + } + jstring js = env->NewStringUTF(desc); + jthrowable fail = (jthrowable)env->NewObject(failClass, failCons, hr, js); + env->Throw(fail); +} + +void ThrowComFailUnicode(JNIEnv *env, const wchar_t* desc, jint hr) +{ + if (!desc) { + ThrowComFail(env, "Java/COM Error", hr); + } + jclass failClass = env->FindClass("com/jacob/com/ComFailException"); + // call the constructor that takes hr and message + jmethodID failCons = + env->GetMethodID(failClass, "", "(ILjava/lang/String;)V"); + jstring js = env->NewString((const jchar *) desc, wcslen(desc)); + jthrowable fail = (jthrowable)env->NewObject(failClass, failCons, hr, js); + env->Throw(fail); +} + +// if env's are different throw on the 1st env +int CheckEnv(JNIEnv *env1, JNIEnv *env2) +{ + if (env1 != env2) { + jclass failClass = env1->FindClass("com/jacob/com/WrongThreadException"); + // call the constructor that takes hr and message + jmethodID failCons = + env1->GetMethodID(failClass, "", "()V"); + env1->ThrowNew(failClass, "Wrong Thread"); + return 0; + } + return 1; +} + +} diff --git a/c/jacob/util.h b/c/jacob/util.h new file mode 100644 index 0000000..5835154 --- /dev/null +++ b/c/jacob/util.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include +extern "C" { + VARIANT *extractVariant(JNIEnv *env, jobject arg); + void ThrowComFail(JNIEnv *env, const char* desc, jint hr); + void ThrowComFailUnicode(JNIEnv *env, const wchar_t* desc, jint hr); + IDispatch *extractDispatch(JNIEnv *env, jobject arg); + SAFEARRAY *extractSA(JNIEnv *env, jobject arg); + void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy); + SAFEARRAY *copySA(SAFEARRAY *psa); +} diff --git a/java/src/com/jacob/activeX/ActiveXComponent.java b/java/src/com/jacob/activeX/ActiveXComponent.java new file mode 100644 index 0000000..0f15e54 --- /dev/null +++ b/java/src/com/jacob/activeX/ActiveXComponent.java @@ -0,0 +1,479 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.activeX; + +import com.jacob.com.Dispatch; +import com.jacob.com.JacobObject; +import com.jacob.com.Variant; + +/** + * This class provides a higher level, more object like, wrapper for top of the + * Dispatch object. The Dispatch class's method essentially directly map to + * Microsoft C API including the first parameter that is almost always the + * target of the message. ActiveXComponent assumes the target of every message + * is the MS COM object behind the ActiveXComponent. This removes the need to + * pass the Dispatch object into every method. + *

+ * It is really up to the developer as to whether they want to use the Dispatch + * interface or the ActiveXComponent interface. + *

+ * This class simulates com.ms.activeX.ActiveXComponent only in the sense that + * it is used for creating Dispatch objects + */ +public class ActiveXComponent extends Dispatch { + + /** + * Normally used to create a new connection to a microsoft application. The + * passed in parameter is the name of the program as registered in the + * registry. It can also be the object name. + *

+ * This constructor causes a new Windows object of the requested type to be + * created. The windows CoCreate() function gets called to create the + * underlying windows object. + * + *

+	 * new ActiveXComponent("ScriptControl");
+	 * 
+ * + * @param programId + */ + public ActiveXComponent(String programId) { + super(programId); + } + + /** + * Creates an active X component that is built on top of the COM pointers + * held in the passed in dispatch. This widens the Dispatch object to pick + * up the ActiveXComponent API + * + * @param dispatchToBeWrapped + */ + public ActiveXComponent(Dispatch dispatchToBeWrapped) { + super(dispatchToBeWrapped); + } + + /** + * only used by the factories + * + */ + private ActiveXComponent() { + super(); + } + + /** + * Probably was a cover for something else in the past. Should be + * deprecated. + * + * @return Now it actually returns this exact same object. + */ + public Dispatch getObject() { + return this; + } + + /** + * Most code should use the standard ActiveXComponent(String) contructor and + * not this factory method. This method exists for applications that need + * special behavior. Experimental in release 1.9.2. + *

+ * Factory that returns a Dispatch object wrapped around the result of a + * CoCreate() call. This differs from the standard constructor in that it + * throws no exceptions and returns null on failure. + *

+ * This will fail for any prog id with a ":" in it. + * + * @param pRequestedProgramId + * @return Dispatch pointer to the COM object or null if couldn't create + */ + public static ActiveXComponent createNewInstance(String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.coCreateInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to co-create instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } + + /** + * Most code should use the standard ActiveXComponent(String) constructor + * and not this factory method. This method exists for applications that + * need special behavior. Experimental in release 1.9.2. + *

+ * Factory that returns a Dispatch wrapped around the result of a + * getActiveObject() call. This differs from the standard constructor in + * that it throws no exceptions and returns null on failure. + *

+ * This will fail for any prog id with a ":" in it + * + * @param pRequestedProgramId + * @return Dispatch pointer to a COM object or null if wasn't already + * running + */ + public static ActiveXComponent connectToActiveInstance( + String pRequestedProgramId) { + ActiveXComponent mCreatedDispatch = null; + try { + mCreatedDispatch = new ActiveXComponent(); + mCreatedDispatch.getActiveInstance(pRequestedProgramId); + } catch (Exception e) { + mCreatedDispatch = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Unable to attach to running instance of " + + pRequestedProgramId); + } + } + return mCreatedDispatch; + } + + /** + * @see com.jacob.com.Dispatch#finalize() + */ + @Override + protected void finalize() { + super.finalize(); + } + + /* + * ============================================================ + * + * start of instance based calls to the COM layer + * =========================================================== + */ + + /** + * retrieves a property and returns it as a Variant + * + * @param propertyName + * @return variant value of property + */ + public Variant getProperty(String propertyName) { + return Dispatch.get(this, propertyName); + } + + /** + * retrieves a property and returns it as an ActiveX component + * + * @param propertyName + * @return Dispatch representing the object under the property name + */ + public ActiveXComponent getPropertyAsComponent(String propertyName) { + return new ActiveXComponent(Dispatch.get(this, propertyName) + .toDispatch()); + + } + + /** + * retrieves a property and returns it as a Boolean + * + * @param propertyName + * property we are looking up + * @return boolean value of property + */ + public boolean getPropertyAsBoolean(String propertyName) { + return Dispatch.get(this, propertyName).getBoolean(); + } + + /** + * retrieves a property and returns it as a byte + * + * @param propertyName + * property we are looking up + * @return byte value of property + */ + public byte getPropertyAsByte(String propertyName) { + return Dispatch.get(this, propertyName).getByte(); + } + + /** + * retrieves a property and returns it as a String + * + * @param propertyName + * @return String value of property + */ + public String getPropertyAsString(String propertyName) { + return Dispatch.get(this, propertyName).getString(); + + } + + /** + * retrieves a property and returns it as a int + * + * @param propertyName + * @return the property value as an int + */ + public int getPropertyAsInt(String propertyName) { + return Dispatch.get(this, propertyName).getInt(); + } + + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Variant arg) { + Dispatch.put(this, propertyName, arg); + } + + /** + * sets a property on this object + * + * @param propertyName + * property name + * @param arg + * variant value to be set + */ + public void setProperty(String propertyName, Dispatch arg) { + Dispatch.put(this, propertyName, arg); + } + + /** + * sets a property to be the value of the string + * + * @param propertyName + * @param propertyValue + */ + public void setProperty(String propertyName, String propertyValue) { + this.setProperty(propertyName, new Variant(propertyValue)); + } + + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, boolean propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /** + * sets a property as a boolean value + * + * @param propertyName + * @param propValue + * the boolean value we want the prop set to + */ + public void setProperty(String propertyName, byte propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /** + * sets the property as an int value + * + * @param propertyName + * @param propValue + * the int value we want the prop to be set to. + */ + public void setProperty(String propertyName, int propValue) { + this.setProperty(propertyName, new Variant(propValue)); + } + + /*------------------------------------------------------- + * Listener logging helpers + *------------------------------------------------------- + */ + + /** + * This boolean determines if callback events should be logged + */ + public static boolean shouldLogEvents = false; + + /** + * used by the doc and application listeners to get intelligent logging + * + * @param description + * event description + * @param args + * args passed in (variants) + * + */ + public void logCallbackEvent(String description, Variant[] args) { + String argString = ""; + if (args != null && ActiveXComponent.shouldLogEvents) { + if (args.length > 0) { + argString += " args: "; + } + for (int i = 0; i < args.length; i++) { + short argType = args[i].getvt(); + argString += ",[" + i + "]"; + // break out the byref bits if they are on this + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // show the type and the fact that its byref + argString += "(" + + (args[i].getvt() & ~Variant.VariantByref) + "/" + + Variant.VariantByref + ")"; + } else { + // show the type + argString += "(" + argType + ")"; + } + argString += "="; + if (argType == Variant.VariantDispatch) { + Dispatch foo = (args[i].getDispatch()); + argString += foo; + } else if ((argType & Variant.VariantBoolean) == Variant.VariantBoolean) { + // do the boolean thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // boolean by ref + argString += args[i].getBooleanRef(); + } else { + // boolean by value + argString += args[i].getBoolean(); + } + } else if ((argType & Variant.VariantString) == Variant.VariantString) { + // do the string thing + if ((argType & Variant.VariantByref) == Variant.VariantByref) { + // string by ref + argString += args[i].getStringRef(); + } else { + // string by value + argString += args[i].getString(); + } + } else { + argString += args[i].toString(); + } + } + System.out.println(description + argString); + } + } + + /* + * ============================================================== + * + * covers for dispatch call methods + * ============================================================= + */ + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction) { + return new ActiveXComponent(invoke(callAction).toDispatch()); + } + + /** + * makes a dispatch call for the passed in action and single parameter + * + * @param callAction + * @param parameters + * @return ActiveXComponent representing the results of the call + */ + public ActiveXComponent invokeGetComponent(String callAction, + Variant... parameters) { + return new ActiveXComponent(invoke(callAction, parameters).toDispatch()); + } + + /** + * invokes a single parameter call on this dispatch that returns no value + * + * @param actionCommand + * @param parameter + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, String parameter) { + return Dispatch.call(this, actionCommand, parameter); + } + + /** + * makes a dispatch call to the passed in action with a single boolean + * parameter + * + * @param actionCommand + * @param parameter + * @return Variant result + */ + public Variant invoke(String actionCommand, boolean parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a single int parameter + * + * @param actionCommand + * @param parameter + * @return Variant result of the invoke (Dispatch.call) + */ + public Variant invoke(String actionCommand, int parameter) { + return Dispatch.call(this, actionCommand, new Variant(parameter)); + } + + /** + * makes a dispatch call to the passed in action with a string and integer + * parameter (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return Variant result + */ + public Variant invoke(String actionCommand, String parameter1, + int parameter2) { + return Dispatch.call(this, actionCommand, parameter1, new Variant( + parameter2)); + } + + /** + * makes a dispatch call to the passed in action with two integer parameters + * (this was put in for some application) + * + * @param actionCommand + * @param parameter1 + * @param parameter2 + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String actionCommand, int parameter1, int parameter2) { + return Dispatch.call(this, actionCommand, new Variant(parameter1), + new Variant(parameter2)); + } + + /** + * makes a dispatch call for the passed in action and no parameter + * + * @param callAction + * @return a Variant but that may be null for some calls + */ + public Variant invoke(String callAction) { + return Dispatch.call(this, callAction); + } + + /** + * This is really a cover for call(String,Variant[]) that should be + * eliminated call with a variable number of args mainly used for quit. + * + * @param name + * @param args + * @return Variant returned by the invoke (Dispatch.callN) + */ + public Variant invoke(String name, Variant... args) { + return Dispatch.callN(this, name, args); + } + +} \ No newline at end of file diff --git a/java/src/com/jacob/activeX/ActiveXDispatchEvents.java b/java/src/com/jacob/activeX/ActiveXDispatchEvents.java new file mode 100644 index 0000000..ab6ee2c --- /dev/null +++ b/java/src/com/jacob/activeX/ActiveXDispatchEvents.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.activeX; + +import com.jacob.com.Dispatch; +import com.jacob.com.DispatchEvents; +import com.jacob.com.InvocationProxy; + +/** + * RELEASE 1.12 EXPERIMENTAL. + *

+ * Use this exactly like the DispatchEvents class. This class plugs in an + * ActiveXInvocationProxy instead of an InvocationProxy. It is the + * ActiveXInvocationProxy that implements the reflection calls and invoke the + * found java event callbacks. See ActiveXInvocationProxy for details. + * + * + */ +public class ActiveXDispatchEvents extends DispatchEvents { + + /** + * This is the most commonly used constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink) { + super(sourceOfEvent, eventSink, null); + } + + /** + * None of the samples use this constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId + * ??? + */ + public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId) { + super(sourceOfEvent, eventSink, progId, null); + } + + /** + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + * + *

+	 * >ActiveXDispatchEvents de = 
+	 * 			new ActiveXDispatchEvents(someDispatch,someEventHAndler,
+	 * 				"Excel.Application",
+	 * 				"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
+	 * 
+	 * @param sourceOfEvent Dispatch object who's MS app will generate callbacks
+	 * @param eventSink Java object that wants to receive the events
+	 * @param progId , mandatory if the typelib is specified
+	 * @param typeLib The location of the typelib to use
+	 * 
+	 */
+	public ActiveXDispatchEvents(Dispatch sourceOfEvent, Object eventSink,
+			String progId, String typeLib) {
+		super(sourceOfEvent, eventSink, progId, typeLib);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see com.jacob.com.DispatchEvents#getInvocationProxy(java.lang.Object)
+	 */
+	protected InvocationProxy getInvocationProxy(Object pTargetObject) {
+		InvocationProxy newProxy = new ActiveXInvocationProxy();
+		newProxy.setTarget(pTargetObject);
+		return newProxy;
+	}
+
+}
diff --git a/java/src/com/jacob/activeX/ActiveXInvocationProxy.java b/java/src/com/jacob/activeX/ActiveXInvocationProxy.java
new file mode 100644
index 0000000..a06f8ba
--- /dev/null
+++ b/java/src/com/jacob/activeX/ActiveXInvocationProxy.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 1999-2004 Sourceforge JACOB Project.
+ * All rights reserved. Originator: Dan Adler (http://danadler.com).
+ * Get more information about JACOB at http://sourceforge.net/projects/jacob-project
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+package com.jacob.activeX;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import com.jacob.com.InvocationProxy;
+import com.jacob.com.NotImplementedException;
+import com.jacob.com.Variant;
+
+/**
+ * RELEASE 1.12 EXPERIMENTAL.
+ * 

+ * This class that lets event handlers receive events with all java objects as + * parameters. The standard Jacob event methods all accept an array of Variant + * objects. When using this class, you can set up your event methods as regular + * java methods with the correct number of parameters of the correct java type. + * This does NOT work for any event that wishes to accept a call back and modify + * the calling parameters to tell windows what to do. An example is when an + * event lets the receiver cancel the action by setting a boolean flag to false. + * The java objects cannot be modified and their values will not be passed back + * into the originating Variants even if they could be modified. + *

+ * This class acts as a proxy between the windows event callback mechanism and + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods native java objects of + * the type and order that match the windows documentation. The methods can + * return void or a Variant that will be returned to the calling layer. All + * Event methods that will be recognized by InvocationProxyAllEvents have the + * signature + * + * void eventMethodName(Object,Object...) or + * Object eventMethodName(Object,Object...) + */ +public class ActiveXInvocationProxy extends InvocationProxy { + + /* + * (non-Javadoc) + * + * @see com.jacob.com.InvocationProxy#invoke(java.lang.String, + * com.jacob.com.Variant[]) + */ + @SuppressWarnings("unchecked") + public Variant invoke(String methodName, Variant targetParameters[]) { + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + // structured programming guidlines say this return should not be up + // here + return null; + } + Class targetClass = mTargetObject.getClass(); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); + } + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); + } + try { + Method targetMethod; + Object parametersAsJavaObjects[] = getParametersAsJavaObjects(targetParameters); + Class parametersAsJavaClasses[] = getParametersAsJavaClasses(parametersAsJavaObjects); + targetMethod = targetClass.getMethod(methodName, + parametersAsJavaClasses); + if (targetMethod != null) { + // protected classes can't be invoked against even if they + // let you grab the method. you could do + // targetMethod.setAccessible(true); + // but that should be stopped by the security manager + Object mReturnedByInvocation = null; + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + parametersAsJavaObjects); + if (mReturnedByInvocation == null) { + mVariantToBeReturned = null; + } else if (!(mReturnedByInvocation instanceof Variant)) { + mVariantToBeReturned = new Variant(mReturnedByInvocation); + } else { + mVariantToBeReturned = (Variant) mReturnedByInvocation; + } + } + } catch (SecurityException e) { + // what causes this exception? + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // this happens whenever the listener doesn't implement all the + // methods + } catch (IllegalArgumentException e) { + // we can throw these inside the catch block so need to re-throw it + Exception oneWeShouldToss = new IllegalArgumentException( + "Unable to map parameters for method " + methodName + ": " + + e.toString()); + oneWeShouldToss.printStackTrace(); + } catch (IllegalAccessException e) { + // can't access the method on the target instance for some reason + e.printStackTrace(); + } catch (InvocationTargetException e) { + // invocation of target method failed + e.printStackTrace(); + } + return mVariantToBeReturned; + + } + + /** + * creates a method signature compatible array of classes from an array of + * parameters + * + * @param parametersAsJavaObjects + * @return + */ + @SuppressWarnings("unchecked") + private Class[] getParametersAsJavaClasses(Object[] parametersAsJavaObjects) { + if (parametersAsJavaObjects == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); + } + int numParameters = parametersAsJavaObjects.length; + Class parametersAsJavaClasses[] = new Class[numParameters]; + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { + Object oneParameterObject = parametersAsJavaObjects[parameterIndex]; + if (oneParameterObject == null) { + parametersAsJavaClasses[parameterIndex] = null; + } else { + Class oneParameterClass = oneParameterObject.getClass(); + parametersAsJavaClasses[parameterIndex] = oneParameterClass; + } + } + return parametersAsJavaClasses; + } + + /** + * converts an array of Variants to their associated Java types + * + * @param targetParameters + * @return + */ + private Object[] getParametersAsJavaObjects(Variant[] targetParameters) { + if (targetParameters == null) { + throw new IllegalArgumentException( + "This only works with an array of parameters"); + } + int numParameters = targetParameters.length; + Object parametersAsJavaObjects[] = new Object[numParameters]; + for (int parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { + Variant oneParameterObject = targetParameters[parameterIndex]; + if (oneParameterObject == null) { + parametersAsJavaObjects[parameterIndex] = null; + } else { + try { + parametersAsJavaObjects[parameterIndex] = oneParameterObject + .toJavaObject(); + } catch (NotImplementedException nie) { + throw new IllegalArgumentException( + "Can't convert parameter " + parameterIndex + + " type " + oneParameterObject.getvt() + + " to java object: " + nie.getMessage()); + } + } + } + return parametersAsJavaObjects; + } + +} diff --git a/java/src/com/jacob/com/ComException.java b/java/src/com/jacob/com/ComException.java new file mode 100644 index 0000000..5daad70 --- /dev/null +++ b/java/src/com/jacob/com/ComException.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Standard exception thrown by com jni code when there is a problem + */ +public abstract class ComException extends JacobException { + + /** + * COM code initializes this filed with an appropriate return code that was + * returned by the underlying com code + */ + protected int hr; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected int m_helpContext; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected String m_helpFile; + /** + * No documentation is available at this time. Someone should document this + * field + */ + protected String m_source; + + /** + * constructor + * + */ + public ComException() { + super(); + } + + /** + * constructor with error code? + * + * @param newHr ?? + */ + public ComException(int newHr) { + super(); + this.hr = newHr; + } + + /** + * @param newHr + * @param description + */ + public ComException(int newHr, String description) { + super(description); + this.hr = newHr; + } + + /** + * @param newHr + * @param source + * @param helpFile + * @param helpContext + */ + public ComException(int newHr, String source, String helpFile, + int helpContext) { + super(); + this.hr = newHr; + m_source = source; + m_helpFile = helpFile; + m_helpContext = helpContext; + } + + /** + * @param newHr + * @param description + * @param source + * @param helpFile + * @param helpContext + */ + public ComException(int newHr, String description, String source, + String helpFile, int helpContext) { + super(description); + this.hr = newHr; + m_source = source; + m_helpFile = helpFile; + m_helpContext = helpContext; + } + + /** + * @param description + */ + public ComException(String description) { + super(description); + } + + /** + * @return int representation of the help context + */ + // Methods + public int getHelpContext() { + return m_helpContext; + } + + /** + * @return String ??? help file + */ + public String getHelpFile() { + return m_helpFile; + } + + /** + * @return int hr result ?? + */ + public int getHResult() { + return hr; + } + + /** + * @return String source ?? + */ + public String getSource() { + return m_source; + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/ComFailException.java b/java/src/com/jacob/com/ComFailException.java new file mode 100644 index 0000000..a2a8aff --- /dev/null +++ b/java/src/com/jacob/com/ComFailException.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * COM Fail Exception class raised when there is a problem + */ +public class ComFailException extends ComException { + /** + * eclipse generated to get rid of a wanring + */ + private static final long serialVersionUID = -266047261992987700L; + + /** + * Constructor + * + * @param hrNew + */ + public ComFailException(int hrNew) { + super(hrNew); + } + + /** + * Constructor + * + * @param hrNew + * @param message + */ + public ComFailException(int hrNew, String message) { + super(hrNew, message); + } + + /** + * @param hrNew + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String source, String helpFile, + int helpContext) { + super(hrNew, source, helpFile, helpContext); + } + + /** + * Constructor + * + * @param hrNew + * @param description + * @param source + * @param helpFile + * @param helpContext + */ + public ComFailException(int hrNew, String description, String source, + String helpFile, int helpContext) { + super(hrNew, description, source, helpFile, helpContext); + } + + /** + * No argument Constructor + */ + public ComFailException() { + super(); + } + + /** + * @param message + */ + public ComFailException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/ComThread.java b/java/src/com/jacob/com/ComThread.java new file mode 100644 index 0000000..096a62a --- /dev/null +++ b/java/src/com/jacob/com/ComThread.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Represents a COM level thread This is an abstract class because all the + * methods are static and no instances are ever created. + */ +public abstract class ComThread { + private static final int MTA = 0x0; + + private static final int STA = 0x2; + + /** + * Comment for haveSTA + */ + public static boolean haveSTA = false; + + /** + * Comment for mainSTA + */ + public static MainSTA mainSTA = null; + + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment + */ + public static synchronized void InitMTA() { + InitMTA(false); + } + + /** + * Initialize the current java thread to be an STA + */ + public static synchronized void InitSTA() { + InitSTA(false); + } + + /** + * Initialize the current java thread to be part of the Multi-threaded COM + * Apartment, if createMainSTA is true, create a separate MainSTA thread + * that will house all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitMTA(boolean createMainSTA) { + Init(createMainSTA, MTA); + } + + /** + * Initialize the current java thread to be an STA COM Apartment, if + * createMainSTA is true, create a separate MainSTA thread that will house + * all Apartment Threaded components + * + * @param createMainSTA + */ + public static synchronized void InitSTA(boolean createMainSTA) { + Init(createMainSTA, STA); + } + + /** + * + */ + public static synchronized void startMainSTA() { + mainSTA = new MainSTA(); + haveSTA = true; + } + + /** + * + */ + public static synchronized void quitMainSTA() { + if (mainSTA != null) + mainSTA.quit(); + } + + /** + * Initialize the current java thread to be part of the MTA/STA COM + * Apartment + * + * @param createMainSTA + * @param mode + */ + public static synchronized void Init(boolean createMainSTA, int mode) { + if (createMainSTA && !haveSTA) { + // if the current thread is going to be in the MTA and there + // is no STA thread yet, then create a main STA thread + // to avoid COM creating its own + startMainSTA(); + } + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before Init: " + mode); + } + doCoInitialize(mode); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after Init: " + mode); + } + ROT.addThread(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after ROT.addThread: " + mode); + } + } + + /** + * Call CoUninitialize to release this java thread from COM + */ + public static synchronized void Release() { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before clearObjects"); + } + ROT.clearObjects(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: before UnInit"); + } + doCoUninitialize(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ComThread: after UnInit"); + } + } + + /** + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * should not require that the user specifically remove object + * from the thread. + * + * This will remove an object from the ROT + * @param o + */ + @Deprecated + public static synchronized void RemoveObject(JacobObject o) { + ROT.removeObject(o); + } + + /** + * @param threadModel + */ + public static native void doCoInitialize(int threadModel); + + /** + * + */ + public static native void doCoUninitialize(); + + /** + * load the Jacob DLL. We do this in case COMThread is called before any + * other reference to one of the JacboObject subclasses is made. + */ + static { + LibraryLoader.loadJacobLibrary(); + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/Currency.java b/java/src/com/jacob/com/Currency.java new file mode 100644 index 0000000..d7aeef4 --- /dev/null +++ b/java/src/com/jacob/com/Currency.java @@ -0,0 +1,91 @@ +package com.jacob.com; + +/** + * Most COM bridges use java.lang.Long as their Java data type for COM Currency + * data. This is because COM currency is a 64 bit number where the last 4 digits + * represent the milli-cents. We wanted to support 64 bit Long values for x64 + * platforms so that meant we wanted to map Java.LONG to COM.LONG even though it + * only works for 64 bit platforms. The end result was we needed a new + * representation for Money so we have this. + *

+ * In the future, this should convert to and from BigDecimal or Double + */ +public class Currency { + Long embeddedValue = null; + + /** + * constructor that takes a long already in COM representation + * + * @param newValue + */ + public Currency(long newValue) { + embeddedValue = new Long(newValue); + } + + /** + * constructor that takes a String already in COM representation + * + * @param newValue + */ + public Currency(String newValue) { + embeddedValue = new Long(newValue); + } + + /** + * + * @return the currency as a primitive long + */ + public long longValue() { + return embeddedValue.longValue(); + } + + /** + * getter to the inner storage so that cmpareTo can work + * + * @return the embedded long value + */ + protected Long getLongValue() { + return embeddedValue; + } + + /** + * compares the values of two currencies + * + * @param anotherCurrency + * @return the usual compareTo results + */ + public int compareTo(Currency anotherCurrency) { + return embeddedValue.compareTo(anotherCurrency.getLongValue()); + } + + /** + * standard comparison + * + * @param o + * must be Currency or Long + * @return the usual compareTo results + */ + public int compareTo(Object o) { + if (o instanceof Currency) { + return compareTo((Currency) o); + } else if (o instanceof Long) { + return embeddedValue.compareTo((Long) o); + } else + throw new IllegalArgumentException( + "Can only compare to Long and Currency not " + + o.getClass().getName()); + } + + /** + * {@inheritDoc} + */ + public boolean equals(Object o) { + if (o == null) { + return false; + } else if (compareTo(o) == 0) { + return true; + } else { + return false; + } + } +} diff --git a/java/src/com/jacob/com/DateUtilities.java b/java/src/com/jacob/com/DateUtilities.java new file mode 100644 index 0000000..5f8bf5e --- /dev/null +++ b/java/src/com/jacob/com/DateUtilities.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.Calendar; +import java.util.Date; + +/** + * java / windows date conversion utilities + * + * @author joe + * + */ +public class DateUtilities { + + /** + * converts a windows time to a Java Date Object + * + * @param comTime + * @return Date object representing the windows time as specified in comTime + */ + static public Date convertWindowsTimeToDate(double comTime) { + return new Date(convertWindowsTimeToMilliseconds(comTime)); + } + + /** + * Convert a COM time from functions Date(), Time(), Now() to a Java time + * (milliseconds). Visual Basic time values are based to 30.12.1899, Java + * time values are based to 1.1.1970 (= 0 milliseconds). The difference is + * added to the Visual Basic value to get the corresponding Java value. The + * Visual Basic double value reads: .<1 + * day percentage fraction>, e.g. "38100.6453" means: 38100 days since + * 30.12.1899 plus (24 hours * 0.6453). Example usage: + * Date javaDate = new Date(toMilliseconds (vbDate));. + * + * @param comTime + * COM time. + * @return Java time. + */ + static public long convertWindowsTimeToMilliseconds(double comTime) { + long result = 0; + + // code from jacobgen: + comTime = comTime - 25569D; + Calendar cal = Calendar.getInstance(); + result = Math.round(86400000L * comTime) + - cal.get(Calendar.ZONE_OFFSET); + cal.setTime(new Date(result)); + result -= cal.get(Calendar.DST_OFFSET); + + return result; + }// convertWindowsTimeToMilliseconds() + + /** + * converts a java date to a windows time object (is this timezone safe?) + * + * @param javaDate + * the java date to be converted to windows time + * @return the double representing the date in a form windows understands + */ + static public double convertDateToWindowsTime(Date javaDate) { + if (javaDate == null) { + throw new IllegalArgumentException( + "cannot convert null to windows time"); + } + return convertMillisecondsToWindowsTime(javaDate.getTime()); + } + + /** + * Convert a Java time to a COM time. + * + * @param milliseconds + * Java time. + * @return COM time. + */ + static public double convertMillisecondsToWindowsTime(long milliseconds) { + double result = 0.0; + + // code from jacobgen: + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(milliseconds); + milliseconds += (cal.get(Calendar.ZONE_OFFSET) + cal + .get(Calendar.DST_OFFSET)); // add GMT offset + result = (milliseconds / 86400000D) + 25569D; + + return result; + }// convertMillisecondsToWindowsTime() +} diff --git a/java/src/com/jacob/com/Dispatch.java b/java/src/com/jacob/com/Dispatch.java new file mode 100644 index 0000000..861d6e4 --- /dev/null +++ b/java/src/com/jacob/com/Dispatch.java @@ -0,0 +1,872 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. All rights reserved. Originator: Dan Adler + * (http://danadler.com). Get more information about JACOB at + * http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version + * 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +package com.jacob.com; + +/** + * Object represents MS level dispatch object. Each instance of this points at + * some data structure on the MS windows side. + * + * + *

+ * You're going to live here a lot + */ +public class Dispatch extends JacobObject { + + /** + * Used to set the locale in a call. The user locale is another option + */ + public static final int LOCALE_SYSTEM_DEFAULT = 2048; + /** used by callN() and callSubN() */ + public static final int Method = 1; + /** used by callN() and callSubN() */ + public static final int Get = 2; + /** used by put() */ + public static final int Put = 4; + /** not used, probably intended for putRef() */ + public static final int PutRef = 8; + /** + * One of legal values for GetDispId. Not used in this layer and probably + * not needed. + */ + public static final int fdexNameCaseSensitive = 1; + + /** + * This is public because Dispatch.cpp knows its name and accesses it + * directly to get the dispatch id. You really can't rename it or make it + * private + */ + public int m_pDispatch; + + /** program Id passed in by ActiveX components in their constructor */ + private String programId = null; + + private static int NOT_ATTACHED = 0; + + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Object[] NO_OBJECT_ARGS = new Object[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static Variant[] NO_VARIANT_ARGS = new Variant[0]; + /** + * Dummy empty array used one doesn't have to be created on every invocation + */ + private final static int[] NO_INT_ARGS = new int[0]; + + /** + * zero argument constructor that sets the dispatch pointer to 0 This is the + * only way to create a Dispatch without a value in the pointer field. + */ + public Dispatch() { + m_pDispatch = NOT_ATTACHED; + } + + /** + * This constructor calls createInstance with progid. This is the + * constructor used by the ActiveXComponent or by programs that don't like + * the activeX interface but wish to create new connections to windows + * programs. + *

+ * This constructor always creates a new windows/program object because it + * is based on the CoCreate() windows function. + *

+ * + * @param requestedProgramId + * @throws IllegalArgumentException + * if null is passed in as the program id + *

+ */ + public Dispatch(String requestedProgramId) { + programId = requestedProgramId; + if (programId != null && !"".equals(programId)) { + createInstanceNative(requestedProgramId); + } else { + throw new IllegalArgumentException( + "Dispatch(String) does not accept null or an empty string as a parameter"); + } + } + + /** + * native call createInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

+ * This ends up calling CoCreate down in the JNI layer + *

+ * The behavior is different if a ":" character exists in the progId. In + * that case CoGetObject and CreateInstance (someone needs to describe this + * better) + * + * @param progid + */ + private native void createInstanceNative(String progid); + + /** + * native call getActiveInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows GetActiveObject() call + *

+ * This ends up calling GetActiveObject down in the JNI layer + *

+ * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void getActiveInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + * name of the program you wish to connect to + */ + protected void getActiveInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + getActiveInstanceNative(pProgramIdentifier); + } + + /** + * native call coCreateInstance only used by the constructor with the same + * parm type. This probably should be private. It is the wrapper for the + * Windows CoCreate() call + *

+ * This ends up calling CoCreate down in the JNI layer + *

+ * This does not have the special behavior for program ids with ":" in them + * that createInstance has. + * + * @param progid + */ + private native void coCreateInstanceNative(String progid); + + /** + * Wrapper around the native method + * + * @param pProgramIdentifier + */ + protected void coCreateInstance(String pProgramIdentifier) { + if (pProgramIdentifier == null || "".equals(pProgramIdentifier)) { + throw new IllegalArgumentException("program id is required"); + } + this.programId = pProgramIdentifier; + coCreateInstanceNative(pProgramIdentifier); + } + + /** + * Return a different interface by IID string. + *

+ * Once you have a Dispatch object, you can navigate to the other interfaces + * of a COM object by calling QueryInterafce. The argument is an IID string + * in the format: "{9BF24410-B2E0-11D4-A695-00104BFF3241}". You typically + * get this string from the idl file (it's called uuid in there). Any + * interface you try to use must be derived from IDispatch. T The atl + * example uses this. + *

+ * The Dispatch instance resulting from this query is instanciated in the + * JNI code. + * + * @param iid + * @return Dispatch a disptach that matches ?? + */ + public native Dispatch QueryInterface(String iid); + + /** + * Constructor that only gets called from JNI QueryInterface calls JNI code + * that looks up the object for the key passed in. The JNI CODE then creates + * a new dispatch object using this constructor + * + * @param pDisp + */ + protected Dispatch(int pDisp) { + m_pDispatch = pDisp; + } + + /** + * Constructor to be used by subclass that want to swap themselves in for + * the default Dispatch class. Usually you will have a class like + * WordDocument that is a subclass of Dispatch and it will have a + * constructor public WordDocument(Dispatch). That constructor should just + * call this constructor as super(Dispatch) + * + * @param dispatchToBeDisplaced + */ + public Dispatch(Dispatch dispatchToBeDisplaced) { + // TAKE OVER THE IDispatch POINTER + this.m_pDispatch = dispatchToBeDisplaced.m_pDispatch; + // NULL OUT THE INPUT POINTER + dispatchToBeDisplaced.m_pDispatch = NOT_ATTACHED; + } + + /** + * returns the program id if an activeX component created this otherwise it + * returns null. This was added to aid in debugging + * + * @return the program id an activeX component was created against + */ + public String getProgramId() { + return programId; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + @Override + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + @Override + public void safeRelease() { + super.safeRelease(); + if (isAttached()) { + release(); + m_pDispatch = NOT_ATTACHED; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * + * @return true if there is an underlying windows dispatch object + */ + protected boolean isAttached() { + if (m_pDispatch == NOT_ATTACHED) { + return false; + } else { + return true; + } + } + + /** + * @param theOneInQuestion + * dispatch being tested + * @throws IllegalStateException + * if this dispatch isn't hooked up + * @throws IllegalArgumentException + * if null the dispatch under test is null + */ + private static void throwIfUnattachedDispatch(Dispatch theOneInQuestion) { + if (theOneInQuestion == null) { + throw new IllegalArgumentException( + "Can't pass in null Dispatch object"); + } else if (theOneInQuestion.isAttached()) { + return; + } else { + throw new IllegalStateException( + "Dispatch not hooked to windows memory"); + } + } + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param val + * @throws com.jacob.com.NotImplementedException + */ + public static void put_Casesensitive(Dispatch dispatchTarget, String name, + Object val) { + throw new NotImplementedException("not implemented yet"); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // eliminate _Guid arg + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, dispID, lcid, wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + */ + public static void invokeSubv(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokev(dispatchTarget, null, dispID, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @param values + * @return never returns anything because + * @throws com.jacob.com.NotImplementedException + */ + public static Variant callN_CaseSensitive(Dispatch dispatchTarget, + String name, Object[] values) { + throw new NotImplementedException("not implemented yet"); + } + + /** + * @param dispatchTarget + * @param name + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, String name, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * an array of argument objects + */ + public static void callSubN(Dispatch dispatchTarget, int dispID, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /* + * ============================================================ start of the + * getIdsOfNames section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @return int id for the passed in name + */ + public static int getIDOfName(Dispatch dispatchTarget, String name) { + int ids[] = getIDsOfNames(dispatchTarget, + Dispatch.LOCALE_SYSTEM_DEFAULT, new String[] { name }); + return ids[0]; + } + + /** + * @param dispatchTarget + * @param lcid + * @param names + * @return int[] in id array for passed in names + */ + // eliminated _Guid argument + public static native int[] getIDsOfNames(Dispatch dispatchTarget, int lcid, + String[] names); + + /** + * @param dispatchTarget + * @param names + * @return int[] int id array for passed in names + */ + // eliminated _Guid argument + public static int[] getIDsOfNames(Dispatch dispatchTarget, String[] names) { + return getIDsOfNames(dispatchTarget, Dispatch.LOCALE_SYSTEM_DEFAULT, + names); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, String name, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param dispID + * @param args + * @return Variant returned by call + */ + public static Variant callN(Dispatch dispatchTarget, int dispID, + Object... args) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, Dispatch.Method | Dispatch.Get, + VariantUtilities.objectsToVariants(args), new int[args.length]); + } + + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, dispID, lcid, wFlags, + VariantUtilities.objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param oArg + * @param uArgErr + * @return Variant returned by invoke + */ + public static Variant invoke(Dispatch dispatchTarget, int dispID, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispID, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * callN section =========================================================== + */ + + /** + * @param dispatchTarget + * @param name + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param name + * @param attributes + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, String name, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, name, attributes); + } + + /** + * @param dispatchTarget + * @param dispid + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, NO_VARIANT_ARGS); + } + + /** + * @param dispatchTarget + * @param dispid + * @param attributes + * var arg list of attributes that will be passed to the + * underlying function + * @return Variant returned by underlying callN + */ + public static Variant call(Dispatch dispatchTarget, int dispid, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + return callN(dispatchTarget, dispid, attributes); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param val + */ + public static void put(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /** + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void put(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.Put, new Object[] { val }, + new int[1]); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispID + * @param lcid + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static native Variant invokev(Dispatch dispatchTarget, String name, + int dispID, int lcid, int wFlags, Variant[] vArg, int[] uArgErr); + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param vArg + * @param uArgErr + * @param wFlagsEx + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, String name, + int wFlags, Variant[] vArg, int[] uArgErr, int wFlagsEx) { + throwIfUnattachedDispatch(dispatchTarget); + // do not implement IDispatchEx for now + return invokev(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, vArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispID + * @param wFlags + * @param vArg + * @param uArgErr + * @return Variant returned by underlying invokev + */ + public static Variant invokev(Dispatch dispatchTarget, int dispID, + int wFlags, Variant[] vArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, null, dispID, + Dispatch.LOCALE_SYSTEM_DEFAULT, wFlags, vArg, uArgErr); + } + + /* + * ============================================================ start of the + * invokeSubv section + * =========================================================== + */ + + // removed _Guid argument + /** + * @param dispatchTarget + * @param name + * @param dispid + * @param lcid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int dispid, int lcid, int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSubv(dispatchTarget, name, dispid, lcid, wFlags, VariantUtilities + .objectsToVariants(oArg), uArgErr); + } + + /* + * ============================================================ start of the + * invokeSub section + * =========================================================== + */ + /** + * @param dispatchTarget + * @param name + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, String name, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, name, 0, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /** + * @param dispatchTarget + * @param dispid + * @param wFlags + * @param oArg + * @param uArgErr + */ + public static void invokeSub(Dispatch dispatchTarget, int dispid, + int wFlags, Object[] oArg, int[] uArgErr) { + throwIfUnattachedDispatch(dispatchTarget); + invokeSub(dispatchTarget, null, dispid, Dispatch.LOCALE_SYSTEM_DEFAULT, + wFlags, oArg, uArgErr); + } + + /* + * ============================================================ start of the + * callSubN section + * =========================================================== + */ + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + */ + public static void callSub(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param name + * @param attributes + * var args list of attributes to be passed to underlying + * functions + */ + public static void callSub(Dispatch dispatchTarget, String name, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, name, attributes); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + */ + public static void callSub(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, NO_OBJECT_ARGS); + } + + /** + * makes call to native callSubN + * + * @param dispatchTarget + * @param dispid + * @param attributes + * var args list of attributes to be passed to underlying + * function + */ + public static void callSub(Dispatch dispatchTarget, int dispid, + Object... attributes) { + throwIfUnattachedDispatch(dispatchTarget); + callSubN(dispatchTarget, dispid, attributes); + } + + /* + * ============================================================ start of the + * invokev section + * =========================================================== + */ + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param name + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, String name) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, name, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /** + * Cover for call to underlying invokev() + * + * @param dispatchTarget + * @param dispid + * @return Variant returned by the request for retrieval of parameter + */ + public static Variant get(Dispatch dispatchTarget, int dispid) { + throwIfUnattachedDispatch(dispatchTarget); + return invokev(dispatchTarget, dispid, Dispatch.Get, NO_VARIANT_ARGS, + NO_INT_ARGS); + } + + /* + * ============================================================ start of the + * invoke section + * =========================================================== + */ + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param name + * @param val + */ + public static void putRef(Dispatch dispatchTarget, String name, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, name, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * cover for underlying call to invoke + * + * @param dispatchTarget + * @param dispid + * @param val + */ + public static void putRef(Dispatch dispatchTarget, int dispid, Object val) { + throwIfUnattachedDispatch(dispatchTarget); + invoke(dispatchTarget, dispid, Dispatch.PutRef, new Object[] { val }, + new int[1]); + } + + /** + * not implemented yet + * + * @param dispatchTarget + * @param name + * @return Variant never returned + * @throws com.jacob.com.NotImplementedException + */ + public static Variant get_CaseSensitive(Dispatch dispatchTarget, String name) { + throw new NotImplementedException("not implemented yet"); + } + + /** + * Cover for native method + * + * @param disp + * @param dispid + * @param lcid + * @return 0 if the dispatch is still active and 1 if it has exited + */ + public static native int hasExited(Dispatch disp, int dispid, int lcid); + + /** + * The method is used to poll until it returns 1, indicating that the COM + * server in gone. + *

+ * Sourceforge feature request 2927058 + * + * @param dispatchTarget + * @return 0 if the dispatch is still active and 1 if it has exited + */ + public static int hasExited(Dispatch dispatchTarget) { + throwIfUnattachedDispatch(dispatchTarget); + return hasExited(dispatchTarget, 0, LOCALE_SYSTEM_DEFAULT); + } + +} diff --git a/java/src/com/jacob/com/DispatchEvents.java b/java/src/com/jacob/com/DispatchEvents.java new file mode 100644 index 0000000..62de581 --- /dev/null +++ b/java/src/com/jacob/com/DispatchEvents.java @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * This class creates the scaffolding for event callbacks. Every instance of tis + * acts as a wrapper around some java object that wants callbacks from the + * microsoft side. It represents the connection between Java and COM for + * callbacks. + *

+ * The callback mechanism will take any event that it receives and try and find + * a java method with the same name that accepts the Variant... as a parameter. + * It will then wrap the call back data in the Variant array and call the java + * method of the object that this DispatchEvents object was initialized with. + *

+ * Instances of this class are created with "sink object" that will receive the + * event messages. The sink object is wrapped in an Invocation handler that + * actually receives the messages and then forwards them on to the "sink + * object". The constructors recognize when an instance of InvocationProxy is + * passed in and do not create a new InvocationProxy as a wrapper. They instead + * use the passed in InvocationProxy. + * + */ +public class DispatchEvents extends JacobObject { + + /** + * pointer to an MS data struct. The COM layer knows the name of this + * variable and puts the windows memory pointer here. + */ + int m_pConnPtProxy = 0; + + /** + * the wrapper for the event sink. This object is the one that will be sent + * a message when an event occurs in the MS layer. Normally, the + * InvocationProxy will forward the messages to a wrapped object that it + * contains. + */ + InvocationProxy mInvocationProxy = null; + + /** + * This is the most commonly used constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

+ * Can be used on any object that implements IProvideClassInfo. + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink) { + this(sourceOfEvent, eventSink, null); + } + + /** + * None of the samples use this constructor. + *

+ * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

+ * Used when the program doesn't implement IProvideClassInfo. It provides a + * way to find the TypeLib in the registry based on the programId. The + * TypeLib is looked up in the registry on the path + * HKEY_LOCAL_MACHINE/SOFTWARE/Classes/CLSID/(CLID drived from + * progid)/ProgID/Typelib + * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId + * program id in the registry that has a TypeLib subkey. The + * progrId is mapped to a CLSID that is they used to look up the + * key to the Typelib + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId) { + this(sourceOfEvent, eventSink, progId, null); + } + + /** + * Creates the event callback linkage between the the MS program represented + * by the Dispatch object and the Java object that will receive the + * callback. + *

+ * This method was added because Excel doesn't implement IProvideClassInfo + * and the registry entry for Excel.Application doesn't include a typelib + * key. + * + *

+	 * DispatchEvents de = new DispatchEvents(someDispatch, someEventHAndler,
+	 * 		"Excel.Application",
+	 * 		"C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE");
+	 * 
+ * + * @param sourceOfEvent + * Dispatch object who's MS app will generate callbacks + * @param eventSink + * Java object that wants to receive the events + * @param progId , + * mandatory if the typelib is specified + * @param typeLib + * The location of the typelib to use + */ + public DispatchEvents(Dispatch sourceOfEvent, Object eventSink, + String progId, String typeLib) { + if (JacobObject.isDebugEnabled()) { + System.out.println("DispatchEvents: Registering " + eventSink + + "for events "); + } + if (eventSink instanceof InvocationProxy) { + mInvocationProxy = (InvocationProxy) eventSink; + } else { + mInvocationProxy = getInvocationProxy(eventSink); + } + if (mInvocationProxy != null) { + init3(sourceOfEvent, mInvocationProxy, progId, typeLib); + } else { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("Cannot register null event sink for events"); + } + throw new IllegalArgumentException( + "Cannot register null event sink for events"); + } + } + + /** + * Returns an instance of the proxy configured with pTargetObject as its + * target + * + * @param pTargetObject + * @return InvocationProxy an instance of the proxy this DispatchEvents will + * send to the COM layer + */ + protected InvocationProxy getInvocationProxy(Object pTargetObject) { + InvocationProxy newProxy = new InvocationProxyAllVariants(); + newProxy.setTarget(pTargetObject); + return newProxy; + } + + /** + * hooks up a connection point proxy by progId event methods on the sink + * object will be called by name with a signature of (Variant[] args) + * + * You must specify the location of the typeLib. + * + * @param src + * dispatch that is the source of the messages + * @param sink + * the object that will receive the messages + * @param progId + * optional program id. most folks don't need this either + * @param typeLib + * optional parameter for those programs that don't register + * their type libs (like Excel) + */ + private native void init3(Dispatch src, Object sink, String progId, + String typeLib); + + /** + * now private so only this object can asccess was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + if (mInvocationProxy != null) { + mInvocationProxy.setTarget(null); + } + mInvocationProxy = null; + super.safeRelease(); + if (m_pConnPtProxy != 0) { + release(); + m_pConnPtProxy = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug("DispatchEvents:" + this.hashCode() + " double release"); + } + } + } + +} diff --git a/java/src/com/jacob/com/DispatchIdentifier.java b/java/src/com/jacob/com/DispatchIdentifier.java new file mode 100644 index 0000000..bc18caf --- /dev/null +++ b/java/src/com/jacob/com/DispatchIdentifier.java @@ -0,0 +1,82 @@ +/** + * + */ +package com.jacob.com; + +/** + * A bunch of DispatchIds that were pulled out of the Dispatch class for version + * 1.14. + */ +public class DispatchIdentifier { + + private DispatchIdentifier() { + // This is utility class so there is no constructor. + } + + public static final int DISPID_UNKNOWN = -1; + public static final int DISPID_VALUE = 0; + public static final int DISPID_PROPERTYPUT = -3; + public static final int DISPID_NEWENUM = -4; + public static final int DISPID_EVALUATE = -5; + public static final int DISPID_CONSTRUCTOR = -6; + public static final int DISPID_DESTRUCTOR = -7; + public static final int DISPID_COLLECT = -8; + public static final int DISPID_AUTOSIZE = -500; + public static final int DISPID_BACKCOLOR = -501; + public static final int DISPID_BACKSTYLE = -502; + public static final int DISPID_BORDERCOLOR = -503; + public static final int DISPID_BORDERSTYLE = -504; + public static final int DISPID_BORDERWIDTH = -505; + public static final int DISPID_DRAWMODE = -507; + public static final int DISPID_DRAWSTYLE = -508; + public static final int DISPID_DRAWWIDTH = -509; + public static final int DISPID_FILLCOLOR = -510; + public static final int DISPID_FILLSTYLE = -511; + public static final int DISPID_FONT = -512; + public static final int DISPID_FORECOLOR = -513; + public static final int DISPID_ENABLED = -514; + public static final int DISPID_HWND = -515; + public static final int DISPID_TABSTOP = -516; + public static final int DISPID_TEXT = -517; + public static final int DISPID_CAPTION = -518; + public static final int DISPID_BORDERVISIBLE = -519; + public static final int DISPID_APPEARANCE = -520; + public static final int DISPID_MOUSEPOINTER = -521; + public static final int DISPID_MOUSEICON = -522; + public static final int DISPID_PICTURE = -523; + public static final int DISPID_VALID = -524; + public static final int DISPID_READYSTATE = -525; + public static final int DISPID_REFRESH = -550; + public static final int DISPID_DOCLICK = -551; + public static final int DISPID_ABOUTBOX = -552; + public static final int DISPID_CLICK = -600; + public static final int DISPID_DBLCLICK = -601; + public static final int DISPID_KEYDOWN = -602; + public static final int DISPID_KEYPRESS = -603; + public static final int DISPID_KEYUP = -604; + public static final int DISPID_MOUSEDOWN = -605; + public static final int DISPID_MOUSEMOVE = -606; + public static final int DISPID_MOUSEUP = -607; + public static final int DISPID_ERROREVENT = -608; + public static final int DISPID_READYSTATECHANGE = -609; + public static final int DISPID_AMBIENT_BACKCOLOR = -701; + public static final int DISPID_AMBIENT_DISPLAYNAME = -702; + public static final int DISPID_AMBIENT_FONT = -703; + public static final int DISPID_AMBIENT_FORECOLOR = -704; + public static final int DISPID_AMBIENT_LOCALEID = -705; + public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706; + public static final int DISPID_AMBIENT_SCALEUNITS = -707; + public static final int DISPID_AMBIENT_TEXTALIGN = -708; + public static final int DISPID_AMBIENT_USERMODE = -709; + public static final int DISPID_AMBIENT_UIDEAD = -710; + public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711; + public static final int DISPID_AMBIENT_SHOWHATCHING = -712; + public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713; + public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714; + public static final int DISPID_AMBIENT_AUTOCLIP = -715; + public static final int DISPID_AMBIENT_APPEARANCE = -716; + public static final int DISPID_AMBIENT_CODEPAGE = -725; + public static final int DISPID_AMBIENT_PALETTE = -726; + public static final int DISPID_AMBIENT_CHARSET = -727; + public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728; +} diff --git a/java/src/com/jacob/com/DispatchProxy.java b/java/src/com/jacob/com/DispatchProxy.java new file mode 100644 index 0000000..0a4f402 --- /dev/null +++ b/java/src/com/jacob/com/DispatchProxy.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * If you need to pass a COM Dispatch object between STA threads, you have to + * marshall the interface. This class is used as follows: the STA that creates + * the Dispatch object must construct an instance of this class. Another thread + * can then call toDispatch() on that instance and get a Dispatch pointer which + * has been marshalled. WARNING: You can only call toDispatch() once! If you + * need to call it multiple times (or from multiple threads) you need to + * construct a separate DispatchProxy instance for each such case! + */ +public class DispatchProxy extends JacobObject { + /** + * Comment for m_pStream + */ + public int m_pStream; + + /** + * Marshals the passed in dispatch into the stream + * + * @param localDispatch + */ + public DispatchProxy(Dispatch localDispatch) { + MarshalIntoStream(localDispatch); + } + + /** + * + * @return Dispatch the dispatch retrieved from the stream + */ + public Dispatch toDispatch() { + return MarshalFromStream(); + } + + private native void MarshalIntoStream(Dispatch d); + + private native Dispatch MarshalFromStream(); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + public void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pStream != 0) { + release(); + m_pStream = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/EnumVariant.java b/java/src/com/jacob/com/EnumVariant.java new file mode 100644 index 0000000..7f16542 --- /dev/null +++ b/java/src/com/jacob/com/EnumVariant.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * An implementation of IEnumVariant based on code submitted by Thomas Hallgren + * (mailto:Thomas.Hallgren@eoncompany.com) + */ +public class EnumVariant extends JacobObject implements + java.util.Enumeration { + private int m_pIEnumVARIANT; + + private final Variant[] m_recBuf = new Variant[1]; + + // this only gets called from JNI + // + protected EnumVariant(int pIEnumVARIANT) { + m_pIEnumVARIANT = pIEnumVARIANT; + } + + /** + * @param disp + */ + public EnumVariant(Dispatch disp) { + int[] hres = new int[1]; + Variant evv = Dispatch.invokev(disp, DispatchIdentifier.DISPID_NEWENUM, + Dispatch.Get, new Variant[0], hres); + if (evv.getvt() != Variant.VariantObject) + // + // The DISPID_NEWENUM did not result in a valid object + // + throw new ComFailException("Can't obtain EnumVARIANT"); + + EnumVariant tmp = evv.toEnumVariant(); + m_pIEnumVARIANT = tmp.m_pIEnumVARIANT; + tmp.m_pIEnumVARIANT = 0; + } + + /** + * Implements java.util.Enumeration + * + * @return boolean true if there are more elements in this enumeration + */ + public boolean hasMoreElements() { + { + if (m_recBuf[0] == null) { + if (this.Next(m_recBuf) <= 0) + return false; + } + return true; + } + } + + /** + * Implements java.util.Enumeration + * + * @return next element in the enumeration + */ + public Variant nextElement() { + Variant last = m_recBuf[0]; + if (last == null) { + if (this.Next(m_recBuf) <= 0) + throw new java.util.NoSuchElementException(); + last = m_recBuf[0]; + } + m_recBuf[0] = null; + return last; + } + + /** + * Get next element in collection or null if at end + * + * @return Variant that is next in the collection + * @deprecated use nextElement() instead + */ + @Deprecated + public Variant Next() { + if (hasMoreElements()) + return nextElement(); + return null; + } + + /** + * This should be private and wrapped to protect JNI layer. + * + * @param receiverArray + * @return Returns the next variant object pointer as an int from windows + * layer + */ + public native int Next(Variant[] receiverArray); + + /** + * This should be private and wrapped to protect JNI layer. + * + * @param count + * number to skip + */ + public native void Skip(int count); + + /** + * This should be private and wrapped to protect JNI layer + */ + public native void Reset(); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + protected void finalize() { + safeRelease(); + } + + /* + * (non-Javadoc) + * + * @see com.jacob.com.JacobObject#safeRelease() + */ + public void safeRelease() { + super.safeRelease(); + if (m_pIEnumVARIANT != 0) { + this.release(); + m_pIEnumVARIANT = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/InvocationProxy.java b/java/src/com/jacob/com/InvocationProxy.java new file mode 100644 index 0000000..ddf98e6 --- /dev/null +++ b/java/src/com/jacob/com/InvocationProxy.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * @version $Id$ + * @author joe + * + * DispatchEvents wraps this class around any event handlers before making the + * JNI call that sets up the link with EventProxy. This means that + * EventProxy.cpp just calls invoke(String,Variant[]) against the instance of + * this class. Then this class does reflection against the event listener to + * call the actual event methods. The event methods can return void or return a + * Variant. Any value returned will be passed back to the calling windows module + * by the Jacob JNI layer. + *

+ * + * The void returning signature is the standard legacy signature. The Variant + * returning signature was added in 1.10 to support event handlers returning + * values. + * + */ +public abstract class InvocationProxy { + + /** + * the object we will try and forward to. + */ + protected Object mTargetObject = null; + + /** + * dummy constructor for subclasses that don't actually wrap anything and + * just want to override the invoke() method + */ + protected InvocationProxy() { + super(); + } + + /** + * The method actually invoked by EventProxy.cpp. The method name is + * calculated by the underlying JNI code from the MS windows Callback + * function name. The method is assumed to take an array of Variant objects. + * The method may return a Variant or be a void. Those are the only two + * options that will not blow up. + *

+ * Subclasses that override this should make sure mTargetObject is not null + * before processing. + * + * @param methodName + * name of method in mTargetObject we will invoke + * @param targetParameters + * Variant[] that is the single parameter to the method + * @return an object that will be returned to the com event caller + */ + public abstract Variant invoke(String methodName, + Variant targetParameters[]); + + /** + * used by EventProxy.cpp to create variant objects in the right thread + * + * @return Variant object that will be used by the COM layer + */ + public Variant getVariant() { + return new VariantViaEvent(); + } + + /** + * Sets the target for this InvocationProxy. + * + * @param pTargetObject + * @throws IllegalArgumentException + * if target is not publicly accessible + */ + public void setTarget(Object pTargetObject) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: setting target " + + pTargetObject); + } + if (pTargetObject != null) { + // JNI code apparently bypasses this check and could operate against + // protected classes. This seems like a security issue... + // maybe it was because JNI code isn't in a package? + if (!java.lang.reflect.Modifier.isPublic(pTargetObject.getClass() + .getModifiers())) { + throw new IllegalArgumentException( + "InvocationProxy only public classes can receive event notifications"); + } + } + mTargetObject = pTargetObject; + } + +} diff --git a/java/src/com/jacob/com/InvocationProxyAllVariants.java b/java/src/com/jacob/com/InvocationProxyAllVariants.java new file mode 100644 index 0000000..a22ff96 --- /dev/null +++ b/java/src/com/jacob/com/InvocationProxyAllVariants.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * This class acts as a proxy between the windows event callback mechanism and + * the Java classes that are looking for events. It assumes that all of the Java + * classes that are looking for events implement methods with the same names as + * the windows events and that the implemented methods accept an array of + * variant objects. The methods can return void or a Variant that will be + * returned to the calling layer. All Event methods that will be recognized by + * InvocationProxyAllEvents have the signature + * + * void eventMethodName(Variant[]) or + * Variant eventMethodName(Variant[]) + */ +public class InvocationProxyAllVariants extends InvocationProxy { + + /* + * (non-Javadoc) + * + * @see com.jacob.com.InvocationProxy#invoke(java.lang.String, + * com.jacob.com.Variant[]) + */ + @SuppressWarnings("unchecked") + public Variant invoke(String methodName, Variant targetParameters[]) { + Variant mVariantToBeReturned = null; + if (mTargetObject == null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: received notification (" + + methodName + ") with no target set"); + } + // structured programming guidlines say this return should not be up + // here + return null; + } + Class targetClass = mTargetObject.getClass(); + if (methodName == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing method name"); + } + if (targetParameters == null) { + throw new IllegalArgumentException( + "InvocationProxy: missing Variant parameters"); + } + try { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: trying to invoke " + + methodName + " on " + mTargetObject); + } + Method targetMethod; + targetMethod = targetClass.getMethod(methodName, + new Class[] { Variant[].class }); + if (targetMethod != null) { + // protected classes can't be invoked against even if they + // let you grab the method. you could do + // targetMethod.setAccessible(true); + // but that should be stopped by the security manager + Object mReturnedByInvocation = null; + mReturnedByInvocation = targetMethod.invoke(mTargetObject, + new Object[] { targetParameters }); + if (mReturnedByInvocation == null) { + mVariantToBeReturned = null; + } else if (!(mReturnedByInvocation instanceof Variant)) { + // could try and convert to Variant here. + throw new IllegalArgumentException( + "InvocationProxy: invokation of target method returned " + + "non-null non-variant object: " + + mReturnedByInvocation); + } else { + mVariantToBeReturned = (Variant) mReturnedByInvocation; + } + } + } catch (SecurityException e) { + // what causes this exception? + e.printStackTrace(); + } catch (NoSuchMethodException e) { + // this happens whenever the listener doesn't implement all the + // methods + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("InvocationProxy: listener (" + mTargetObject + + ") doesn't implement " + methodName); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + // we can throw these inside the catch block so need to re-throw it + throw e; + } catch (IllegalAccessException e) { + // can't access the method on the target instance for some reason + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("InvocationProxy: probably tried to access public method on non public class" + + methodName); + } + e.printStackTrace(); + } catch (InvocationTargetException e) { + // invocation of target method failed + e.printStackTrace(); + } + return mVariantToBeReturned; + + } +} diff --git a/java/src/com/jacob/com/JacobException.java b/java/src/com/jacob/com/JacobException.java new file mode 100644 index 0000000..20f62d1 --- /dev/null +++ b/java/src/com/jacob/com/JacobException.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * The parent class of all Jacob exceptions. They all used to be based off of + * RuntimeException or ComException but it was decided to base them all off of + * one owned by this project. + */ +public class JacobException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -1637125318746002715L; + + /** + * Default constructor. Calls super with a "No Message Provided" string + */ + public JacobException() { + super("No Message Provided"); + } + + /** + * standard constructor + * + * @param message + */ + public JacobException(String message) { + super(message); + } +} diff --git a/java/src/com/jacob/com/JacobObject.java b/java/src/com/jacob/com/JacobObject.java new file mode 100644 index 0000000..9442360 --- /dev/null +++ b/java/src/com/jacob/com/JacobObject.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * The superclass of all Jacob objects. It is used to create a standard API + * framework and to facilitate memory management for Java and COM memory + * elements. + *

+ * All instances of this class and subclasses are automatically managed by the + * ROT. This means the ROT cannot be a subclass of JacobObject. + *

+ * All COM object created by JACOB extend this class so that we can + * automatically release them when the thread is detached from COM - if we leave + * it to the finalizer it will call the release from another thread, which may + * result in a segmentation violation. + */ +public class JacobObject { + + /** + * Standard constructor that adds this JacobObject to the memory management + * pool. + */ + public JacobObject() { + ROT.addObject(this); + } + + /** + * Finalizers call this method. This method should release any COM data + * structures in a way that it can be called multiple times. This can happen + * if someone manually calls this and then a finalizer calls it. + */ + public void safeRelease() { + // currently does nothing - subclasses may do something + if (isDebugEnabled()) { + // this used to do a toString() but that is bad for SafeArray + debug("SafeRelease: " + this.getClass().getName()); + } + } + + /** + * When things go wrong, it is useful to be able to debug the ROT. + */ + private static final boolean DEBUG = + // true; + "true".equalsIgnoreCase(System.getProperty("com.jacob.debug")); + + protected static boolean isDebugEnabled() { + return DEBUG; + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildDate() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildDate() { + return JacobReleaseInfo.getBuildDate(); + } + + /** + * Loads JacobVersion.Properties and returns the value of version in it + * + * @deprecated use JacobReleaseInfo.getBuildVersion() instead. + * @return String value of version in JacobVersion.Properties or "" if none + */ + @Deprecated + public static String getBuildVersion() { + return JacobReleaseInfo.getBuildVersion(); + } + + /** + * Very basic debugging function. + * + * @param istrMessage + */ + protected static void debug(String istrMessage) { + if (isDebugEnabled()) { + System.out.println(Thread.currentThread().getName() + ": " + + istrMessage); + } + } + + /** + * force the jacob DLL to be loaded whenever this class is referenced + */ + static { + LibraryLoader.loadJacobLibrary(); + } + +} \ No newline at end of file diff --git a/java/src/com/jacob/com/JacobReleaseInfo.java b/java/src/com/jacob/com/JacobReleaseInfo.java new file mode 100644 index 0000000..8940859 --- /dev/null +++ b/java/src/com/jacob/com/JacobReleaseInfo.java @@ -0,0 +1,96 @@ +package com.jacob.com; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * An interface to the version properties file. This code was removed from + * JacobObject because it doesn't belong there. + * + */ +public class JacobReleaseInfo { + + /** + * holds the build version as retrieved from the version properties file + * that exists in the JAR. This can be retrieved by calling the static + * method getBuildVersion() + * + * @see #getBuildVersion() + */ + private static String buildVersion = ""; + /** + * holds the build date as retrieved from the version properties file that + * exists in the JAR This can be retrieved by calling the static method + * getBuildDate() + * + * @see #getBuildDate() + */ + private static String buildDate = ""; + /** the name of the jacob version properties file */ + private static final String PROPERTY_FILE_NAME = "META-INF/JacobVersion.properties"; + + /** + * Loads version information from PROPERTY_FILE_NAME that was built as part + * of this release. + * + * @throws IllegalStateException + * when it can't find the version properties file + */ + private static void loadVersionProperties() { + Properties versionProps = new Properties(); + // can't use system class loader cause won't work in JavaWebStart + InputStream stream = JacobReleaseInfo.class.getClassLoader() + .getResourceAsStream(PROPERTY_FILE_NAME); + // This should never happen. This is an attempt to make something work + // for WebSphere. They may be using some kind of Servlet loader that + // needs an absolute path based search + if (stream == null) { + stream = JacobReleaseInfo.class.getClassLoader() + .getResourceAsStream("/" + PROPERTY_FILE_NAME); + } + // A report came in that WebSphere had trouble finding the file + // so lets trap it. Plus, it's a good idea anyway. + if (stream == null) { + throw new IllegalStateException( + "Can't find " + + PROPERTY_FILE_NAME + + " using JacobReleaseInfo.class.getClassLoader().getResourceAsStream()"); + } else { + try { + versionProps.load(stream); + stream.close(); + buildVersion = (String) versionProps.get("version"); + buildDate = (String) versionProps.get("build.date"); + } catch (IOException ioe) { + ioe.printStackTrace(); + System.err.println("Warning! Couldn't load props " + ioe); + } + } + } + + /** + * loads PROPERT_FILE_NAME and returns the value of version in it + * + * @return String value of version in PROPERT_FILE_NAME or "" if none + */ + public static String getBuildDate() { + if (buildDate.equals("")) { + loadVersionProperties(); + } + return buildDate; + } + + /** + * loads PROPERT_FILE_NAME and returns the value of version in it + * + * @return String value of version in PROPERT_FILE_NAME or "" if none + */ + public static String getBuildVersion() { + if (buildVersion.equals("")) { + loadVersionProperties(); + } + return buildVersion; + } + +} diff --git a/java/src/com/jacob/com/LibraryLoader.java b/java/src/com/jacob/com/LibraryLoader.java new file mode 100644 index 0000000..85f9a16 --- /dev/null +++ b/java/src/com/jacob/com/LibraryLoader.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999-2007 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Locale; +import java.util.MissingResourceException; +import java.util.ResourceBundle; +import java.util.Set; + +/** + * Utility class to centralize the way in which the jacob JNI library is loaded. + *

+ * + * This supports defining the path or library name using system properties or a + * custom resource file. If desired, jacob can auto-detect the correct version + * of the DLL for 32 or 64 bit windows, as long as you have named them + * differently. + * + *

    + *
  1. If system property {@link #JACOB_DLL_PATH} is defined, the file located + * there will be loaded as the jacob dll using System.load().
  2. + * + *
  3. If system property {@link #JACOB_DLL_NAME} is defined, the file located + * there will be loaded as the jacob dll.
  4. + *
  5. If system property {@link #JACOB_DLL_NAME_X86} and + * {@link #JACOB_DLL_NAME_X64} are defined, the file located there will be + * loaded as the jacob dll, depending on the version of Windows.
  6. + * + *
  7. If {@link #JACOB_DLL_NAME} is defined in the + * {@code com.jacob.com.JacobLibraryLoader} resource file, the specified dll + * will be loaded from the {@code java.library.path}.
  8. + *
  9. If {@link #JACOB_DLL_NAME_X86} and {@link #JACOB_DLL_NAME_X64} are + * defined in the {@code com.jacob.com.JacobLibraryLoader} resource file, the + * specified dll will be loaded from the {@code java.library.path}, depending + * on the version of Windows.
  10. + * + *
  11. If none of the above are true, the default is to load the library named + * "jacob-<version>-<arch>" (or + * "jacob-<version>-<arch&rt;.dll") from the {@code java.library.path}. + *
  12. + *
+ * + * The standard behavior for most applications is that {@code LoadLibrary()} + * will be called to load the dll. {@code LoadLibary()} searches directories + * specified in the variable {@code java.library.path}. This is why most test + * cases specify -Djava.library.path in their command line arguments. + *

+ * JACOB_DLL_PATH submitted sourceforge ticket 1493647 Added 1.11
+ * JACOB_DLL_NAME, JACOB_DLL_NAME_32, JACOB_DLL_NAME_64 submitted sourceforge + * ticket 1845039 Added 1.14M7 + * + * @author Scott Dickerson (sjd78) + * @author Jason Smith + */ +public final class LibraryLoader { + /** + * Name of system property (currently jacob.dll.path) that may + * contain an absolute path to the JNI library. + */ + public static final String JACOB_DLL_PATH = "jacob.dll.path"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'). + */ + public static final String JACOB_DLL_NAME = "jacob.dll.name"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'), 32 + * bit windows. + */ + public static final String JACOB_DLL_NAME_X86 = "jacob.dll.name.x86"; + + /** + * Name of system property (currently jacob.dll.name) that may + * contain an alternate name for the JNI library (default is 'jacob'), 64 + * bit windows. + */ + public static final String JACOB_DLL_NAME_X64 = "jacob.dll.name.x64"; + + /** + * Appended to "jacob" when building DLL name This string must EXACTLY match + * the string in the build.xml file + */ + public static final String DLL_NAME_MODIFIER_32_BIT = "x86"; + /** + * Appended to "jacob" when building DLL name This string must EXACTLY match + * the string in the build.xml file + */ + public static final String DLL_NAME_MODIFIER_64_BIT = "x64"; + + /** + * Load the jacob dll either from an absolute path or by a library name, + * both of which may be defined in various ways. + * + * @throws UnsatisfiedLinkError + * if the library does not exist. + */ + public static void loadJacobLibrary() { + // In some cases, a library that uses Jacob won't be able to set system + // properties + // prior to Jacob being loaded. The resource bundle provides an + // alternate way to + // override DLL name or path that will be loaded with Jacob regardless + // of other + // initialization order. + ResourceBundle resources = null; + Set keys = new HashSet(); + try { + resources = ResourceBundle.getBundle(LibraryLoader.class.getName(), + Locale.getDefault(), LibraryLoader.class.getClassLoader()); + for (Enumeration i = resources.getKeys(); i + .hasMoreElements();) { + String key = i.nextElement(); + keys.add(key); + } + } catch (MissingResourceException e) { + // Do nothing. Expected. + } + + // First, check for a defined PATH. System property overrides resource + // bundle. + String path = System.getProperty(JACOB_DLL_PATH); + if (path == null && resources != null && keys.contains(JACOB_DLL_PATH)) { + path = (String) resources.getObject(JACOB_DLL_PATH); + } + + if (path != null) { + JacobObject.debug("Loading library " + path + + " using System.loadLibrary "); + System.load(path); + } else { + // Path was not defined, so use the OS mechanism for loading + // libraries. + // Check for a defined NAME. System property overrides resource + // bundle. + String name = null; + + if (System.getProperty(JACOB_DLL_NAME) != null) { + name = System.getProperty(JACOB_DLL_NAME); + } else if (System.getProperty(JACOB_DLL_NAME_X86) != null + && shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X86); + } else if (System.getProperty(JACOB_DLL_NAME_X64) != null + && !shouldLoad32Bit()) { + name = System.getProperty(JACOB_DLL_NAME_X64); + } else if (resources != null && keys.contains(JACOB_DLL_NAME)) { + name = resources.getString(JACOB_DLL_NAME); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X86) + && shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X86); + } else if (resources != null && keys.contains(JACOB_DLL_NAME_X64) + && !shouldLoad32Bit()) { + name = resources.getString(JACOB_DLL_NAME_X64); + } else { + // No alternate NAME or PATH was defined, so use the default. + // We will almost always end up here. + name = getPreferredDLLName(); + } + + JacobObject.debug("Loading library " + name + + " using System.loadLibrary "); + // System.out.println("Loading " + name); + System.loadLibrary(name); + } + } + + /** + * Developer note: This method MUST be synchronized with the DLL names + * created as part of the build process in build.xml + *

+ * The DLL name is "jacob\.release" + * + * @return the preferred name of the DLL adjusted for this platform and + * version without the ".dll" extension + */ + public static String getPreferredDLLName() { + if (shouldLoad32Bit()) { + return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "-" + + DLL_NAME_MODIFIER_32_BIT; + } else { + return "jacob" + "-" + JacobReleaseInfo.getBuildVersion() + "-" + + DLL_NAME_MODIFIER_64_BIT; + } + } + + /** + * Detects whether this is a 32-bit JVM. + * + * @return {@code true} if this is a 32-bit JVM. + */ + protected static boolean shouldLoad32Bit() { + // This guesses whether we are running 32 or 64 bit Java. + // This works for Sun and IBM JVMs version 5.0 or later. + // May need to be adjusted for non-Sun JVMs. + + String bits = System.getProperty("sun.arch.data.model", "?"); + if (bits.equals("32")) + return true; + else if (bits.equals("64")) + return false; + + // this works for jRocket + String arch = System.getProperty("java.vm.name", "?"); + if (arch.toLowerCase().indexOf("64-bit") >= 0) + return false; + + return true; + } +} // LibraryLoader diff --git a/java/src/com/jacob/com/MainSTA.java b/java/src/com/jacob/com/MainSTA.java new file mode 100644 index 0000000..5a8f0ea --- /dev/null +++ b/java/src/com/jacob/com/MainSTA.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * We provide our own main sta thread to avoid COM tagging a random thread as + * the main STA - this is the thread in which all Apartment threaded components + * will be created if the client chooses an MTA threading model for the java + * side of the app. + */ +public class MainSTA extends STA { +} \ No newline at end of file diff --git a/java/src/com/jacob/com/NotImplementedException.java b/java/src/com/jacob/com/NotImplementedException.java new file mode 100644 index 0000000..8971158 --- /dev/null +++ b/java/src/com/jacob/com/NotImplementedException.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * Thrown by java APIs that are not implemented either because they were never + * implemented or because they are being deprecated This is a subclass of + * ComException so callers can still just catch ComException. + */ +public class NotImplementedException extends JacobException { + + /** + * + */ + private static final long serialVersionUID = -9169900832852356445L; + + /** + * @param description + */ + public NotImplementedException(String description) { + super(description); + } + +} diff --git a/java/src/com/jacob/com/ROT.java b/java/src/com/jacob/com/ROT.java new file mode 100644 index 0000000..2f5cec5 --- /dev/null +++ b/java/src/com/jacob/com/ROT.java @@ -0,0 +1,279 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.WeakHashMap; + +/** + * The Running Object Table (ROT) maps each thread to a collection of all the + * JacobObjects that were created in that thread. It always operates on the + * current thread so all the methods are static and they implicitly get the + * current thread. + *

+ * The clearObjects method is used to release all the COM objects created by + * Jacob in the current thread prior to uninitializing COM for that thread. + *

+ * Prior to 1.9, manual garbage collection was the only option in Jacob, but + * from 1.9 onward, setting the com.jacob.autogc system property allows the + * objects referenced by the ROT to be automatically GCed. Automatic GC may be + * preferable in systems with heavy event callbacks. + *

+ * Is [ 1116101 ] jacob-msg 0284 relevant??? + */ +public abstract class ROT { + /** + * Manual garbage collection was the only option pre 1.9 Can staticly cache + * the results because only one value and we don't let it change during a + * run + */ + protected static final boolean USE_AUTOMATIC_GARBAGE_COLLECTION = "true" + .equalsIgnoreCase(System.getProperty("com.jacob.autogc")); + + /** + * If the code is ran from an applet that is called from javascript the Java + * Plugin does not give full permissions to the code and thus System + * properties cannot be accessed. They can be accessed at class + * initialization time. + * + * The default behavior is to include all classes in the ROT, setting a + * boolean here to indicate this prevents a call to System.getProperty as + * part of the general call flow. + */ + protected static final Boolean INCLUDE_ALL_CLASSES_IN_ROT = Boolean + .valueOf(System.getProperty("com.jacob.includeAllClassesInROT", + "true")); + + /** + * Suffix added to class name to make up property name that determines if + * this object should be stored in the ROT. This 1.13 "feature" makes it + * possible to cause VariantViaEvent objects to not be added to the ROT in + * event callbacks. + *

+ * We don't have a static for the actual property because there is a + * different property for each class that may make use of this feature. + */ + protected static String PUT_IN_ROT_SUFFIX = ".PutInROT"; + + /** + * A hash table where each element is another HashMap that represents a + * thread. Each thread HashMap contains the com objects created in that + * thread + */ + private static HashMap> rot = new HashMap>(); + + /** + * adds a new thread storage area to rot + * + * @return Map corresponding to the thread that this call was made in + */ + protected synchronized static Map addThread() { + // should use the id here instead of the name because the name can be + // changed + String t_name = Thread.currentThread().getName(); + if (rot.containsKey(t_name)) { + // nothing to do + } else { + Map tab = null; + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: Automatic GC flag == " + + USE_AUTOMATIC_GARBAGE_COLLECTION); + } + if (!USE_AUTOMATIC_GARBAGE_COLLECTION) { + tab = new HashMap(); + } else { + tab = new WeakHashMap(); + } + rot.put(t_name, tab); + } + return getThreadObjects(false); + } + + /** + * Returns the pool for this thread if it exists. can create a new one if + * you wish by passing in TRUE + * + * @param createIfDoesNotExist + * @return Map the collection that holds the objects created in the current + * thread + */ + protected synchronized static Map getThreadObjects( + boolean createIfDoesNotExist) { + String t_name = Thread.currentThread().getName(); + if (!rot.containsKey(t_name) && createIfDoesNotExist) { + addThread(); + } + return rot.get(t_name); + } + + /** + * Iterates across all of the entries in the Hashmap in the rot that + * corresponds to this thread. This calls safeRelease() on each entry and + * then clears the map when done and removes it from the rot. All traces of + * this thread's objects will disappear. This is called by COMThread in the + * tear down and provides a synchronous way of releasing memory + */ + protected static void clearObjects() { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + rot.keySet().size() + + " thread tables exist"); + } + + Map tab = getThreadObjects(false); + if (tab != null) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: " + tab.keySet().size() + + " objects to clear in this thread's ROT "); + } + // walk the values + Iterator it = tab.keySet().iterator(); + while (it.hasNext()) { + JacobObject o = it.next(); + if (o != null + // can't use this cause creates a Variant if calling SafeAray + // and we get an exception modifying the collection while + // iterating + // && o.toString() != null + ) { + if (JacobObject.isDebugEnabled()) { + if (o instanceof SafeArray) { + // SafeArray create more objects when calling + // toString() + // which causes a concurrent modification exception + // in HashMap + JacobObject.debug("ROT: removing " + + o.getClass().getName()); + } else { + // Variant toString() is probably always bad in here + JacobObject.debug("ROT: removing " + o.hashCode() + + "->" + o.getClass().getName()); + } + } + o.safeRelease(); + } + } + // empty the collection + tab.clear(); + // remove the collection from rot + ROT.removeThread(); + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: thread table cleared and removed"); + } + } else { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: nothing to clear!"); + } + } + } + + /** + * Removes the map from the rot that is associated with the current thread. + */ + private synchronized static void removeThread() { + // should this see if it exists first? + rot.remove(Thread.currentThread().getName()); + } + + /** + * @deprecated the java model leave the responsibility of clearing up + * objects to the Garbage Collector. Our programming model + * should not require that the user specifically remove object + * from the thread.
+ * This will remove an object from the ROT
+ * This does not need to be synchronized because only the rot + * modification related methods need to synchronized. Each + * individual map is only modified in a single thread. + * @param o + */ + @Deprecated + protected static void removeObject(JacobObject o) { + Map tab = ROT.getThreadObjects(false); + if (tab != null) { + tab.remove(o); + } + o.safeRelease(); + } + + /** + * Adds an object to the HashMap for the current thread.
+ *

+ * This method does not need to be threaded because the only concurrent + * modification risk is on the hash map that contains all of the thread + * related hash maps. The individual thread related maps are only used on a + * per thread basis so there isn't a locking issue. + *

+ * In addition, this method cannot be threaded because it calls + * ComThread.InitMTA. The ComThread object has some methods that call ROT so + * we could end up deadlocked. This method should be safe without the + * synchronization because the ROT works on per thread basis and the methods + * that add threads and remove thread related entries are all synchronized + * + * + * @param o + */ + protected static void addObject(JacobObject o) { + String shouldIncludeClassInROT = "true"; + // only call System.getProperty if we are not including all classes in + // the ROT. This lets us run with standard Jacob behavior in Applets + // without the security exception raised by System.getProperty in the + // flow + if (!ROT.INCLUDE_ALL_CLASSES_IN_ROT) { + shouldIncludeClassInROT = System.getProperty(o.getClass().getName() + + PUT_IN_ROT_SUFFIX, "true"); + } + if (shouldIncludeClassInROT.equalsIgnoreCase("false")) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("JacobObject: New instance of " + + o.getClass().getName() + " not added to ROT"); + } + } else { + // first see if we have a table for this thread + Map tab = getThreadObjects(false); + if (tab == null) { + // this thread has not been initialized as a COM thread + // so make it part of MTA for backwards compatibility + ComThread.InitMTA(false); + // don't really need the "true" because the InitMTA will have + // called back to the ROT to create a table for this thread + tab = getThreadObjects(true); + } + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("ROT: adding " + o + "->" + + o.getClass().getName() + + " table size prior to addition:" + tab.size()); + } + // add the object to the table that is specific to this thread + if (tab != null) { + tab.put(o, null); + } + } + } + + /** + * ROT can't be a subclass of JacobObject because of the way ROT pools are + * managed so we force a DLL load here by referencing JacobObject + */ + static { + LibraryLoader.loadJacobLibrary(); + } + +} diff --git a/java/src/com/jacob/com/STA.java b/java/src/com/jacob/com/STA.java new file mode 100644 index 0000000..a8e29d7 --- /dev/null +++ b/java/src/com/jacob/com/STA.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * A class that implements a Single Threaded Apartment. Users will subclass this + * and override OnInit() and OnQuit() where they will create and destroy a COM + * component that wants to run in an STA other than the main STA. + */ +public class STA extends Thread { + /** + * referenced by STA.cpp + */ + public int threadID; + + /** + * constructor for STA + */ + public STA() { + start(); // start the thread + } + + /* + * (non-Javadoc) + * + * @see java.lang.Thread#run() + */ + public void run() { + // init COM + ComThread.InitSTA(); + if (OnInit()) { + // this call blocks in the win32 message loop + // until quitMessagePump is called + doMessagePump(); + } + OnQuit(); + // uninit COM + ComThread.Release(); + } + + /** + * Override this method to create and initialize any COM component that you + * want to run in this thread. If anything fails, return false to terminate + * the thread. + * + * @return always returns true + */ + public boolean OnInit() { + return true; + } + + /** + * Override this method to destroy any resource before the thread exits and + * COM in uninitialized + */ + public void OnQuit() { + // there is nothing to see here + } + + /** + * calls quitMessagePump + */ + public void quit() { + quitMessagePump(); + } + + /** + * run a message pump for the main STA + */ + public native void doMessagePump(); + + /** + * quit message pump for the main STA + */ + public native void quitMessagePump(); + + /** + * STA isn't a subclass of JacobObject so a reference to it doesn't load the + * DLL without this + */ + static { + LibraryLoader.loadJacobLibrary(); + } +} \ No newline at end of file diff --git a/java/src/com/jacob/com/SafeArray.java b/java/src/com/jacob/com/SafeArray.java new file mode 100644 index 0000000..8b14b3b --- /dev/null +++ b/java/src/com/jacob/com/SafeArray.java @@ -0,0 +1,1172 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * This creates an array wrapper around Variant objects(?). This supports 1, 2 + * and n-dimensional arrays. It exists in this form because n-dimensional arrays + * were a later addition. + */ +public class SafeArray extends JacobObject { + /** The super secret int that is actually the pointer to windows memory */ + int m_pV = 0; + + /** + * Constructor. Why does this exist? Yeah, someone will post on sourceforge + * about this comment. + * + */ + public SafeArray() { + } + + /** + * Constructor. + * + * @param vt + * type of array + */ + public SafeArray(int vt) { + init(vt, new int[] { 0 }, new int[] { -1 }); + } + + /** + * Constructor for a single dimensional array whose lower bounds is 0 and + * whose upper bound is specified as a parameter + * + * @param vt + * type of the array + * @param celems + * length of the array + */ + public SafeArray(int vt, int celems) { + init(vt, new int[] { 0 }, new int[] { celems }); + } + + /** + * Creates a two dimensional SafeArray whose base indexes are 0. + * + * @param vt + * Type of the array + * @param celems1 + * length of the array in first dimension + * @param celems2 + * length of the array in second dimension + */ + public SafeArray(int vt, int celems1, int celems2) { + init(vt, new int[] { 0, 0 }, new int[] { celems1, celems2 }); + } + + /** + * Constructor with support for N-dimensional array support + *

+ * You create an N-D SafeArray by: SafeArray sa = new + * SafeArray(Variant.VariantVariant, new int[] {0,0,0,0}, new int[] + * {4,4,4,4}); Where the 1st array is lower bounds and 2nd has the lengths + * of each dimension * + * + * @param vt + * @param lbounds + * @param celems + */ + public SafeArray(int vt, int lbounds[], int celems[]) { + init(vt, lbounds, celems); + } + + /** + * convert a string to a VT_UI1 array + * + * @param s + * source string + */ + public SafeArray(String s) { + char[] ca = s.toCharArray(); + init(Variant.VariantByte, new int[] { 0 }, new int[] { ca.length }); + fromCharArray(ca); + } + + /** + * convert a VT_UI1 array to string + * + * @return variant byte as a string + */ + public String asString() { + if (getvt() != Variant.VariantByte) { + return null; + } + char ja[] = toCharArray(); + return new String(ja); + } + + public native Object clone(); + + /** + * now private so only this object can access. Was: call this to explicitly + * release the com object before gc + * + */ + private native void destroy(); + + /** + * {@inheritDoc} + */ + protected void finalize() { + safeRelease(); + } + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromBooleanArray(boolean ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromByteArray(byte ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromCharArray(char ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromDoubleArray(double ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromFloatArray(float ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromIntArray(int ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromLongArray(long ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromShortArray(short ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromStringArray(String ja[]); + + /** + * populate the safe array from the passed in array of data + * + * @param ja + */ + public native void fromVariantArray(Variant ja[]); + + /** + * boolean access + * + * @param sa_idx + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx); + + /** + * get boolean value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native boolean getBoolean(int indices[]); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @return boolean representation + */ + public native boolean getBoolean(int sa_idx1, int sa_idx2); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @return byte representaton + */ + public native byte getByte(int sa_idx); + + /** + * get byte value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native byte getByte(int indices[]); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @return byte representation + */ + public native byte getByte(int sa_idx1, int sa_idx2); + + /** + * Fills byte array from contents of this array + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @return single character rpeesentation + */ + public native char getChar(int sa_idx); + + /** + * get char value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native char getChar(int indices[]); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @return single character representation + */ + public native char getChar(int sa_idx1, int sa_idx2); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @return double stored in array + */ + public native double getDouble(int sa_idx); + + /** + * get double value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native double getDouble(int indices[]); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @return double stored in array + */ + public native double getDouble(int sa_idx1, int sa_idx2); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * @return the size of each element? + */ + public native int getElemSize(); + + /** + * @return The ??features of the array? + */ + public native int getFeatures(); + + /** + * float access + * + * @param sa_idx + * @return float held in array at location + */ + public native float getFloat(int sa_idx); + + /** + * get float value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native float getFloat(int indices[]); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @return float held in array at location + */ + public native float getFloat(int sa_idx1, int sa_idx2); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return int stored in array + */ + public native int getInt(int sa_idx); + + /** + * get int value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native int getInt(int indices[]); + + /** + * get int from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return int stored in array + */ + public native int getInt(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of ints from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the ints + * @param ja_start + * the start point in the java int array to start filling + */ + public native void getInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * get int from an single dimensional array + * + * @param sa_idx + * array index + * @return long stored in array + */ + public native long getLong(int sa_idx); + + /** + * get long value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native long getLong(int indices[]); + + /** + * get long from 2 dimensional array + * + * @param sa_idx1 + * array index first dimension + * @param sa_idx2 + * array index of second dimension + * @return long stored in array + */ + public native long getLong(int sa_idx1, int sa_idx2); + + /** + * retrieves a group of longs from a single dimensional array + * + * @param sa_idx + * the index in the array to start the get + * @param nelems + * number of elements to retrieve + * @param ja + * the structure to be filled with the longs + * @param ja_start + * the start point in the java longs array to start filling + */ + public native void getLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * @return The lower bounds of the array? + */ + public native int getLBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The lower bounds of the array? + */ + public native int getLBound(int dim); + + /** + * @return The number of dimensions in this array + */ + public native int getNumDim(); + + /** + * not implemented. + * + * @return 0 + */ + public int getNumLocks() { + return 0; + } + + /** + * short access + * + * @param sa_idx + * @return short stored in array + */ + public native short getShort(int sa_idx); + + /** + * get short value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native short getShort(int indices[]); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @return short stored in array + */ + public native short getShort(int sa_idx1, int sa_idx2); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * string access + * + * @param sa_idx + * @return String stored in array + * + */ + public native String getString(int sa_idx); + + /** + * get String value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native String getString(int indices[]); + + /** + * string access + * + * @param sa_idx1 + * @param sa_idx2 + * @return String stored in array + */ + public native String getString(int sa_idx1, int sa_idx2); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * @return The upper bounds of the array? + */ + public native int getUBound(); + + /** + * @param dim + * the dimension we are checking in a multidimensional array + * @return The upper bounds of the array? + */ + public native int getUBound(int dim); + + /** + * variant access + * + * @param sa_idx + * @return Variant held in location in the array? + */ + public native Variant getVariant(int sa_idx); + + /** + * get Variant value from N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @return the value at the specified location + */ + public native Variant getVariant(int indices[]); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @return Variant held in a location in the array? + */ + public native Variant getVariant(int sa_idx1, int sa_idx2); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void getVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * @return the Variant type + */ + public native int getvt(); + + protected native void init(int vt, int lbounds[], int celems[]); + + /** + * Does anyone want to document this? + * + * @param sa + */ + public native void reinit(SafeArray sa); + + /** + * Does anyone want to document this? + * + * @param vt + * the variant type? + */ + public native void reinterpretType(int vt); + + /** + * {@inheritDoc} + */ + public void safeRelease() { + super.safeRelease(); + if (m_pV != 0) { + destroy(); + m_pV = 0; + } else { + // looks like a double release + if (isDebugEnabled()) { + debug(this.getClass().getName() + ":" + this.hashCode() + + " double release"); + } + } + } + + /** + * boolean access + * + * @param sa_idx + * @param c + */ + public native void setBoolean(int sa_idx, boolean c); + + /** + * set boolean value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setBoolean(int indices[], boolean c); + + /** + * boolean access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setBoolean(int sa_idx1, int sa_idx2, boolean c); + + /** + * boolean access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBooleans(int sa_idx, int nelems, boolean ja[], + int ja_start); + + /** + * byte access + * + * @param sa_idx + * @param c + */ + public native void setByte(int sa_idx, byte c); + + /** + * set byte value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setByte(int indices[], byte c); + + /** + * byte access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setByte(int sa_idx1, int sa_idx2, byte c); + + /** + * fills array with passed in bytes + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setBytes(int sa_idx, int nelems, byte ja[], int ja_start); + + /** + * char access + * + * @param sa_idx + * @param c + */ + public native void setChar(int sa_idx, char c); + + /** + * set char value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setChar(int indices[], char c); + + /** + * char access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setChar(int sa_idx1, int sa_idx2, char c); + + /** + * char access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setChars(int sa_idx, int nelems, char ja[], int ja_start); + + /** + * double access + * + * @param sa_idx + * @param c + */ + public native void setDouble(int sa_idx, double c); + + /** + * set double value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setDouble(int indices[], double c); + + /** + * double access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setDouble(int sa_idx1, int sa_idx2, double c); + + /** + * double access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setDoubles(int sa_idx, int nelems, double ja[], + int ja_start); + + /** + * float access + * + * @param sa_idx + * @param c + */ + public native void setFloat(int sa_idx, float c); + + /** + * set float value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setFloat(int indices[], float c); + + /** + * float access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setFloat(int sa_idx1, int sa_idx2, float c); + + /** + * float access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setFloats(int sa_idx, int nelems, float ja[], + int ja_start); + + /** + * sets the int value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setInt(int sa_idx, int c); + + /** + * set int value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setInt(int indices[], int c); + + /** + * sets the int value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setInt(int sa_idx1, int sa_idx2, int c); + + /** + * sets a group of ints into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new int values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setInts(int sa_idx, int nelems, int ja[], int ja_start); + + /** + * sets the long value of an element in a single dimensional array + * + * @param sa_idx + * index into the array + * @param c + * the value to be set + */ + public native void setLong(int sa_idx, long c); + + /** + * set long value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setLong(int indices[], long c); + + /** + * sets the long value of a 2 dimensional array + * + * @param sa_idx1 + * index on the first dimension + * @param sa_idx2 + * index on the second dimension + * @param c + * the value to be set + */ + public native void setLong(int sa_idx1, int sa_idx2, long c); + + /** + * sets a group of longs into a single dimensional array + * + * @param sa_idx + * the index of the start of the array to put into + * @param nelems + * number of elements to be copied + * @param ja + * the new long values to be put into the array + * @param ja_start + * the start index in the array that we are copying into + * SafeArray + */ + public native void setLongs(int sa_idx, int nelems, long ja[], int ja_start); + + /** + * short access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setShort(int sa_idx1, int sa_idx2, short c); + + /** + * short access + * + * @param sa_idx + * @param c + */ + public native void setShort(int sa_idx, short c); + + /** + * set short value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setShort(int indices[], short c); + + /** + * short access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setShorts(int sa_idx, int nelems, short ja[], + int ja_start); + + /** + * puts a string into an element in a two dimensional array. + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setString(int sa_idx1, int sa_idx2, String c); + + /* + * ================================================================ The + * beginning of N-dimensional array support + * ================================================================ + */ + + /** + * puts a string into an element in a single dimensional safe array + * + * @param sa_idx + * @param c + */ + public native void setString(int sa_idx, String c); + + /** + * set Stringvalue in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param c + */ + public native void setString(int indices[], String c); + + /** + * string access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setStrings(int sa_idx, int nelems, String ja[], + int ja_start); + + /** + * variant access + * + * @param sa_idx1 + * @param sa_idx2 + * @param c + */ + public native void setVariant(int sa_idx1, int sa_idx2, Variant c); + + /** + * variant access + * + * @param sa_idx + * @param c + */ + public native void setVariant(int sa_idx, Variant c); + + /** + * set Variant value in N-dimensional array + * + * @param indices - + * length must equal Dimension of SafeArray + * @param v + */ + public native void setVariant(int indices[], Variant v); + + /** + * variant access + * + * @param sa_idx + * @param nelems + * @param ja + * @param ja_start + */ + public native void setVariants(int sa_idx, int nelems, Variant ja[], + int ja_start); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return boolean[] array of booleans contained in this collection + */ + public native boolean[] toBooleanArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return byte[] byte array contained in this collection + */ + public native byte[] toByteArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return char[] character array contained in this collection + */ + public native char[] toCharArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return double[] double array contained in this collection + */ + public native double[] toDoubleArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return float[] array of float contained in this collection + */ + public native float[] toFloatArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return int[] int array contained in this collection + */ + public native int[] toIntArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return long[] long array contained in this collection + */ + public native long[] toLongArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return short[] short array contained in this collection + */ + public native short[] toShortArray(); + + /** + * Standard toString() Warning, this creates new Variant objects! + * + * @return String contents of variant + */ + public String toString() { + String s = ""; + int ndim = getNumDim(); + if (ndim == 1) { + int ldim = getLBound(); + int udim = getUBound(); + for (int i = ldim; i <= udim; i++) { + Variant v = getVariant(i); + + if (((v.getvt() & Variant.VariantTypeMask) | Variant.VariantArray) == v + .getvt()) { + return s + "[" + v.toSafeArray().toString() + "]"; + } else { + s += " " + v.toString(); + } + } + } else if (ndim == 2) { + int ldim1 = getLBound(1); + int udim1 = getUBound(1); + + int ldim2 = getLBound(2); + int udim2 = getUBound(2); + + for (int i = ldim1; i <= udim1; i++) { + for (int j = ldim2; j <= udim2; j++) { + Variant v = getVariant(i, j); + s += " " + v.toString(); + } + s += "\n"; + } + } + return s; + } + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return String[] String array contained in this collection + */ + public native String[] toStringArray(); + + /** + * Retrieves the data from the array cast to a Java data type + * + * @return Variant[] array of variants contained in this collection + */ + public native Variant[] toVariantArray(); + +} \ No newline at end of file diff --git a/java/src/com/jacob/com/Variant.java b/java/src/com/jacob/com/Variant.java new file mode 100644 index 0000000..9aafac3 --- /dev/null +++ b/java/src/com/jacob/com/Variant.java @@ -0,0 +1,2235 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Date; + +/** + * The multi-format data type used for all call backs and most communications + * between Java and COM. It provides a single class that can handle all data + * types. + *

+ * Just loading this class creates 3 variants that get added to the ROT + *

+ * PROPVARIANT introduces new types so eventually Variant will need to be + * upgraded to support PropVariant types. + * http://blogs.msdn.com/benkaras/archive/2006/09/13/749962.aspx + *

+ * This object no longer implements Serializable because serialization is broken + * (and has been since 2000/xp). The underlying marshalling/unmarshalling code + * is broken in the JNI layer. + */ +public class Variant extends JacobObject { + + /** + * Use this constant for optional parameters + */ + public final static com.jacob.com.Variant DEFAULT; + + /** + * Same than {@link #DEFAULT} + */ + public final static com.jacob.com.Variant VT_MISSING; + + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_TRUE = new com.jacob.com.Variant( + true); + + /** + * Use for true/false variant parameters + */ + public final static com.jacob.com.Variant VT_FALSE = new com.jacob.com.Variant( + false); + + /** variant's type is empty : equivalent to VB Nothing and VT_EMPTY */ + public static final short VariantEmpty = 0; + + /** variant's type is null : equivalent to VB Null and VT_NULL */ + public static final short VariantNull = 1; + + /** variant's type is short VT_I2 */ + public static final short VariantShort = 2; + + /** variant's type is int VT_I4, a Long in VC */ + public static final short VariantInt = 3; + + /** variant's type is float VT_R4 */ + public static final short VariantFloat = 4; + + /** variant's type is double VT_R8 */ + public static final short VariantDouble = 5; + + /** variant's type is currency VT_CY */ + public static final short VariantCurrency = 6; + + /** variant's type is date VT_DATE */ + public static final short VariantDate = 7; + + /** variant's type is string also known as VT_BSTR */ + public static final short VariantString = 8; + + /** variant's type is dispatch VT_DISPATCH */ + public static final short VariantDispatch = 9; + + /** variant's type is error VT_ERROR */ + public static final short VariantError = 10; + + /** variant's type is boolean VT_BOOL */ + public static final short VariantBoolean = 11; + + /** variant's type is variant it encapsulate another variant VT_VARIANT */ + public static final short VariantVariant = 12; + + /** variant's type is object VT_UNKNOWN */ + public static final short VariantObject = 13; + + /** variant's type is object VT_DECIMAL */ + public static final short VariantDecimal = 14; + + // VT_I1 = 16 + + /** variant's type is byte VT_UI1 */ + public static final short VariantByte = 17; + + // VT_UI2 = 18 + // VT_UI4 = 19 + + /** + * variant's type is 64 bit long integer VT_I8 - not yet implemented in + * Jacob because we have to decide what to do with Currency and because its + * only supported on XP and later. No win2k, NT or 2003 server. + */ + public static final short VariantLongInt = 20; + + // VT_UI8 = 21 + // VT_INT = 22 + // VT_UNIT = 23 + // VT_VOID = 24 + // VT_HRESULT = 25 + + /** + * This value is for reference only and is not to be used by any callers + */ + public static final short VariantPointer = 26; + + // VT_SAFEARRAY = 27 + // VT_CARRARY = 28 + // VT_USERDEFINED = 29 + + /** what is this? VT_TYPEMASK && VT_BSTR_BLOB 0xfff */ + public static final short VariantTypeMask = 4095; + + /** variant's type is array VT_ARRAY 0x2000 */ + public static final short VariantArray = 8192; + + /** variant's type is a reference (to IDispatch?) VT_BYREF 0x4000 */ + public static final short VariantByref = 16384; + + /* + * Do the run time definition of DEFAULT and MISSING. Have to use static + * block because of the way the initialization is done via two calls instead + * of just a constructor for this type. + */ + static { + com.jacob.com.Variant vtMissing = new com.jacob.com.Variant(); + vtMissing.putVariantNoParam(); + DEFAULT = vtMissing; + VT_MISSING = vtMissing; + } + + /** + * Pointer to MS struct. + */ + int m_pVariant = 0; + + /** + * public constructor, initializes and sets type to VariantEmpty + */ + public Variant() { + this(null, false); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(boolean in) { + this(new Boolean(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(byte in) { + this(new Byte(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(double in) { + this(new Double(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(float in) { + this(new Float(in)); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(int in) { + this(new Integer(in)); + }; + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(long in) { + this(new Long(in)); + } + + /** + * Convenience constructor that calls the main one with a byRef value of + * false + * + * @param in + * object to be made into variant + */ + public Variant(Object in) { + this(in, false); + } + + /** + * Constructor that accepts the data object and information about whether + * this is by reference or not. It calls the JavaVariantConverter to + * actually push the data into the newly created Variant. + * + * @param pValueObject + * The value object that will pushed down into windows memory. A + * null object sets this to "empty" + * @param fByRef + */ + public Variant(Object pValueObject, boolean fByRef) { + init(); + VariantUtilities.populateVariant(this, pValueObject, fByRef); + } + + /** + * Constructor that accepts a primitive rather than an object + * + * @param in + */ + public Variant(short in) { + this(new Short(in)); + } + + /** + * Cover for native method so we can cover it. + *

+ * This cannot convert an object to a byRef. It can convert from byref to + * not byref + * + * @param in + * type to convert this variant too + * @return Variant returns this same object so folks can change when + * replacing calls toXXX() with changeType().getXXX() + */ + public Variant changeType(short in) { + changeVariantType(in); + return this; + } + + /** + * Converts variant to the passed in type by converting the underlying + * windows variant structure. private so folks use public java method + * + * @param in + * the desired resulting type + */ + private native void changeVariantType(short in); + + /** + * this returns null + * + * @return ?? comment says null? + */ + @Override + public native Object clone(); + + /** + * @deprecated No longer used + * @return null ! + */ + @Deprecated + public native Variant cloneIndirect(); + + /* + * (non-Javadoc) + * + * @see java.lang.Object#finalize() + */ + @Override + protected void finalize() { + safeRelease(); + } + + /** + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public boolean getBoolean() { + if (this.getvt() == VariantBoolean) { + return getVariantBoolean(); + } else { + throw new IllegalStateException( + "getBoolean() only legal on Variants of type VariantBoolean, not " + + this.getvt()); + } + } + + /** + * public cover for native method + * + * @return the boolean from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type + */ + public boolean getBooleanRef() { + if ((this.getvt() & VariantTypeMask) == VariantBoolean + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantBooleanRef(); + } else { + throw new IllegalStateException( + "getBooleanRef() only legal on byRef Variants of type VariantBoolean, not " + + this.getvt()); + } + } + + /** + * + * @return returns the value as a boolean, throws an exception if its not. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByte() { + if (this.getvt() == VariantByte) { + return getVariantByte(); + } else { + throw new IllegalStateException( + "getByte() only legal on Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * public cover for native method + * + * @return the byte from a booleanRef + * @throws IllegalStateException + * if variant is not of the requested type + */ + public byte getByteRef() { + if ((this.getvt() & VariantTypeMask) == VariantByte + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantByteRef(); + } else { + throw new IllegalStateException( + "getByteRef() only legal on byRef Variants of type VariantByte, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrency() { + if (this.getvt() == VariantCurrency) { + return new Currency(getVariantCurrency()); + } else { + throw new IllegalStateException( + "getCurrency() only legal on Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * MS Currency objects are 64 bit fixed point numbers with 15 digits to the + * left and 4 to the right of the decimal place. + * + * @return returns the currency value as a long, throws exception if not a + * currency type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Currency getCurrencyRef() { + if ((this.getvt() & VariantTypeMask) == VariantCurrency + && (this.getvt() & VariantByref) == VariantByref) { + return new Currency(getVariantCurrencyRef()); + } else { + throw new IllegalStateException( + "getCurrencyRef() only legal on byRef Variants of type VariantCurrency, not " + + this.getvt()); + } + } + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDate() { + if (this.getvt() == VariantDate) { + return getVariantDate(); + } else { + throw new IllegalStateException( + "getDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * + * @return returns the date value as a double, throws exception if not a + * date type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDateRef() { + if ((this.getvt() & VariantTypeMask) == VariantDate + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDateRef(); + } else { + throw new IllegalStateException( + "getDateRef() only legal on byRef Variants of type VariantDate, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimal() { + if (this.getvt() == VariantDecimal) { + return (BigDecimal) (getVariantDec()); + } else { + throw new IllegalStateException( + "getDecimal() only legal on Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * return the BigDecimal value held in this variant (fails on other types) + * + * @return BigDecimal + * @throws IllegalStateException + * if variant is not of the requested type + */ + public BigDecimal getDecimalRef() { + if ((this.getvt() & VariantTypeMask) == VariantDecimal + && (this.getvt() & VariantByref) == VariantByref) { + return (BigDecimal) (getVariantDecRef()); + } else { + throw new IllegalStateException( + "getDecimalRef() only legal on byRef Variants of type VariantDecimal, not " + + this.getvt()); + } + } + + /** + * cover for {@link #toDispatch()} This method now matches other getXXX() + * methods. It throws an IllegalStateException if the object is not of type + * VariantDispatch + * + * @return this object as a dispatch + * @throws IllegalStateException + * if wrong variant type + */ + public Dispatch getDispatch() { + if (this.getvt() == VariantDispatch) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatch() only legal on Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * Dispatch and dispatchRef are treated the same This is just a cover for + * toDispatch() with a flag check + * + * @return the results of toDispatch() + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Dispatch getDispatchRef() { + if ((this.getvt() & VariantTypeMask) == VariantDispatch + && (this.getvt() & VariantByref) == VariantByref) { + return toDispatch(); + } else { + throw new IllegalStateException( + "getDispatchRef() only legal on byRef Variants of type VariantDispatch, not " + + this.getvt()); + } + } + + /** + * @return double return the double value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDouble() { + if (this.getvt() == VariantDouble) { + return getVariantDouble(); + } else { + throw new IllegalStateException( + "getDouble() only legal on Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * + * @return returns the double value, throws exception if not a Double type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public double getDoubleRef() { + if ((this.getvt() & VariantTypeMask) == VariantDouble + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantDoubleRef(); + } else { + throw new IllegalStateException( + "getDoubleRef() only legal on byRef Variants of type VariantDouble, not " + + this.getvt()); + } + } + + /** + * Pointless method that was put here so that putEmpty() has a get method. + * This would have returned null if the value was VT_EMPTY or if it wasn't + * so it would have always returned the same value. + * + * @deprecated method never did anything + */ + @Deprecated + public void getEmpty() { + } + + /** + * @return double return the error value held in this variant (fails on + * other types?) + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getError() { + if (this.getvt() == VariantError) { + return getVariantError(); + } else { + throw new IllegalStateException( + "getError() only legal on Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * + * @return returns the error value as an int, throws exception if not a + * Error type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getErrorRef() { + if ((this.getvt() & VariantTypeMask) == VariantError + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantErrorRef(); + } else { + throw new IllegalStateException( + "getErrorRef() only legal on byRef Variants of type VariantError, not " + + this.getvt()); + } + } + + /** + * @return returns the value as a float if the type is of type float + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloat() { + if (this.getvt() == VariantFloat) { + return getVariantFloat(); + } else { + throw new IllegalStateException( + "getFloat() only legal on Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * + * @return returns the float value, throws exception if not a Float type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public float getFloatRef() { + if ((this.getvt() & VariantTypeMask) == VariantFloat + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantFloatRef(); + } else { + throw new IllegalStateException( + "getFloatRef() only legal on byRef Variants of type VariantFloat, not " + + this.getvt()); + } + } + + /** + * return the int value held in this variant if it is an int or a short. + * Throws for other types. + * + * @return int contents of the windows memory + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getInt() { + if (this.getvt() == VariantInt) { + return getVariantInt(); + } else if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getInt() only legal on Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public int getIntRef() { + if ((this.getvt() & VariantTypeMask) == VariantInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantIntRef(); + } else { + throw new IllegalStateException( + "getIntRef() only legal on byRef Variants of type VariantInt, not " + + this.getvt()); + } + } + + /** + * returns the windows time contained in this Variant to a Java Date. should + * return null if this is not a date Variant SF 959382 + * + * @return java.util.Date returns the date if this is a VariantDate != 0, + * null if it is a VariantDate == 0 and throws an + * IllegalStateException if this isn't a date. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public Date getJavaDate() { + Date returnDate = null; + if (getvt() == VariantDate) { + double windowsDate = getDate(); + if (windowsDate != 0) { + returnDate = DateUtilities.convertWindowsTimeToDate(getDate()); + } + } else { + throw new IllegalStateException( + "getJavaDate() only legal on Variants of type VariantDate, not " + + this.getvt()); + } + return returnDate; + } + + /** + * returns the windows time contained in this Variant to a Java Date should + * return null if this is not a date reference Variant SF 959382 + * + * @return java.util.Date + */ + public Date getJavaDateRef() { + double windowsDate = getDateRef(); + if (windowsDate == 0) { + return null; + } else { + return DateUtilities.convertWindowsTimeToDate(windowsDate); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a Long + * type.. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLong() { + if (this.getvt() == VariantLongInt) { + return getVariantLong(); + } else { + throw new IllegalStateException( + "getLong() only legal on Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * 64 bit Longs only available on x64. 64 bit long support added 1.14 + * + * @return returns the value as a long, throws exception if not a long type + * @throws IllegalStateException + * if variant is not of the requested type + */ + public long getLongRef() { + if ((this.getvt() & VariantTypeMask) == VariantLongInt + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantLongRef(); + } else { + throw new IllegalStateException( + "getLongRef() only legal on byRef Variants of type VariantLongInt, not " + + this.getvt()); + } + } + + /** + * This method would have returned null if the type was VT_NULL. But because + * we return null if the data is not of the right type, this method should + * have always returned null + * + * @deprecated method never did anything + */ + @Deprecated + public void getNull() { + } + + /** + * return the int value held in this variant (fails on other types?) + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShort() { + if (this.getvt() == VariantShort) { + return getVariantShort(); + } else { + throw new IllegalStateException( + "getShort() only legal on Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * get the content of this variant as an int + * + * @return int + * @throws IllegalStateException + * if variant is not of the requested type + */ + public short getShortRef() { + if ((this.getvt() & VariantTypeMask) == VariantShort + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantShortRef(); + } else { + throw new IllegalStateException( + "getShortRef() only legal on byRef Variants of type VariantShort, not " + + this.getvt()); + } + } + + /** + * + * @return string contents of the variant. + * @throws IllegalStateException + * if this variant is not of type String + */ + public String getString() { + if (getvt() == Variant.VariantString) { + return getVariantString(); + } else { + throw new IllegalStateException( + "getString() only legal on Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * gets the content of the variant as a string ref + * + * @return String retrieved from the COM area. + * @throws IllegalStateException + * if variant is not of the requested type + */ + public String getStringRef() { + if ((this.getvt() & VariantTypeMask) == VariantString + && (this.getvt() & VariantByref) == VariantByref) { + return getVariantStringRef(); + } else { + throw new IllegalStateException( + "getStringRef() only legal on byRef Variants of type VariantString, not " + + this.getvt()); + } + } + + /** + * Used to get the value from a windows type of VT_VARIANT or a jacob + * Variant type of VariantVariant. Added 1.12 pre 6 - VT_VARIANT support is + * at an alpha level + * + * @return Object a java Object that represents the content of the enclosed + * Variant + */ + public Object getVariant() { + if ((this.getvt() & VariantTypeMask) == VariantVariant + && (this.getvt() & VariantByref) == VariantByref) { + if (JacobObject.isDebugEnabled()) { + JacobObject.debug("About to call getVariantVariant()"); + } + Variant enclosedVariant = new Variant(); + int enclosedVariantMemory = getVariantVariant(); + enclosedVariant.m_pVariant = enclosedVariantMemory; + Object enclosedVariantAsJava = enclosedVariant.toJavaObject(); + // zero out the reference to the underlying windows memory so that + // it is still only owned in one place by one java object + // (this object of type VariantVariant) + // enclosedVariant.putEmpty(); // don't know if this would have had + // side effects + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); + } + enclosedVariant.m_pVariant = 0; + return enclosedVariantAsJava; + } else { + throw new IllegalStateException( + "getVariant() only legal on Variants of type VariantVariant, not " + + this.getvt()); + } + } + + /** + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @return the Variant Array that represents the data in the Variant + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] getVariantArrayRef() { + throw new NotImplementedException("Not implemented"); + } + + /** + * + * @return the value in this Variant as a boolean, null if not a boolean + */ + private native boolean getVariantBoolean(); + + private native boolean getVariantBooleanRef(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByte(); + + /** + * @return the value in this Variant as a byte, null if not a byte + */ + private native byte getVariantByteRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrency(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantCurrencyRef(); + + /** + * @return double return the date (as a double) value held in this variant + * (fails on other types?) + */ + private native double getVariantDate(); + + /** + * get the content of this variant as a double representing a date + * + * @return double + */ + private native double getVariantDateRef(); + + /** + * @return the value in this Variant as a decimal, null if not a decimal + */ + private native Object getVariantDec(); + + /** + * @return the value in this Variant (byref) as a decimal, null if not a + * decimal + */ + private native Object getVariantDecRef(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDouble(); + + /** + * @return double get the content of this variant as a double + */ + private native double getVariantDoubleRef(); + + private native int getVariantError(); + + private native int getVariantErrorRef(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloat(); + + /** + * @return returns the value as a float if the type is of type float + */ + private native float getVariantFloatRef(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantInt(); + + /** + * @return the int value held in this variant (fails on other types?) + */ + private native int getVariantIntRef(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLong(); + + /** + * @return the value in this Variant as a long, null if not a long + */ + private native long getVariantLongRef(); + + /** + * get the content of this variant as a short + * + * @return short + */ + private native short getVariantShort(); + + /** + * @return short the content of this variant as a short + */ + private native short getVariantShortRef(); + + /** + * Native method that actually extracts a string value from the variant + * + * @return + */ + private native String getVariantString(); + + /** + * @return String the content of this variant as a string + */ + private native String getVariantStringRef(); + + /** + * Returns the variant type via a native method call + * + * @return short one of the VT_xx types + */ + private native short getVariantType(); + + /** + * Returns the variant type via a native method call. Added 1.12 pre 6 - + * VT_VARIANT support is at an alpha level + * + * @return Variant one of the VT_Variant types + */ + private native int getVariantVariant(); + + /** + * Reports the type of the underlying Variant object + * + * @return returns the variant type as a short, one of the Variantxxx values + * defined as statics in this class. returns VariantNull if not + * initialized + * @throws IllegalStateException + * if there is no underlying windows data structure + */ + public short getvt() { + if (m_pVariant != 0) { + return getVariantType(); + } else { + throw new IllegalStateException("uninitialized Variant"); + } + } + + /** + * initializes the COM Variant and puts its reference in this instance + */ + protected native void init(); + + /** + * + * @return returns true if the variant is considered null + * @throws IllegalStateException + * if there is no underlying windows memory + */ + public boolean isNull() { + getvt(); + return isVariantConsideredNull(); + } + + /** + * is the variant null or empty or error or null dispatch + * + * @return true if it is null or false if not + */ + private native boolean isVariantConsideredNull(); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + * + * @deprecated replaced by putNoParam() + */ + @Deprecated + public void noParam() { + putNoParam(); + } + + /** + * returns true if the passed in Variant is a constant that should not be + * freed + * + * @param pVariant + * @return boolean that is true if Variant is a type of constant, VT_FALSE, + * VT_TRUE, VT_MISSING, DEFAULT + */ + protected boolean objectIsAConstant(Variant pVariant) { + if (pVariant == VT_FALSE || pVariant == VT_TRUE + || pVariant == VT_MISSING || pVariant == DEFAULT) { + return true; + } else { + return false; + } + + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + public void putBoolean(boolean in) { + // verify we aren't released yet + getvt(); + putVariantBoolean(in); + } + + /** + * pushes a boolean into the variant by ref and sets the type of the variant + * to boolean + * + * @param in + */ + public void putBooleanRef(boolean in) { + // verify we aren't released yet + getvt(); + putVariantBooleanRef(in); + } + + /** + * pushes a byte into the varaint and sets the type + * + * @param in + */ + public void putByte(byte in) { + // verify we aren't released yet + getvt(); + putVariantByte(in); + }; + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putByteArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * pushes a byte into the variant by ref and sets the type + * + * @param in + */ + public void putByteRef(byte in) { + // verify we aren't released yet + getvt(); + putVariantByteRef(in); + } + + /** + * @param in + * the object that would be wrapped by the Variant if this method + * was implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putCharArray(Object in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * Puts a value in as a currency and sets the variant type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object. + */ + public void putCurrency(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrency(in.longValue()); + } + + /** + * Pushes a long into the variant as currency and sets the type. MS Currency + * objects are 64 bit fixed point numbers with 15 digits to the left and 4 + * to the right of the decimal place. + * + * @param in + * the long that will be put into the 64 bit currency object + */ + public void putCurrencyRef(Currency in) { + // verify we aren't released yet + getvt(); + putVariantCurrencyRef(in.longValue()); + } + + /** + * converts a java date to a windows time and calls putDate(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDate(Date inDate) { + if (inDate == null) { + throw new IllegalArgumentException( + "Cannot put null in as windows date"); + // do nothing + } else { + putDate(DateUtilities.convertDateToWindowsTime(inDate)); + } + } + + /** + * puts a windows date double into the variant and sets the type + * + * @param in + */ + public void putDate(double in) { + // verify we aren't released yet + getvt(); + putVariantDate(in); + } + + /** + * converts a java date to a windows time and calls putDateRef(double) SF + * 959382 + * + * @param inDate + * a Java date to be converted + * @throws IllegalArgumentException + * if inDate = null + */ + public void putDateRef(Date inDate) { + if (inDate == null) { + throw new IllegalArgumentException( + "Cannot put null in as windows date"); + // do nothing + } else { + putDateRef(DateUtilities.convertDateToWindowsTime(inDate)); + } + } + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + public void putDateRef(double in) { + // verify we aren't released + getvt(); + putVariantDateRef(in); + } + + /** + * This actual does all the validating and massaging of the BigDecimalValues + * when converting them to MS Decimal types + * + * @param in + * number to be made into VT_DECIMAL + * @param byRef + * store by reference or not + * @param roundingBehavior + * one of the BigDecimal ROUND_xxx methods. Any method other than + * ROUND_UNECESSARY means that the value will be rounded to fit + */ + private void putDecimal(BigDecimal in, boolean byRef) { + // verify we aren't released + getvt(); + // first validate the min and max + VariantUtilities.validateDecimalMinMax(in); + BigInteger allWordBigInt; + allWordBigInt = in.unscaledValue(); + // Assume any required rounding has been done. + VariantUtilities.validateDecimalScaleAndBits(in); + // finally we can do what we actually came here to do + int sign = in.signum(); + // VT_DECIMAL always has positive value with just the sign + // flipped + if (in.signum() < 0) { + in = in.negate(); + } + // ugh, reusing allWordBigInt but now should always be positive + // and any round is applied + allWordBigInt = in.unscaledValue(); + byte scale = (byte) in.scale(); + int lowWord = allWordBigInt.intValue(); + BigInteger middleWordBigInt = allWordBigInt.shiftRight(32); + int middleWord = middleWordBigInt.intValue(); + BigInteger highWordBigInt = allWordBigInt.shiftRight(64); + int highWord = highWordBigInt.intValue(); + if (byRef) { + putVariantDecRef(sign, scale, lowWord, middleWord, highWord); + } else { + putVariantDec(sign, scale, lowWord, middleWord, highWord); + } + } + + /** + * EXPERIMENTAL 1.14 feature to support rounded decimals. + *

+ * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

+ * This default set method throws exceptions if precision or size is out of + * bounds + *

+ * There are 12 bytes available for the integer number. + *

+ * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimal(BigDecimal in) { + putDecimal(in, false); + } + + /** + * Set the value of this variant and set the type. This may throw exceptions + * more often than the caller expects because most callers don't manage the + * scale of their BigDecimal objects. + *

+ * This default set method throws exceptions if precision or size is out of + * bounds + *

+ * There are 12 bytes available for the integer number. + *

+ * There is 1 byte for the scale. + * + * @param in + * the BigDecimal that will be converted to VT_DECIMAL + * @throws IllegalArgumentException + * if the scale is > 28, the maximum for VT_DECIMAL or if there + * are more than 12 bytes worth the digits + */ + public void putDecimalRef(BigDecimal in) { + putDecimal(in, true); + } + + /** + * This acts a cover for putVariant Dispatch. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatch(Dispatch in) { + putVariantDispatch(in); + } + + /** + * Dispatch and dispatchRef are treated the same This is a cover for + * putVariantDispatch(). putDispatch and putDispatchRef are treated the same + * because no one has written the COM code for putDispatchRef. + * + * @param in + * the Dispatch we're putting down in the COM variant space. + */ + public void putDispatchRef(Dispatch in) { + putVariantDispatch(in); + } + + /** + * wraps this Variant around the passed in double. + * + * @param in + */ + public void putDouble(double in) { + // verify we aren't released yet + getvt(); + putVariantDouble(in); + } + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + public void putDoubleRef(double in) { + // verify we aren't released + getvt(); + putVariantDoubleRef(in); + } + + /** + * sets the type to VariantEmpty + * + */ + public void putEmpty() { + // verify we aren't released yet + getvt(); + putVariantEmpty(); + } + + /** + * puts an error code (I think) into the variant and sets the type + * + * @param in + */ + public void putError(int in) { + // verify we aren't released yet + getvt(); + putVariantError(in); + } + + /** + * pushes an error code into the variant by ref and sets the type + * + * @param in + */ + public void putErrorRef(int in) { + // verify we aren't released yet + getvt(); + putVariantErrorRef(in); + } + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + public void putFloat(float in) { + // verify we haven't been released yet + getvt(); + putVariantFloat(in); + } + + /** + * pushes a float into the variant and sets the type + * + * @param in + */ + public void putFloatRef(float in) { + // verify we aren't released yet + getvt(); + putVariantFloatRef(in); + } + + /** + * set the value of this variant and set the type + * + * @param in + */ + public void putInt(int in) { + // verify we aren't released yet + getvt(); + putVariantInt(in); + } + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + public void putIntRef(int in) { + // verify we aren't released + getvt(); + putVariantIntRef(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLong(long in) { + // verify we aren't released yet + getvt(); + putVariantLong(in); + } + + /** + * Puts a 64 bit Java Long into a 64 bit Variant Long. Only works on x64 + * systems otherwise throws an error. 64 bit long support added 1.14 + * + * @param in + * the long that will be put into the 64 bit Long object. + */ + public void putLongRef(long in) { + // verify we aren't released yet + getvt(); + putVariantLongRef(in); + } + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + public void putNoParam() { + // verify we aren't released yet + getvt(); + putVariantNoParam(); + } + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + public void putNothing() { + // verify we aren't released yet + getvt(); + putVariantNothing(); + } + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + public void putNull() { + // verify we aren't released yet + getvt(); + putVariantNull(); + } + + /** + * Puts an object into the Variant -- converts to Dispatch. Acts as a cover + * for putVariantDispatch(); This primarily exists to support jacobgen. This + * should be deprecated. + * + * @param in + * the object we are putting into the Variant, assumes a + * @see Variant#putDispatch(Dispatch) + * @deprecated should use putDispatch() + */ + @Deprecated + public void putObject(Object in) { + // this should verify in instanceof Dispatch + putVariantDispatch(in); + } + + /** + * Just a cover for putObject(). We shouldn't accept any old random object. + * This has been left in to support jacobgen. This should be deprecated. + * + * @param in + * @deprecated + */ + @Deprecated + public void putObjectRef(Object in) { + putObject(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArray(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArray(in); + } + + /** + * have no idea... + * + * @param in + */ + public void putSafeArrayRef(SafeArray in) { + // verify we haven't been released yet + getvt(); + putVariantSafeArrayRef(in); + } + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + public void putShort(short in) { + // verify we aren't released + getvt(); + putVariantShort(in); + } + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + public void putShortRef(short in) { + // verify we aren't released + getvt(); + putVariantShortRef(in); + } + + /** + * put a string into the variant and set its type + * + * @param in + */ + public void putString(String in) { + // verify we aren't released yet + getvt(); + putVariantString(in); + } + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + public void putStringRef(String in) { + // verify we aren't released + getvt(); + putVariantStringRef(in); + } + + /** + * Puts a variant into this variant making it type VT_VARIANT. Added 1.12 + * pre 6 + * + * @param objectToBeWrapped + * A object that is to be referenced by this variant. If + * objectToBeWrapped is already of type Variant, then it is used. + * If objectToBeWrapped is not Variant then + * new Variant(objectToBeWrapped) is called and the + * result is passed into the com layer + * @throws IllegalArgumentException + * if inVariant = null or if inVariant is a Varint + */ + public void putVariant(Object objectToBeWrapped) { + if (objectToBeWrapped == null) { + throw new IllegalArgumentException( + "Cannot put null in as a variant"); + } else if (objectToBeWrapped instanceof Variant) { + throw new IllegalArgumentException( + "Cannot putVariant() only accepts non jacob objects."); + } else { + Variant inVariant = new Variant(objectToBeWrapped); + putVariantVariant(inVariant); + // This could be done in Variant.cpp + if (JacobObject.isDebugEnabled()) { + JacobObject + .debug("Zeroing out enclosed Variant's ref to windows memory"); + } + inVariant.m_pVariant = 0; + } + } + + /** + * @deprecated superseded by SafeArray + * @param in + * doesn't matter because this method does nothing + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArray(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * @param in + * the thing that would be come an array if this method was + * implemented + * @deprecated superseded by SafeArray + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public void putVariantArrayRef(Variant[] in) { + throw new NotImplementedException("Not implemented"); + } + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBoolean(boolean in); + + /** + * puts a boolean into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantBooleanRef(boolean in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByte(byte in); + + /** + * puts a byte into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantByteRef(byte in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrency(long in); + + /** + * puts a Currency into the variant and sets it's type + * + * @param in + * the new value + */ + private native void putVariantCurrencyRef(long in); + + /** + * set the value of this variant + * + * @param in + */ + private native void putVariantDate(double in); + + /** + * set the content of this variant to a date (VT_DATE|VT_BYREF) + * + * @param in + */ + private native void putVariantDateRef(double in); + + /** + * private JNI method called by putDecimal + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDec(int signum, byte scale, int lo, int mid, + int hi); + + /** + * private JNI method called by putDecimalRef + * + * @param signum + * sign + * @param scale + * BigDecimal's scale + * @param lo + * low 32 bits + * @param mid + * middle 32 bits + * @param hi + * high 32 bits + */ + private native void putVariantDecRef(int signum, byte scale, int lo, + int mid, int hi); + + /** + * the JNI implementation for putDispatch() so that we can screen the + * incoming dispatches in putDispatch() before this is invoked + * + * @param in + * should be a dispatch object + */ + private native void putVariantDispatch(Object in); + + private native void putVariantDouble(double in); + + /** + * set the content of this variant to a double (VT_R8|VT_BYREF) + * + * @param in + */ + private native void putVariantDoubleRef(double in); + + /** + * Sets the type to VariantEmpty. No values needed + */ + private native void putVariantEmpty(); + + private native void putVariantError(int in); + + private native void putVariantErrorRef(int in); + + /** + * fills the Variant with a float and sets the type to float + * + * @param in + */ + private native void putVariantFloat(float in); + + private native void putVariantFloatRef(float in); + + /** + * set the value of this variant and set the type + * + * @param in + */ + private native void putVariantInt(int in); + + /** + * set the content of this variant to an int (VT_I4|VT_BYREF) + * + * @param in + */ + private native void putVariantIntRef(int in); + + private native void putVariantLong(long in); + + private native void putVariantLongRef(long in); + + /** + * sets the type to VT_ERROR and the error message to DISP_E_PARAMNOTFOIUND + */ + private native void putVariantNoParam(); + + /** + * Sets the type to VariantDispatch and sets the value to null Equivalent to + * VB's nothing + */ + private native void putVariantNothing(); + + /** + * Set this Variant's type to VT_NULL (the VB equivalent of NULL) + */ + private native void putVariantNull(); + + private native void putVariantSafeArray(SafeArray in); + + private native void putVariantSafeArrayRef(SafeArray in); + + /** + * set the content of this variant to a short (VT_I2) + * + * @param in + */ + private native void putVariantShort(short in); + + /** + * set the content of this variant to a short (VT_I2|VT_BYREF) + * + * @param in + */ + private native void putVariantShortRef(short in); + + private native void putVariantString(String in); + + /** + * set the content of this variant to a string (VT_BSTR|VT_BYREF) + * + * @param in + */ + private native void putVariantStringRef(String in); + + /** + * All VariantVariant type variants are BYREF. + * + * Set the content of this variant to a string (VT_VARIANT|VT_BYREF). + * + * Added 1.12 pre 6 - VT_VARIANT support is at an alpha level + * + * @param in + * variant to be wrapped + * + */ + private native void putVariantVariant(Variant in); + + /** + * now private so only this object can access was: call this to explicitly + * release the com object before gc + * + */ + private native void release(); + + /** + * This will release the "C" memory for the Variant unless this Variant is + * one of the constants in which case we don't want to release the memory. + *

+ * + * @see com.jacob.com.JacobObject#safeRelease() + */ + @Override + public void safeRelease() { + // The well known constants should not be released. + // Unfortunately this doesn't fix any other classes that are + // keeping constants around in their static ivars. + // those will still be busted. + // + // The only inconsistency here is that we leak + // when this class is unloaded because we won't + // free the memory even if the constants are being + // finalized. this is not a big deal at all. + // another way around this would be to create the constants + // in their own thread so that they would never be released + if (!objectIsAConstant(this)) { + super.safeRelease(); + if (m_pVariant != 0) { + release(); + m_pVariant = 0; + } else { + // looks like a double release + // this should almost always happen due to gc + // after someone has called ComThread.Release + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + " double release"); + // Throwable x = new Throwable(); + // x.printStackTrace(); + } + } + } else { + if (isDebugEnabled()) { + debug("Variant: " + this.hashCode() + + " don't want to release a constant"); + } + } + } + + /** + * this is supposed to cause the underlying variant object struct to be + * rebuilt from a previously serialized byte array. + * + * @param ba + */ + protected native void SerializationReadFromBytes(byte[] ba); + + /** + * this is supposed to create a byte array that represents the underlying + * variant object structure + */ + protected native byte[] SerializationWriteToBytes(); + + /** + * @deprecated should be replaced by changeType() followed by getBoolean() + * @return the value of this variant as boolean (after possible conversion) + */ + @Deprecated + public boolean toBoolean() { + changeType(Variant.VariantBoolean); + return getBoolean(); + } + + /** + * attempts to return the content of this variant as a double (after + * possible conversion) + * + * @deprecated should be replaced by changeType() followed by getByte() + * @return byte + */ + @Deprecated + public byte toByte() { + changeType(Variant.VariantByte); + return getByte(); + } + + /** + * @deprecated superseded by SafeArray + * @return nothing because this method is not implemented + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toByteArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated superseded by SafeArray + * @return never returns anything + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Object toCharArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * @deprecated should be replaced by changeType() followed by getCurrency + * @return the content of this variant as a long representing a monetary + * amount + */ + @Deprecated + public Currency toCurrency() { + changeType(Variant.VariantCurrency); + return getCurrency(); + } + + /** + * @deprecated should use changeType() followed by getDate() + * @return the value of this variant as a date (after possible conversion) + */ + @Deprecated + public double toDate() { + changeType(VariantDate); + return getDate(); + } + + /** + * @return the content of this variant as a Dispatch object (after possible + * conversion) + */ + public Dispatch toDispatch() { + // now make the native call + return toVariantDispatch(); + } + + /** + * @deprecated should call changeType() then getDouble() + * @return the content of this variant as a double (after possible + * conversion) + */ + @Deprecated + public double toDouble() { + changeType(Variant.VariantDouble); + return getDouble(); + } + + /** @return the value of this variant as an enumeration (java style) */ + public native EnumVariant toEnumVariant(); + + /** + * converts to an error type and returns the error + * + * @deprecated should use changeType() followed by getError() + * @return the error as an int (after conversion) + */ + @Deprecated + public int toError() { + changeType(Variant.VariantError); + return getError(); + } + + /** + * attempts to return the contents of this variant as a float (after + * possible conversion) + * + * @deprecated should use changeType() and getFloat() instead + * @return float + */ + @Deprecated + public float toFloat() { + changeType(Variant.VariantFloat); + return getFloat(); + } + + /** + * @deprecated should use changeType() followed by getInt() + * @return the value of this variant as an int (after possible conversion) + */ + @Deprecated + public int toInt() { + changeType(VariantInt); + return getInt(); + } + + /** + * Returns the windows time contained in this Variant as a Java Date + * converts to a date like many of the other toXXX() methods SF 959382. + *

+ * This method added 12/2005 for possible use by jacobgen instead of its + * conversion code + *

+ * This does not convert the data + * + * @deprecated callers should use getDate() + * @return java.util.Date version of this variant if it is a date, otherwise + * null + * + */ + @Deprecated + public Date toJavaDate() { + changeType(Variant.VariantDate); + return getJavaDate(); + } + + /** + * Convert a JACOB Variant value to a Java object (type conversions). + * provided in Sourceforge feature request 959381. See + * JavaVariantConverter..convertVariantTJavaObject(Variant) for more + * information. + * + * @return Corresponding Java object of the type matching the Variant type. + * @throws IllegalStateException + * if no underlying windows data structure + * @throws NotImplementedException + * if unsupported conversion is requested + * @throws JacobException + * if the calculated result was a JacobObject usually as a + * result of error + */ + public Object toJavaObject() throws JacobException { + return VariantUtilities.variantToObject(this); + } + + /** + * Acts a a cover for toDispatch. This primarily exists to support jacobgen. + * + * @deprecated this is a cover for toDispatch(); + * @return Object returned by toDispatch() + * @see Variant#toDispatch() instead + */ + @Deprecated + public Object toObject() { + return toDispatch(); + } + + /** + * By default toSafeArray makes a deep copy due to the fact that this + * Variant owns the embedded SafeArray and will destroy it when it gc's + * calls toSafeArray(true). + * + * @return the object converted to a SafeArray + */ + public SafeArray toSafeArray() { + // verify we haven't been released yet + getvt(); + return toSafeArray(true); + } + + /** + * This lets folk turn into a safe array without a deep copy. Should this + * API be public? + * + * @param deepCopy + * @return SafeArray constructed + */ + public SafeArray toSafeArray(boolean deepCopy) { + // verify we haven't been released yet + getvt(); + return toVariantSafeArray(deepCopy); + } + + /** + * I don't know what this is. Is it some legacy (pre 1.8) thing? + * + * @deprecated + * @return this object as a dispatch object by calling toDispatch() + */ + @Deprecated + public Object toScriptObject() { + return toDispatch(); + } + + /** + * attempts to return the contents of this Variant as a short (after + * possible conversion) + * + * @deprecated callers should use changeType() followed by getShort() + * @return short + */ + @Deprecated + public short toShort() { + this.changeType(Variant.VariantShort); + return getShort(); + } + + /** + * This method now correctly implements java toString() semantics Attempts + * to return the content of this variant as a string + *

    + *
  • "not initialized" if not initialized + *
  • "null" if VariantEmpty, + *
  • "null" if VariantError + *
  • "null" if VariantNull + *
  • the value if we know how to describe one of that type + *
  • three question marks if can't convert + * + * @return String value conversion, + * @throws IllegalStateException + * if there is no underlying windows data structure + */ + @Override + public String toString() { + try { + // see if we are in a legal state + getvt(); + } catch (IllegalStateException ise) { + return ""; + } + if (getvt() == VariantEmpty || getvt() == VariantError + || getvt() == VariantNull) { + return "null"; + } + if (getvt() == VariantString) { + return getString(); + } + try { + Object foo = toJavaObject(); + // rely on java objects to do the right thing + return foo.toString(); + } catch (NotImplementedException nie) { + // some types do not generate a good description yet + return "Description not available for type: " + getvt(); + } + } + + /** + * Exists to support jacobgen. This would be deprecated if it weren't for + * jacobgen + * + * @deprecated superseded by "this" + * @return this same object + */ + @Deprecated + public Variant toVariant() { + return this; + } + + /** + * @deprecated superseded by SafeArray + * @return nothing because this method is not implemented + * @throws com.jacob.com.NotImplementedException + */ + @Deprecated + public Variant[] toVariantArray() { + throw new NotImplementedException("Not implemented"); + } + + /** + * native method used by toDispatch() + * + * @return + */ + private native Dispatch toVariantDispatch(); + + private native SafeArray toVariantSafeArray(boolean deepCopy); + + /* + * ===================================================================== + * + * + * ===================================================================== + */ + + /** + * Clear the content of this variant + */ + public native void VariantClear(); + +} \ No newline at end of file diff --git a/java/src/com/jacob/com/VariantUtilities.java b/java/src/com/jacob/com/VariantUtilities.java new file mode 100644 index 0000000..ae384f0 --- /dev/null +++ b/java/src/com/jacob/com/VariantUtilities.java @@ -0,0 +1,502 @@ +/** + * + */ +package com.jacob.com; + +import java.lang.reflect.Array; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.MathContext; +import java.util.Date; + +/** + * A utility class used to convert between Java objects and Variants + */ +public final class VariantUtilities { + private VariantUtilities() { + // utility class with only static methods don't need constructors + } + + /** + * Populates a variant object from a java object. This method attempts to + * figure out the appropriate Variant type + * + * @param targetVariant + * @param pValueObject + * @param fByRef + */ + protected static void populateVariant(Variant targetVariant, + Object pValueObject, boolean fByRef) { + if (pValueObject == null) { + targetVariant.putEmpty(); + } else if (pValueObject instanceof Integer) { + if (fByRef) { + targetVariant.putIntRef(((Integer) pValueObject).intValue()); + } else { + targetVariant.putInt(((Integer) pValueObject).intValue()); + } + } else if (pValueObject instanceof Short) { + if (fByRef) { + targetVariant.putShortRef(((Short) pValueObject).shortValue()); + } else { + targetVariant.putShort(((Short) pValueObject).shortValue()); + } + } else if (pValueObject instanceof String) { + if (fByRef) { + targetVariant.putStringRef((String) pValueObject); + } else { + targetVariant.putString((String) pValueObject); + } + } else if (pValueObject instanceof Boolean) { + if (fByRef) { + targetVariant.putBooleanRef(((Boolean) pValueObject) + .booleanValue()); + } else { + targetVariant.putBoolean(((Boolean) pValueObject) + .booleanValue()); + } + } else if (pValueObject instanceof Double) { + if (fByRef) { + targetVariant.putDoubleRef(((Double) pValueObject) + .doubleValue()); + } else { + targetVariant.putDouble(((Double) pValueObject).doubleValue()); + } + } else if (pValueObject instanceof Float) { + if (fByRef) { + targetVariant.putFloatRef(((Float) pValueObject).floatValue()); + } else { + targetVariant.putFloat(((Float) pValueObject).floatValue()); + } + } else if (pValueObject instanceof BigDecimal) { + if (fByRef) { + targetVariant.putDecimalRef(((BigDecimal) pValueObject)); + } else { + targetVariant.putDecimal(((BigDecimal) pValueObject)); + } + } else if (pValueObject instanceof Byte) { + if (fByRef) { + targetVariant.putByteRef(((Byte) pValueObject).byteValue()); + } else { + targetVariant.putByte(((Byte) pValueObject).byteValue()); + } + } else if (pValueObject instanceof Date) { + if (fByRef) { + targetVariant.putDateRef((Date) pValueObject); + } else { + targetVariant.putDate((Date) pValueObject); + } + } else if (pValueObject instanceof Long) { + if (fByRef) { + targetVariant.putLongRef(((Long) pValueObject).longValue()); + } else { + targetVariant.putLong(((Long) pValueObject).longValue()); + } + } else if (pValueObject instanceof Currency) { + if (fByRef) { + targetVariant.putCurrencyRef(((Currency) pValueObject)); + } else { + targetVariant.putCurrency(((Currency) pValueObject)); + } + } else if (pValueObject instanceof SafeArray) { + if (fByRef) { + targetVariant.putSafeArrayRef((SafeArray) pValueObject); + } else { + targetVariant.putSafeArray((SafeArray) pValueObject); + } + } else if (pValueObject instanceof Dispatch) { + if (fByRef) { + targetVariant.putDispatchRef((Dispatch) pValueObject); + } else { + targetVariant.putDispatch((Dispatch) pValueObject); + } + } else if (pValueObject instanceof Variant) { + // newly added 1.12-pre6 to support VT_VARIANT + targetVariant.putVariant(pValueObject); + } else { + // sourceforge patch 2171967 + // used to rely on coercion but sometimes crashed VM + throw new NotImplementedException( + "populateVariant() not implemented for " + + pValueObject.getClass()); + } + } + + /** + * Map arguments based on msdn documentation. This method relies on the + * variant constructor except for arrays. + * + * @param objectToBeMadeIntoVariant + * @return Variant that represents the object + */ + protected static Variant objectToVariant(Object objectToBeMadeIntoVariant) { + if (objectToBeMadeIntoVariant == null) { + return new Variant(); + } else if (objectToBeMadeIntoVariant instanceof Variant) { + // if a variant was passed in then be a slacker and just return it + return (Variant) objectToBeMadeIntoVariant; + } else if (objectToBeMadeIntoVariant.getClass().isArray()) { + // automatically convert arrays using reflection + // handle it differently based on the type of array + // added primitive support sourceforge 2762275 + SafeArray sa = null; + int len1 = Array.getLength(objectToBeMadeIntoVariant); + Class componentType = objectToBeMadeIntoVariant.getClass() + .getComponentType(); + + if (componentType.isArray()) { // array of arrays + int max = 0; + for (int i = 0; i < len1; i++) { + Object e1 = Array.get(objectToBeMadeIntoVariant, i); + int len2 = Array.getLength(e1); + if (max < len2) { + max = len2; + } + } + sa = new SafeArray(Variant.VariantVariant, len1, max); + for (int i = 0; i < len1; i++) { + Object e1 = Array.get(objectToBeMadeIntoVariant, i); + for (int j = 0; j < Array.getLength(e1); j++) { + sa.setVariant(i, j, objectToVariant(Array.get(e1, j))); + } + } + } else if (byte.class.equals(componentType)) { + byte[] arr = (byte[]) objectToBeMadeIntoVariant; + sa = new SafeArray(Variant.VariantByte, len1); + for (int i = 0; i < len1; i++) { + sa.setByte(i, arr[i]); + } + } else if (int.class.equals(componentType)) { + int[] arr = (int[]) objectToBeMadeIntoVariant; + sa = new SafeArray(Variant.VariantInt, len1); + for (int i = 0; i < len1; i++) { + sa.setInt(i, arr[i]); + } + } else if (double.class.equals(componentType)) { + double[] arr = (double[]) objectToBeMadeIntoVariant; + sa = new SafeArray(Variant.VariantDouble, len1); + for (int i = 0; i < len1; i++) { + sa.setDouble(i, arr[i]); + } + } else if (long.class.equals(componentType)) { + long[] arr = (long[]) objectToBeMadeIntoVariant; + sa = new SafeArray(Variant.VariantLongInt, len1); + for (int i = 0; i < len1; i++) { + sa.setLong(i, arr[i]); + } + } else { + // array of object + sa = new SafeArray(Variant.VariantVariant, len1); + for (int i = 0; i < len1; i++) { + sa.setVariant(i, objectToVariant(Array.get( + objectToBeMadeIntoVariant, i))); + } + } + Variant returnVariant = new Variant(); + populateVariant(returnVariant, sa, false); + return returnVariant; + } else { + // rely on populateVariant to throw an exception if its an + // invalid type + Variant returnVariant = new Variant(); + populateVariant(returnVariant, objectToBeMadeIntoVariant, false); + return returnVariant; + } + } + + /** + * converts an array of objects into an array of Variants by repeatedly + * calling obj2Variant(Object) + * + * @param arrayOfObjectsToBeConverted + * @return Variant[] + */ + protected static Variant[] objectsToVariants( + Object[] arrayOfObjectsToBeConverted) { + if (arrayOfObjectsToBeConverted instanceof Variant[]) { + // just return the passed in array if it is a Variant array + return (Variant[]) arrayOfObjectsToBeConverted; + } else { + Variant vArg[] = new Variant[arrayOfObjectsToBeConverted.length]; + for (int i = 0; i < arrayOfObjectsToBeConverted.length; i++) { + vArg[i] = objectToVariant(arrayOfObjectsToBeConverted[i]); + } + return vArg; + } + } + + /** + * Convert a JACOB Variant value to a Java object (type conversions). + * provided in Sourceforge feature request 959381. A fix was done to handle + * byRef bug report 1607878. + *

    + * Unlike other toXXX() methods, it does not do a type conversion except for + * special data types (it shouldn't do any!) + *

    + * Converts Variant.VariantArray types to SafeArrays + * + * @return Corresponding Java object of the type matching the Variant type. + * @throws IllegalStateException + * if no underlying windows data structure + * @throws NotImplementedException + * if unsupported conversion is requested + * @throws JacobException + * if the calculated result was a JacobObject usually as a + * result of error + */ + protected static Object variantToObject(Variant sourceData) { + Object result = null; + + short type = sourceData.getvt(); // variant type + + if ((type & Variant.VariantArray) == Variant.VariantArray) { // array + // returned? + SafeArray array = null; + type = (short) (type - Variant.VariantArray); + // From SF Bug 1840487 + // This did call toSafeArray(false) but that meant + // this was the only variantToObject() that didn't have its own + // copy of the data so you would end up with weird run time + // errors after some GC. So now we just get stupid about it and + // always make a copy just like toSafeArray() does. + array = sourceData.toSafeArray(); + result = array; + } else { // non-array object returned + switch (type) { + case Variant.VariantEmpty: // 0 + case Variant.VariantNull: // 1 + break; + case Variant.VariantShort: // 2 + result = new Short(sourceData.getShort()); + break; + case Variant.VariantShort | Variant.VariantByref: // 2 + result = new Short(sourceData.getShortRef()); + break; + case Variant.VariantInt: // 3 + result = new Integer(sourceData.getInt()); + break; + case Variant.VariantInt | Variant.VariantByref: // 3 + result = new Integer(sourceData.getIntRef()); + break; + case Variant.VariantFloat: // 4 + result = new Float(sourceData.getFloat()); + break; + case Variant.VariantFloat | Variant.VariantByref: // 4 + result = new Float(sourceData.getFloatRef()); + break; + case Variant.VariantDouble: // 5 + result = new Double(sourceData.getDouble()); + break; + case Variant.VariantDouble | Variant.VariantByref: // 5 + result = new Double(sourceData.getDoubleRef()); + break; + case Variant.VariantCurrency: // 6 + result = sourceData.getCurrency(); + break; + case Variant.VariantCurrency | Variant.VariantByref: // 6 + result = sourceData.getCurrencyRef(); + break; + case Variant.VariantDate: // 7 + result = sourceData.getJavaDate(); + break; + case Variant.VariantDate | Variant.VariantByref: // 7 + result = sourceData.getJavaDateRef(); + break; + case Variant.VariantString: // 8 + result = sourceData.getString(); + break; + case Variant.VariantString | Variant.VariantByref: // 8 + result = sourceData.getStringRef(); + break; + case Variant.VariantDispatch: // 9 + result = sourceData.getDispatch(); + break; + case Variant.VariantDispatch | Variant.VariantByref: // 9 + result = sourceData.getDispatchRef(); // Can dispatches even + // be byRef? + break; + case Variant.VariantError: // 10 + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantError"); + break; + case Variant.VariantBoolean: // 11 + result = new Boolean(sourceData.getBoolean()); + break; + case Variant.VariantBoolean | Variant.VariantByref: // 11 + result = new Boolean(sourceData.getBooleanRef()); + break; + case Variant.VariantVariant: // 12 they are always by ref + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantVariant without ByRef"); + break; + case Variant.VariantVariant | Variant.VariantByref: // 12 + result = sourceData.getVariant(); + break; + case Variant.VariantObject: // 13 + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantObject"); + break; + case Variant.VariantDecimal: // 14 + result = sourceData.getDecimal(); + break; + case Variant.VariantDecimal | Variant.VariantByref: // 14 + result = sourceData.getDecimalRef(); + break; + case Variant.VariantByte: // 17 + result = new Byte(sourceData.getByte()); + break; + case Variant.VariantByte | Variant.VariantByref: // 17 + result = new Byte(sourceData.getByteRef()); + break; + case Variant.VariantLongInt: // 20 + result = new Long(sourceData.getLong()); + break; + case Variant.VariantLongInt | Variant.VariantByref: // 20 + result = new Long(sourceData.getLongRef()); + break; + case Variant.VariantTypeMask: // 4095 + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantBstrBlob/VariantTypeMask"); + break; + case Variant.VariantArray: // 8192 + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantArray"); + break; + case Variant.VariantByref: // 16384 + result = new NotImplementedException( + "toJavaObject() Not implemented for VariantByref"); + break; + default: + result = new NotImplementedException("Unknown return type: " + + type); + // there was a "return result" here that caused defect 1602118 + // so it was removed + break; + }// switch (type) + + if (result instanceof JacobException) { + throw (JacobException) result; + } + } + + return result; + }// toJava() + + /** + * Verifies that we have a scale 0 <= x <= 28 and now more than 96 bits of + * data. The roundToMSDecimal method will attempt to adjust a BigDecimal to + * pass this set of tests + * + * @param in + * @throws IllegalArgumentException + * if out of bounds + */ + protected static void validateDecimalScaleAndBits(BigDecimal in) { + BigInteger allWordBigInt = in.unscaledValue(); + if (in.scale() > 28) { + // should this cast to a string and call putStringRef()? + throw new IllegalArgumentException( + "VT_DECIMAL only supports a maximum scale of 28 and the passed" + + " in value has a scale of " + in.scale()); + } else if (in.scale() < 0) { + // should this cast to a string and call putStringRef()? + throw new IllegalArgumentException( + "VT_DECIMAL only supports a minimum scale of 0 and the passed" + + " in value has a scale of " + in.scale()); + } else if (allWordBigInt.bitLength() > 12 * 8) { + throw new IllegalArgumentException( + "VT_DECIMAL supports a maximum of " + + 12 + * 8 + + " bits not counting scale and the number passed in has " + + allWordBigInt.bitLength()); + + } else { + // no bounds problem to be handled + } + + } + + /** + * Largest possible number with scale set to 0 + */ + private static final BigDecimal LARGEST_DECIMAL = new BigDecimal( + new BigInteger("ffffffffffffffffffffffff", 16)); + /** + * Smallest possible number with scale set to 0. MS doesn't support negative + * scales like BigDecimal. + */ + private static final BigDecimal SMALLEST_DECIMAL = new BigDecimal( + new BigInteger("ffffffffffffffffffffffff", 16).negate()); + + /** + * Does any validation that couldn't have been fixed by rounding or scale + * modification. + * + * @param in + * The BigDecimal to be validated + * @throws IllegalArgumentException + * if the number is too large or too small or null + */ + protected static void validateDecimalMinMax(BigDecimal in) { + if (in == null) { + throw new IllegalArgumentException( + "null is not a supported Decimal value."); + } else if (LARGEST_DECIMAL.compareTo(in) < 0) { + throw new IllegalArgumentException( + "Value too large for VT_DECIMAL data type:" + in.toString() + + " integer: " + in.toBigInteger().toString(16) + + " scale: " + in.scale()); + } else if (SMALLEST_DECIMAL.compareTo(in) > 0) { + throw new IllegalArgumentException( + "Value too small for VT_DECIMAL data type:" + in.toString() + + " integer: " + in.toBigInteger().toString(16) + + " scale: " + in.scale()); + } + + } + + /** + * Rounds the scale and bit length so that it will pass + * validateDecimalScaleBits(). Developers should call this method if they + * really want MS Decimal and don't want to lose precision. + *

    + * Changing the scale on a number that can fit in an MS Decimal can change + * the number's representation enough that it will round to a number too + * large to be represented by an MS VT_DECIMAL + * + * @param sourceDecimal + * @return BigDecimal a new big decimal that was rounded to fit in an MS + * VT_DECIMAL + */ + public static BigDecimal roundToMSDecimal(BigDecimal sourceDecimal) { + BigInteger sourceDecimalIntComponent = sourceDecimal.unscaledValue(); + BigDecimal destinationDecimal = new BigDecimal( + sourceDecimalIntComponent, sourceDecimal.scale()); + int roundingModel = BigDecimal.ROUND_HALF_UP; + validateDecimalMinMax(destinationDecimal); + // First limit the number of digits and then the precision. + // Try and round to 29 digits because we can sometimes do that + BigInteger allWordBigInt; + allWordBigInt = destinationDecimal.unscaledValue(); + if (allWordBigInt.bitLength() > 96) { + destinationDecimal = destinationDecimal.round(new MathContext(29)); + // see if 29 digits uses more than 96 bits + if (allWordBigInt.bitLength() > 96) { + // Dang. It was over 97 bits so shorten it one more digit to + // stay <= 96 bits + destinationDecimal = destinationDecimal.round(new MathContext( + 28)); + } + } + // the bit manipulations above may change the scale so do it afterwards + // round the scale to the max MS can support + if (destinationDecimal.scale() > 28) { + destinationDecimal = destinationDecimal.setScale(28, roundingModel); + } + if (destinationDecimal.scale() < 0) { + destinationDecimal = destinationDecimal.setScale(0, roundingModel); + } + return destinationDecimal; + } +} diff --git a/java/src/com/jacob/com/VariantViaEvent.java b/java/src/com/jacob/com/VariantViaEvent.java new file mode 100644 index 0000000..696a501 --- /dev/null +++ b/java/src/com/jacob/com/VariantViaEvent.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * a public class to variant that is used to track which variant objects are + * created by event callbacks This is solely used for that purpose. + */ +public class VariantViaEvent extends Variant { + + /** + * Standard constructor used by JNI event handling layer + */ + public VariantViaEvent() { + super(); + } +} diff --git a/java/src/com/jacob/com/WrongThreadException.java b/java/src/com/jacob/com/WrongThreadException.java new file mode 100644 index 0000000..028021b --- /dev/null +++ b/java/src/com/jacob/com/WrongThreadException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 1999-2004 Sourceforge JACOB Project. + * All rights reserved. Originator: Dan Adler (http://danadler.com). + * Get more information about JACOB at http://sourceforge.net/projects/jacob-project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +package com.jacob.com; + +/** + * thrown in util.cpp + */ +public class WrongThreadException extends JacobException { + /** + * identifier generated by Eclipse + */ + private static final long serialVersionUID = 6308780364980228692L; + + /** + * standard 0 arg constructor with no message + * + */ + public WrongThreadException() { + super("No Message Provided."); + } + + /** + * standard constructor with a string message + * + * @param s + */ + public WrongThreadException(String s) { + super(s); + } +} \ No newline at end of file