diff options
Diffstat (limited to 'private/oleutest/letest/ole2ui/ole2ui.c')
-rw-r--r-- | private/oleutest/letest/ole2ui/ole2ui.c | 971 |
1 files changed, 971 insertions, 0 deletions
diff --git a/private/oleutest/letest/ole2ui/ole2ui.c b/private/oleutest/letest/ole2ui/ole2ui.c new file mode 100644 index 000000000..fd1fc57bc --- /dev/null +++ b/private/oleutest/letest/ole2ui/ole2ui.c @@ -0,0 +1,971 @@ +/* + * OLE2UI.C + * + * Contains initialization routines and miscellaneous API implementations for + * the OLE 2.0 User Interface Support Library. + * + * Copyright (c)1992 Microsoft Corporation, All Right Reserved + */ + +#define STRICT 1 + +#include "ole2ui.h" +#include "common.h" +#include "utility.h" +#include "resimage.h" +#include "iconbox.h" +#include <commdlg.h> + +#define WINDLL 1 // make far pointer version of stdargs.h +#include <stdarg.h> + +// NOTE: If this code is being compiled for a DLL, then we need to define +// our OLE2UI debug symbols here (with the OLEDBGDATA_MAIN macro). If we're +// compiling for a static LIB, then the application we link to must +// define these symbols -- we just need to make an external reference here +// (with the macro OLEDBGDATA). + +#ifdef DLL_VER +OLEDBGDATA_MAIN(TEXT("OLE2UI")) +#else +OLEDBGDATA +#endif + +//The DLL instance handle shared amongst all dialogs. +HINSTANCE ghInst; + +//Registered messages for use with all the dialogs, registered in LibMain +UINT uMsgHelp=0; +UINT uMsgEndDialog=0; +UINT uMsgBrowse=0; +UINT uMsgChangeIcon=0; +UINT uMsgFileOKString=0; +UINT uMsgCloseBusyDlg=0; + +//Clipboard formats used by PasteSpecial +UINT cfObjectDescriptor; +UINT cfLinkSrcDescriptor; +UINT cfEmbedSource; +UINT cfEmbeddedObject; +UINT cfLinkSource; +UINT cfOwnerLink; +UINT cfFileName; + +// local function prototypes +BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); +BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam); + + +// local definition +#define WM_U_UPDATELINK WM_USER + + +// local structure definition +typedef struct tagUPDATELINKS +{ + LPOLEUILINKCONTAINER lpOleUILinkCntr; // pointer to Link Container + UINT cLinks; // total number of links + UINT cUpdated; // number of links updated + DWORD dwLink; // pointer to link + BOOL fError; // error flag + LPTSTR lpszTitle; // caption for dialog box +} UPDATELINKS, *PUPDATELINKS, FAR *LPUPDATELINKS; + + +/* + * OleUIInitialize + * + * NOTE: This function should only be called by your application IF it is + * using the static-link version of this library. If the DLL version is + * being used, this function is automatically called from the OLE2UI DLL's + * LibMain. + * + * Purpose: + * Initializes the OLE UI Library. Registers the OLE clipboard formats + * used in the Paste Special dialog, registers private custom window + * messages, and registers window classes of the "Result Image" + * and "Icon Box" custom controls used in the UI dialogs. + * + * Parameters: + * + * hInstance HINSTANCE of the module where the UI library resources + * and Dialog Procedures are contained. If you are calling + * this function yourself, this should be the instance handle + * of your application. + * + * hPrevInst HINSTANCE of the previous application instance. + * This is the parameter passed in to your WinMain. For + * the DLL version, this should always be set to zero (for + * WIN16 DLLs). + * + * lpszClassIconBox + * LPTSTR containing the name you assigned to the symbol + * SZCLASSICONBOX (this symbol is defined in UICLASS.H + * which is generated in the MAKEFILE). + * + * This name is used as the window class name + * when registering the IconBox custom control used in the + * UI dialogs. In order to handle mutliple apps running + * with this library, you must make this name unique to your + * application. + * + * For the DLL version: Do NOT call this function directly + * from your application, it is called automatically from + * the DLL's LibMain. + * + * For the static library version: This should be set to + * the symbol SZCLASSICONBOX. This symbol is defined in + * UICLASS.H. + * + * lpszClassResImage + * LPTSTR containing the name you assigned to the symbol + * SZCLASSRESULTIMAGE. See the description of + * lpszClassIconBox above for more info. + * + * Return Value: + * BOOL TRUE if initialization was successful. + * FALSE if either the "Magic Number" did not verify, or one of + * the window classes could not be registered. If the + * "Magic Number" did not verify, then the resources + * in your module are of a different version than the + * ones you compiled with. + */ + +STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance, + HINSTANCE hPrevInst, + LPTSTR lpszClassIconBox, + LPTSTR lpszClassResImage) +{ + HRSRC hr; + HGLOBAL hg; + LPWORD lpdata; + + OleDbgOut1(TEXT("OleUIInitialize called.\r\n")); + ghInst=hInstance; + + // Verify that we have the correct resources added to our application + // by checking the "VERIFICATION" resource with the magic number we've + // compiled into our app. + + OutputDebugString(TEXT("Entering OleUIInitialize\n")); + + if ((hr = FindResource(hInstance, TEXT("VERIFICATION"), RT_RCDATA)) == NULL) + goto ResourceLoadError; + + if ((hg = LoadResource(hInstance, hr)) == NULL) + goto ResourceLoadError; + + if ((lpdata = (LPWORD)LockResource(hg)) == NULL) + goto ResourceLockError; + + if ((WORD)*lpdata != (WORD)OLEUI_VERSION_MAGIC) + goto ResourceReadError; + + // OK, resource versions match. Contine on. + UnlockResource(hg); + FreeResource(hg); + OleDbgOut1(TEXT("OleUIInitialize: Resource magic number verified.\r\n")); + + // Register messages we need for the dialogs. If + uMsgHelp =RegisterWindowMessage(SZOLEUI_MSG_HELP); + uMsgEndDialog =RegisterWindowMessage(SZOLEUI_MSG_ENDDIALOG); + uMsgBrowse =RegisterWindowMessage(SZOLEUI_MSG_BROWSE); + uMsgChangeIcon=RegisterWindowMessage(SZOLEUI_MSG_CHANGEICON); + uMsgFileOKString = RegisterWindowMessage(FILEOKSTRING); + uMsgCloseBusyDlg = RegisterWindowMessage(SZOLEUI_MSG_CLOSEBUSYDIALOG); + + // Register Clipboard Formats used by PasteSpecial dialog. + cfObjectDescriptor = RegisterClipboardFormat(CF_OBJECTDESCRIPTOR); + cfLinkSrcDescriptor= RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR); + cfEmbedSource = RegisterClipboardFormat(CF_EMBEDSOURCE); + cfEmbeddedObject = RegisterClipboardFormat(CF_EMBEDDEDOBJECT); + cfLinkSource = RegisterClipboardFormat(CF_LINKSOURCE); + cfOwnerLink = RegisterClipboardFormat(CF_OWNERLINK); + cfFileName = RegisterClipboardFormat(CF_FILENAME); + + if (!FResultImageInitialize(hInstance, hPrevInst, lpszClassResImage)) + { + OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n")); + return 0; + } + + if (!FIconBoxInitialize(hInstance, hPrevInst, lpszClassIconBox)) + { + OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n")); + return 0; + } + + return TRUE; + +ResourceLoadError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to find version verification resource.\r\n")); + return FALSE; + +ResourceLockError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Unable to lock version verification resource.\r\n")); + FreeResource(hg); + return FALSE; + +ResourceReadError: + OleDbgOut1(TEXT("OleUIInitialize: ERROR - Version verification values did not compare.\r\n")); + + {TCHAR buf[255]; + wsprintf(buf, TEXT("resource read 0x%X, my value is 0x%X\n"), (WORD)*lpdata, (WORD)OLEUI_VERSION_MAGIC); + OutputDebugString(buf); + } + + UnlockResource(hg); + FreeResource(hg); + return FALSE; +} + + +/* + * OleUIUnInitialize + * + * NOTE: This function should only be called by your application IF it is using + * the static-link version of this library. If the DLL version is being used, + * this function is automatically called from the DLL's LibMain. + * + * Purpose: + * Uninitializes OLE UI libraries. Deletes any resources allocated by the + * library. + * + * Return Value: + * BOOL TRUE if successful, FALSE if not. Current implementation always + * returns TRUE. + */ + + +STDAPI_(BOOL) OleUIUnInitialize() +{ + IconBoxUninitialize(); + ResultImageUninitialize(); + + return TRUE; +} + + +/* + * OleUIAddVerbMenu + * + * Purpose: + * Add the Verb menu for the specified object to the given menu. If the + * object has one verb, we directly add the verb to the given menu. If + * the object has multiple verbs we create a cascading sub-menu. + * + * Parameters: + * lpObj LPOLEOBJECT pointing to the selected object. If this + * is NULL, then we create a default disabled menu item. + * + * lpszShortType LPTSTR with short type name (AuxName==2) corresponding + * to the lpOleObj. if the string is NOT known, then NULL + * may be passed. if NULL is passed, then + * IOleObject::GetUserType will be called to retrieve it. + * if the caller has the string handy, then it is faster + * to pass it in. + * + * hMenu HMENU in which to make modifications. + * + * uPos Position of the menu item + * + * uIDVerbMin UINT ID value at which to start the verbs. + * verb_0 = wIDMVerbMin + verb_0 + * verb_1 = wIDMVerbMin + verb_1 + * verb_2 = wIDMVerbMin + verb_2 + * etc. + * uIDVerbMax UINT maximum ID value allowed for object verbs. + * if uIDVerbMax==0 then any ID value is allowed + * + * bAddConvert BOOL specifying whether or not to add a "Convert" item + * to the bottom of the menu (with a separator). + * + * idConvert UINT ID value to use for the Convert menu item, if + * bAddConvert is TRUE. + * + * lphMenu HMENU FAR * of the cascading verb menu if it's created. + * If there is only one verb, this will be filled with NULL. + * + * + * Return Value: + * BOOL TRUE if lpObj was valid and we added at least one verb + * to the menu. FALSE if lpObj was NULL and we created + * a disabled default menu item + */ + +STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj, + LPTSTR lpszShortType, + HMENU hMenu, + UINT uPos, + UINT uIDVerbMin, + UINT uIDVerbMax, + BOOL bAddConvert, + UINT idConvert, + HMENU FAR *lphMenu) +{ + LPPERSISTSTORAGE lpPS=NULL; + LPENUMOLEVERB lpEnumOleVerb = NULL; + OLEVERB oleverb; + LPUNKNOWN lpUnk; + LPTSTR lpszShortTypeName = lpszShortType; + LPTSTR lpszVerbName = NULL; + HRESULT hrErr; + BOOL fStatus; + BOOL fIsLink = FALSE; + BOOL fResult = TRUE; + BOOL fAddConvertItem = FALSE; + int cVerbs = 0; + UINT uFlags = MF_BYPOSITION; + static BOOL fFirstTime = TRUE; + static TCHAR szBuffer[OLEUI_OBJECTMENUMAX]; + static TCHAR szNoObjectCmd[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmd1Verb[OLEUI_OBJECTMENUMAX]; + static TCHAR szObjectCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szLinkCmdNVerb[OLEUI_OBJECTMENUMAX]; + static TCHAR szUnknown[OLEUI_OBJECTMENUMAX]; + static TCHAR szEdit[OLEUI_OBJECTMENUMAX]; + static TCHAR szConvert[OLEUI_OBJECTMENUMAX]; + + *lphMenu=NULL; + + // Set fAddConvertItem flag + if (bAddConvert & (idConvert != 0)) + fAddConvertItem = TRUE; + + // only need to load the strings the 1st time + if (fFirstTime) { + if (0 == LoadString(ghInst, IDS_OLE2UIEDITNOOBJCMD, + (LPTSTR)szNoObjectCmd, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_1VERB, + (LPTSTR)szLinkCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_1VERB, + (LPTSTR)szObjectCmd1Verb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIEDITLINKCMD_NVERB, + (LPTSTR)szLinkCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + if (0 == LoadString(ghInst, IDS_OLE2UIEDITOBJECTCMD_NVERB, + (LPTSTR)szObjectCmdNVerb, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIUNKNOWN, + (LPTSTR)szUnknown, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if (0 == LoadString(ghInst, IDS_OLE2UIEDIT, + (LPTSTR)szEdit, OLEUI_OBJECTMENUMAX)) + return FALSE; + + if ( (0 == LoadString(ghInst, IDS_OLE2UICONVERT, + (LPTSTR)szConvert, OLEUI_OBJECTMENUMAX)) && fAddConvertItem) + return FALSE; + + fFirstTime = FALSE; + } + + // Delete whatever menu may happen to be here already. + DeleteMenu(hMenu, uPos, uFlags); + + if (!lpOleObj) + goto AVMError; + + if (! lpszShortTypeName) { + // get the Short form of the user type name for the menu + OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n")) + hrErr = CallIOleObjectGetUserTypeA( + lpOleObj, + USERCLASSTYPE_SHORT, + (LPTSTR FAR*)&lpszShortTypeName + ); + OLEDBG_END2 + + if (NOERROR != hrErr) { + OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr); + } + } + + // check if the object is a link (it is a link if it support IOleLink) + hrErr = lpOleObj->lpVtbl->QueryInterface( + lpOleObj, + &IID_IOleLink, + (LPVOID FAR*)&lpUnk + ); + if (NOERROR == hrErr) { + fIsLink = TRUE; + OleStdRelease(lpUnk); + } + + // Get the verb enumerator from the OLE object + OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n")) + hrErr = lpOleObj->lpVtbl->EnumVerbs( + lpOleObj, + (LPENUMOLEVERB FAR*)&lpEnumOleVerb + ); + OLEDBG_END2 + + if (NOERROR != hrErr) { + OleDbgOutHResult(TEXT("IOleObject::EnumVerbs returned"), hrErr); + } + + if (!(*lphMenu = CreatePopupMenu())) + goto AVMError; + + // loop through all verbs + while (lpEnumOleVerb != NULL) { // forever + hrErr = lpEnumOleVerb->lpVtbl->Next( + lpEnumOleVerb, + 1, + (LPOLEVERB)&oleverb, + NULL + ); + if (NOERROR != hrErr) + break; // DONE! no more verbs + + /* OLE2NOTE: negative verb numbers and verbs that do not + ** indicate ONCONTAINERMENU should NOT be put on the verb menu + */ + if (oleverb.lVerb < 0 || + ! (oleverb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU)) { + + /* OLE2NOTE: we must still free the verb name string */ + if (oleverb.lpszVerbName) + OleStdFree(oleverb.lpszVerbName); + continue; + } + + // we must free the previous verb name string + if (lpszVerbName) + OleStdFreeString(lpszVerbName, NULL); + + CopyAndFreeOLESTR(oleverb.lpszVerbName, &lpszVerbName); + + if ( 0 == uIDVerbMax || + (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) ) { + fStatus = InsertMenu( + *lphMenu, + (UINT)-1, + MF_BYPOSITION | (UINT)oleverb.fuFlags, + uIDVerbMin+(UINT)oleverb.lVerb, + (LPTSTR)lpszVerbName + ); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + } + + // Add the separator and "Convert" menu item. + if (fAddConvertItem) { + + if (0 == cVerbs) { + LPTSTR lpsz; + + // if object has no verbs, then use "Convert" as the obj's verb + lpsz = lpszVerbName = OleStdCopyString(szConvert, NULL); + uIDVerbMin = idConvert; + + // remove "..." from "Convert..." string; it will be added later + if (lpsz) { + while(*lpsz && *lpsz != TEXT('.')) + lpsz++; + *lpsz = TEXT('\0'); + } + } + + if (cVerbs > 0) { + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION | MF_SEPARATOR, + (UINT)0, + (LPCTSTR)NULL); + if (! fStatus) + goto AVMError; + } + + /* add convert menu */ + fStatus = InsertMenu(*lphMenu, + (UINT)-1, + MF_BYPOSITION, + idConvert, + (LPCTSTR)szConvert); + if (! fStatus) + goto AVMError; + + cVerbs++; + } + + + /* + * Build the appropriate menu based on the number of verbs found + * + * NOTE: Localized verb menus may require a different format. + * to assist in localization of the single verb case, the + * szLinkCmd1Verb and szObjectCmd1Verb format strings start + * with either a '0' (note: NOT '\0'!) or a '1': + * leading '0' -- verb type + * leading '1' -- type verb + */ + + if (cVerbs == 0) { + + // there are NO verbs (not even Convert...). set the menu to be + // "<short type> &Object/Link" and gray it out. + wsprintf( + szBuffer, + (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + uFlags |= MF_GRAYED; + +#if defined( OBSOLETE ) + //No verbs. Create a default using Edit as the verb. + LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb); + + if (*lpsz == TEXT('0')) { + wsprintf(szBuffer, lpsz+1, (LPSTR)szEdit, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + } + else { + wsprintf(szBuffer, lpsz+1, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")), + (LPTSTR)szEdit + ); + } +#endif + + fResult = FALSE; + DestroyMenu(*lphMenu); + *lphMenu = NULL; + + } + else if (cVerbs == 1) { + //One verb without Convert, one item. + LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb); + + if (*lpsz == TEXT('0')) { + wsprintf(szBuffer, lpsz+1, lpszVerbName, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + } + else { + wsprintf(szBuffer, lpsz+1, + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")), + lpszVerbName + ); + } + + // if only "verb" is "Convert..." then append the ellipses + if (fAddConvertItem) + lstrcat(szBuffer, TEXT("...")); + + DestroyMenu(*lphMenu); + *lphMenu=NULL; + } + else { + + //Multiple verbs or one verb with Convert, add the cascading menu + wsprintf( + szBuffer, + (fIsLink ? (LPTSTR)szLinkCmdNVerb:(LPTSTR)szObjectCmdNVerb), + (lpszShortTypeName ? lpszShortTypeName : (LPTSTR) TEXT("")) + ); + uFlags |= MF_ENABLED | MF_POPUP; + uIDVerbMin=(UINT)*lphMenu; + } + + if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, (LPTSTR)szBuffer)) + +AVMError: + { + InsertMenu(hMenu, uPos, MF_GRAYED | uFlags, + uIDVerbMin, (LPTSTR)szNoObjectCmd); +#if defined( OBSOLETE ) + HMENU hmenuDummy = CreatePopupMenu(); + + InsertMenu(hMenu, uPos, MF_GRAYED | MF_POPUP | uFlags, + (UINT)hmenuDummy, (LPTSTR)szNoObjectCmd); +#endif + fResult = FALSE; + } + + if (lpszVerbName) + OleStdFreeString(lpszVerbName, NULL); + if (!lpszShortType && lpszShortTypeName) + OleStdFreeString(lpszShortTypeName, NULL); + if (lpEnumOleVerb) + lpEnumOleVerb->lpVtbl->Release(lpEnumOleVerb); + return fResult; +} + + +/* PromptUserDlgProc + * ----------------- + * + * Purpose: + * Dialog procedure used by OleUIPromptUser(). Returns when a button is + * clicked in the dialog box and the button id is return. + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam + * + * Returns: + * + */ +BOOL CALLBACK EXPORT PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + switch (iMsg) { + case WM_INITDIALOG: + { + LPTSTR lpszTitle; + TCHAR szBuf[256]; + TCHAR szFormat[256]; + va_list *parglist; + + if (!lParam) { + EndDialog(hDlg, -1); + return FALSE; + } + + // + // lParam is really a va_list *. We called va_start and va_end in + // the function that calls this. + // + + parglist = (va_list *) lParam; + + lpszTitle = va_arg(*parglist, LPTSTR); + SetWindowText(hDlg, lpszTitle); + + GetDlgItemText(hDlg, ID_PU_TEXT,(LPTSTR)szFormat,sizeof(szFormat)/sizeof(TCHAR)); + wvsprintf((LPTSTR)szBuf, (LPTSTR)szFormat, *parglist); + + + SetDlgItemText(hDlg, ID_PU_TEXT, (LPTSTR)szBuf); + return TRUE; + } + case WM_COMMAND: + EndDialog(hDlg, wParam); + return TRUE; + + default: + return FALSE; + } +} + + +/* OleUIPromptUser + * --------------- + * + * Purpose: + * Popup a dialog box with the specified template and returned the + * response (button id) from the user. + * + * Parameters: + * nTemplate resource number of the dialog + * hwndParent parent of the dialog box + * ... title of the dialog box followed by argument list + * for the format string in the static control + * (ID_PU_TEXT) of the dialog box. + * The caller has to make sure that the correct number + * and type of argument are passed in. + * + * Returns: + * button id selected by the user (template dependent) + * + * Comments: + * the following message dialog boxes are supported: + * + * IDD_LINKSOURCEUNAVAILABLE -- Link source is unavailable + * VARARG Parameters: + * None. + * Used for the following error codes: + * OLE_E_CANT_BINDTOSOURCE + * STG_E_PATHNOTFOUND + * (sc >= MK_E_FIRST) && (sc <= MK_E_LAST) -- any Moniker error + * any unknown error if object is a link + * + * IDD_SERVERNOTFOUND -- server registered but NOT found + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * CO_E_APPNOTFOUND + * CO_E_APPDIDNTREG + * any unknown error if object is an embedded object + * + * IDD_SERVERNOTREG -- server NOT registered + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of object + * Used for the following error codes: + * REGDB_E_CLASSNOTREG + * OLE_E_STATIC -- static object with no server registered + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_LINKTYPECHANGED -- class of link source changed since last binding + * VARARG Parameters: + * LPSTR lpszUserType -- user type name of ole link source + * Used for the following error codes: + * OLE_E_CLASSDIFF + * + * IDD_OUTOFMEMORY -- out of memory + * VARARG Parameters: + * None. + * Used for the following error codes: + * E_OUTOFMEMORY + * + */ +int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...) +{ + int nRet; + va_list arglist; + LPARAM lParam; + + // + // We want to pass the variable list of arguments to PrompUserDlgProc, + // but we can't just pass arglist because arglist is not always the + // same size as an LPARAM (e.g. on Alpha va_list is a structure). + // So, we pass the a pointer to the arglist instead. + // + + va_start(arglist, hwndParent); + lParam = (LPARAM) &arglist; + + nRet = DialogBoxParam(ghInst, MAKEINTRESOURCE(nTemplate), hwndParent, + PromptUserDlgProc, lParam); + + va_end(arglist); + + return nRet; +} + + + +/* UpdateLinksDlgProc + * ------------------ + * + * Purpose: + * Dialog procedure used by OleUIUpdateLinks(). It will enumerate all + * all links in the container and updates all automatic links. + * Returns when the Stop Button is clicked in the dialog box or when all + * links are updated + * + * Parameters: + * hDlg + * iMsg + * wParam + * lParam pointer to the UPDATELINKS structure + * + * Returns: + * + */ +BOOL CALLBACK EXPORT UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam) +{ + LPUPDATELINKS FAR* lplpUL = NULL; + HANDLE gh; + static BOOL fAbort = FALSE; + + //Process the temination message + if (iMsg==uMsgEndDialog) + { + gh = RemoveProp(hDlg, STRUCTUREPROP); + if (NULL!=gh) { + GlobalUnlock(gh); + GlobalFree(gh); + } + EndDialog(hDlg, wParam); + return TRUE; + } + + switch (iMsg) { + case WM_INITDIALOG: + { + gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(LPUPDATELINKS)); + SetProp(hDlg, STRUCTUREPROP, gh); + + if (NULL==gh) + { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + + fAbort = FALSE; + lplpUL = (LPUPDATELINKS FAR*)GlobalLock(gh); + + if (lplpUL) { + *lplpUL = (LPUPDATELINKS)lParam; + SetWindowText(hDlg, (*lplpUL)->lpszTitle); + SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL); + return TRUE; + } else { + PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L); + return FALSE; + } + } + + case WM_TIMER: + KillTimer(hDlg, 1); + gh = GetProp(hDlg, STRUCTUREPROP); + + if (NULL!=gh) { + // gh was locked previously, lock and unlock to get lplpUL + lplpUL = GlobalLock(gh); + GlobalUnlock(gh); + } + if (! fAbort && lplpUL) + PostMessage(hDlg, WM_U_UPDATELINK, 0, (LPARAM)(*lplpUL)); + else + PostMessage(hDlg,uMsgEndDialog,OLEUI_CANCEL,0L); + + return 0; + + case WM_COMMAND: // Stop button + fAbort = TRUE; + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + + case WM_U_UPDATELINK: + { + HRESULT hErr; + int nPercent; + RECT rc; + TCHAR szPercent[5]; // 0% to 100% + HBRUSH hbr; + HDC hDC; + HWND hwndMeter; + MSG msg; + DWORD dwUpdateOpt; + LPUPDATELINKS lpUL = (LPUPDATELINKS)lParam; + + lpUL->dwLink=lpUL->lpOleUILinkCntr->lpVtbl->GetNextLink( + lpUL->lpOleUILinkCntr, + lpUL->dwLink + ); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (! IsDialogMessage(hDlg, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + if (fAbort) + return FALSE; + + if (!lpUL->dwLink) { // all links processed + SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L); + return TRUE; + } + + hErr = lpUL->lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions( + lpUL->lpOleUILinkCntr, + lpUL->dwLink, + (LPDWORD)&dwUpdateOpt + ); + + if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS)) { + + hErr = lpUL->lpOleUILinkCntr->lpVtbl->UpdateLink( + lpUL->lpOleUILinkCntr, + lpUL->dwLink, + FALSE, // fMessage + FALSE // ignored + ); + lpUL->fError |= (hErr != NOERROR); + lpUL->cUpdated++; + + nPercent = lpUL->cUpdated * 100 / lpUL->cLinks; + if (nPercent <= 100) { // do NOT advance % beyond 100% + // update percentage + wsprintf((LPTSTR)szPercent, TEXT("%d%%"), nPercent); + SetDlgItemText(hDlg, ID_PU_PERCENT, (LPTSTR)szPercent); + + // update indicator + hwndMeter = GetDlgItem(hDlg, ID_PU_METER); + GetClientRect(hwndMeter, (LPRECT)&rc); + InflateRect((LPRECT)&rc, -1, -1); + rc.right = (rc.right - rc.left) * nPercent / 100 + rc.left; + hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + if (hbr) { + hDC = GetDC(hwndMeter); + if (hDC) { + FillRect(hDC, (LPRECT)&rc, hbr); + ReleaseDC(hwndMeter, hDC); + } + DeleteObject(hbr); + } + } + } + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + if (! IsDialogMessage(hDlg, &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + PostMessage(hDlg, WM_U_UPDATELINK, 0, lParam); + + return TRUE; + } + + default: + return FALSE; + } +} + + +/* OleUIUpdateLink + * --------------- + * + * Purpose: + * Update all links in the Link Container and popup a dialog box which + * shows the progress of the updating. + * The process is stopped when the user press Stop button or when all + * links are processed. + * + * Parameters: + * lpOleUILinkCntr pointer to Link Container + * hwndParent parent window of the dialog + * lpszTitle title of the dialog box + * cLinks total number of links + * + * Returns: + * TRUE all links updated successfully + * FALSE otherwise + */ +STDAPI_(BOOL) OleUIUpdateLinks(LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks) +{ + LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS)); + BOOL fError; + + OleDbgAssert(lpOleUILinkCntr && hwndParent && lpszTitle && (cLinks>0)); + OleDbgAssert(lpUL); + + lpUL->lpOleUILinkCntr = lpOleUILinkCntr; + lpUL->cLinks = cLinks; + lpUL->cUpdated = 0; + lpUL->dwLink = 0; + lpUL->fError = FALSE; + lpUL->lpszTitle = lpszTitle; + + DialogBoxParam(ghInst, MAKEINTRESOURCE(IDD_UPDATELINKS), + hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL); + + fError = lpUL->fError; + OleStdFree((LPVOID)lpUL); + + return !fError; +} |