summaryrefslogtreecommitdiffstats
path: root/private/ole2ui32/ole2ui.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ole2ui32/ole2ui.cpp1036
1 files changed, 1036 insertions, 0 deletions
diff --git a/private/ole2ui32/ole2ui.cpp b/private/ole2ui32/ole2ui.cpp
new file mode 100644
index 000000000..30828b946
--- /dev/null
+++ b/private/ole2ui32/ole2ui.cpp
@@ -0,0 +1,1036 @@
+/*
+ * OLE2UI.CPP
+ *
+ * Contains initialization routines and miscellaneous API implementations for
+ * the OLE 2.0 User Interface Support Library.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#include "precomp.h"
+#include "common.h"
+#include "utility.h"
+#include "resimage.h"
+#include "iconbox.h"
+#include <commdlg.h>
+#include <stdarg.h>
+
+OLEDBGDATA
+
+// Registered messages for use with all the dialogs, registered in LibMain
+UINT uMsgHelp;
+UINT uMsgEndDialog;
+UINT uMsgBrowse;
+UINT uMsgChangeIcon;
+UINT uMsgFileOKString;
+UINT uMsgCloseBusyDlg;
+UINT uMsgConvert;
+UINT uMsgChangeSource;
+UINT uMsgAddControl;
+UINT uMsgBrowseOFN;
+
+// local function prototypes
+BOOL CALLBACK PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
+BOOL CALLBACK UpdateLinksDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
+
+// local definition
+#define WM_U_UPDATELINK (WM_USER+0x2000)
+#define WM_U_SHOWWINDOW (WM_USER+0x2001)
+
+// 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 OLEDLG 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).
+ *
+ * Return Value:
+ * BOOL TRUE if initialization was successful.
+ * FALSE otherwise.
+ */
+
+#pragma code_seg(".text$initseg")
+
+BOOL bWin4; // TRUE if running Windows4 or greater
+BOOL bSharedData; // TRUE if running Win32s (it has shared data)
+
+static DWORD tlsIndex= (DWORD)-1;
+static TASKDATA taskData;
+
+STDAPI_(TASKDATA*) GetTaskData()
+{
+ TASKDATA* pData;
+ if (tlsIndex == (DWORD)-1)
+ pData = &taskData;
+ else
+ pData = (TASKDATA*)TlsGetValue(tlsIndex);
+ return pData;
+}
+
+DWORD WINAPI _AfxTlsAlloc()
+{
+ DWORD dwResult = TlsAlloc();
+ DWORD dwVersion = GetVersion();
+ if ((dwVersion & 0x80000000) && (BYTE)dwVersion <= 3)
+ {
+ while (dwResult >= 0 && dwResult <= 2)
+ dwResult = TlsAlloc();
+ }
+ return dwResult;
+}
+
+static int nInitCount;
+
+STDAPI_(BOOL) OleUIUnInitialize();
+
+STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance,
+ HINSTANCE hPrevInst)
+{
+ OleDbgOut1(TEXT("OleUIInitialize called.\r\n"));
+
+ // Cache information about the windows version we are running
+ DWORD dwVersion = GetVersion();
+ bWin4 = LOBYTE(dwVersion) >= 4;
+ bSharedData = !bWin4 && (dwVersion & 0x80000000);
+
+ if (nInitCount == 0)
+ {
+ if (bSharedData)
+ {
+ // allocate thread local storage on Win32s
+ tlsIndex = _AfxTlsAlloc();
+ if (tlsIndex == (DWORD)-1)
+ return FALSE;
+ }
+ }
+ ++nInitCount;
+
+ // Setup process local storage if necessary
+ if (tlsIndex != (DWORD)-1)
+ {
+ void* pData = LocalAlloc(LPTR, sizeof(TASKDATA));
+ if (pData == NULL)
+ {
+ if (nInitCount == 0)
+ {
+ OleUIUnInitialize();
+ return FALSE;
+ }
+ }
+ TlsSetValue(tlsIndex, pData);
+ }
+
+ // Initialize OleStd functions
+ OleStdInitialize(hInstance, hInstance);
+
+ // Register messages we need for the dialogs.
+ 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);
+ uMsgConvert = RegisterWindowMessage(SZOLEUI_MSG_CONVERT);
+ uMsgChangeSource = RegisterWindowMessage(SZOLEUI_MSG_CHANGESOURCE);
+ uMsgAddControl = RegisterWindowMessage(SZOLEUI_MSG_ADDCONTROL);
+ uMsgBrowseOFN = RegisterWindowMessage(SZOLEUI_MSG_BROWSE_OFN);
+
+ if (!FResultImageInitialize(hInstance, hPrevInst))
+ {
+ OleDbgOut1(TEXT("OleUIInitialize: FResultImageInitialize failed. Terminating.\r\n"));
+ return 0;
+ }
+ if (!FIconBoxInitialize(hInstance, hPrevInst))
+ {
+ OleDbgOut1(TEXT("OleUIInitialize: FIconBoxInitialize failed. Terminating.\r\n"));
+ return 0;
+ }
+ return TRUE;
+}
+
+#pragma code_seg()
+
+
+/*
+ * 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();
+
+ // Cleanup thread local storage
+ if (tlsIndex != (DWORD)-1)
+ {
+ TASKDATA* pData = (TASKDATA*)TlsGetValue(tlsIndex);
+ TlsSetValue(tlsIndex, NULL);
+ if (pData != NULL)
+ {
+ if (pData->hInstCommCtrl != NULL)
+ FreeLibrary(pData->hInstCommCtrl);
+ if (pData->hInstShell != NULL)
+ FreeLibrary(pData->hInstShell);
+ if (pData->hInstComDlg != NULL)
+ FreeLibrary(pData->hInstComDlg);
+ LocalFree(pData);
+ }
+ }
+
+ // Last chance cleanup
+ if (nInitCount == 1)
+ {
+ // cleanup thread local storage
+ if (tlsIndex != (DWORD)-1)
+ {
+ TlsFree(tlsIndex);
+ tlsIndex = (DWORD)-1;
+ }
+ }
+ if (nInitCount != 0)
+ --nInitCount;
+
+ 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,
+ LPCTSTR lpszShortType,
+ HMENU hMenu, UINT uPos,
+ UINT uIDVerbMin, UINT uIDVerbMax,
+ BOOL bAddConvert, UINT idConvert,
+ HMENU FAR *lphMenu)
+{
+ LPPERSISTSTORAGE lpPS=NULL;
+ LPENUMOLEVERB lpEnumOleVerb = NULL;
+ OLEVERB oleverb;
+ LPCTSTR 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];
+
+ // Set fAddConvertItem flag
+ if (bAddConvert & (idConvert != 0))
+ fAddConvertItem = TRUE;
+
+ // only need to load the strings the 1st time
+ if (fFirstTime)
+ {
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITNOOBJCMD,
+ szNoObjectCmd, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_1VERB,
+ szLinkCmd1Verb, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_1VERB,
+ szObjectCmd1Verb, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITLINKCMD_NVERB,
+ szLinkCmdNVerb, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDITOBJECTCMD_NVERB,
+ szObjectCmdNVerb, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN,
+ szUnknown, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UIEDIT,
+ szEdit, OLEUI_OBJECTMENUMAX))
+ return FALSE;
+
+ if (0 == LoadString(_g_hOleStdResInst, IDS_OLE2UICONVERT,
+ szConvert, OLEUI_OBJECTMENUMAX) && fAddConvertItem)
+ return FALSE;
+
+ fFirstTime = FALSE;
+ }
+
+ // Delete whatever menu may happen to be here already.
+ DeleteMenu(hMenu, uPos, uFlags);
+
+ if (lphMenu == NULL || IsBadWritePtr(lphMenu, sizeof(HMENU)))
+ {
+ goto AVMError;
+ }
+ *lphMenu=NULL;
+
+ if ((!lpOleObj) || IsBadReadPtr(lpOleObj, sizeof (IOleObject)))
+ goto AVMError;
+
+ if ((!lpszShortTypeName) || IsBadReadPtr(lpszShortTypeName, sizeof(TCHAR)))
+ {
+ // get the Short form of the user type name for the menu
+ OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n"))
+#if defined(WIN32) && !defined(UNICODE)
+ LPOLESTR wszShortTypeName = NULL;
+ lpszShortTypeName = NULL;
+ hrErr = lpOleObj->GetUserType(
+ USERCLASSTYPE_SHORT,
+ &wszShortTypeName);
+ if (NULL != wszShortTypeName)
+ {
+ UINT uLen = WTOALEN(wszShortTypeName);
+ lpszShortTypeName = (LPTSTR) OleStdMalloc(uLen);
+ if (NULL != lpszShortTypeName)
+ {
+ WTOA((char *)lpszShortTypeName, wszShortTypeName, uLen);
+ }
+ OleStdFree(wszShortTypeName);
+ }
+#else
+ hrErr = lpOleObj->GetUserType(
+ USERCLASSTYPE_SHORT,
+ (LPTSTR FAR*)&lpszShortTypeName);
+#endif
+ OLEDBG_END2
+
+ if (NOERROR != hrErr)
+ OleDbgOutHResult(TEXT("IOleObject::GetUserType returned"), hrErr);
+ }
+
+ // check if the object is a link
+ fIsLink = OleStdIsOleLink((LPUNKNOWN)lpOleObj);
+
+ // Get the verb enumerator from the OLE object
+ OLEDBG_BEGIN2(TEXT("IOleObject::EnumVerbs called\r\n"))
+ hrErr = lpOleObj->EnumVerbs(
+ (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)
+ {
+ hrErr = lpEnumOleVerb->Next(
+ 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)
+ OleStdFree(lpszVerbName);
+
+#if defined(WIN32) && !defined(UNICODE)
+ lpszVerbName = NULL;
+ if (NULL != oleverb.lpszVerbName)
+ {
+ UINT uLen = WTOALEN(oleverb.lpszVerbName);
+ lpszVerbName = (LPTSTR) OleStdMalloc(uLen);
+ if (NULL != lpszVerbName)
+ {
+ WTOA(lpszVerbName, oleverb.lpszVerbName, uLen);
+ }
+ OleStdFree(oleverb.lpszVerbName);
+ }
+#else
+ lpszVerbName = oleverb.lpszVerbName;
+#endif
+ if ( 0 == uIDVerbMax ||
+ (uIDVerbMax >= uIDVerbMin+(UINT)oleverb.lVerb) )
+ {
+ fStatus = InsertMenu(
+ *lphMenu,
+ (UINT)-1,
+ MF_BYPOSITION | (UINT)oleverb.fuFlags,
+ uIDVerbMin+(UINT)oleverb.lVerb,
+ 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);
+ uIDVerbMin = idConvert;
+
+ // remove "..." from "Convert..." string; it will be added later
+ if (lpsz)
+ {
+ while(*lpsz && *lpsz != '.')
+ lpsz = CharNext(lpsz);
+ *lpsz = '\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
+ *
+ */
+ 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 ? szLinkCmdNVerb : szObjectCmdNVerb),
+ (lpszShortTypeName ? lpszShortTypeName : TEXT(""))
+ );
+ uFlags |= MF_GRAYED;
+
+ fResult = FALSE;
+ DestroyMenu(*lphMenu);
+ *lphMenu = NULL;
+
+ }
+ else if (cVerbs == 1)
+ {
+ //One verb without Convert, one item.
+ LPTSTR lpsz = (fIsLink ? szLinkCmd1Verb : szObjectCmd1Verb);
+
+ // strip ampersands from lpszVerbName to ensure that
+ // the right character is used as the menu key
+ LPTSTR pchIn;
+ LPTSTR pchOut;
+ pchIn = pchOut = lpszVerbName;
+ while (*pchIn)
+ {
+ while (*pchIn && '&' == *pchIn)
+ {
+ pchIn++;
+ }
+ *pchOut = *pchIn;
+ pchOut++;
+ pchIn++;
+ }
+ *pchOut = 0;
+
+ FormatString2(szBuffer, lpsz, lpszVerbName, lpszShortTypeName);
+
+ // 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 ? szLinkCmdNVerb: szObjectCmdNVerb),
+ (lpszShortTypeName ? lpszShortTypeName : TEXT(""))
+ );
+ uFlags |= MF_ENABLED | MF_POPUP;
+ uIDVerbMin=(UINT)*lphMenu;
+ }
+
+ if (!InsertMenu(hMenu, uPos, uFlags, uIDVerbMin, szBuffer))
+ {
+AVMError:
+ InsertMenu(hMenu, uPos, MF_GRAYED | uFlags,
+ uIDVerbMin, szNoObjectCmd);
+ fResult = FALSE;
+ }
+
+ if (lpszVerbName)
+ OleStdFree(lpszVerbName);
+ if (!lpszShortType && lpszShortTypeName)
+ OleStdFree((LPVOID)lpszShortTypeName);
+ if (lpEnumOleVerb)
+ lpEnumOleVerb->Release();
+ return fResult;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Support for special error prompts
+
+typedef struct tagPROMPTUSER
+{
+ va_list argptr;
+ UINT nIDD; // dialog/help ID
+ LPTSTR szTitle;
+} PROMPTUSER, *PPROMPTUSER, FAR* LPPROMPTUSER;
+
+/* 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 PromptUserDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ SendDlgItemMessage(hDlg, IDC_PU_ICON,
+ STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_EXCLAMATION), 0L);
+
+ LPPROMPTUSER lpPU = (LPPROMPTUSER)lParam;
+ SetProp(hDlg, STRUCTUREPROP, lpPU);
+ SetWindowText(hDlg, lpPU->szTitle);
+
+ TCHAR szFormat[256];
+ GetDlgItemText(hDlg, IDC_PU_TEXT, szFormat,
+ sizeof(szFormat)/sizeof(TCHAR));
+ TCHAR szBuf[256];
+ wvsprintf(szBuf, szFormat, lpPU->argptr);
+ SetDlgItemText(hDlg, IDC_PU_TEXT, szBuf);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ EndDialog(hDlg, wParam);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+//+---------------------------------------------------------------------------
+//
+// Function: OleUIPromptUserInternal
+//
+// Synopsis: internal entry point to start the PromptUser dialog
+// Used to support both ANSI and Unicode entrypoints
+//
+// Arguments: [nTemplate] - dialog template ID
+// [szTitle] - the title string
+// [hwndParent] - the dialog's parent window
+// [arglist] - variable argument list
+//
+// History: 12-01-94 stevebl Created
+//
+//----------------------------------------------------------------------------
+
+int OleUIPromptUserInternal(int nTemplate, HWND hwndParent, LPTSTR szTitle, va_list arglist)
+{
+ PROMPTUSER pu;
+ pu.szTitle = szTitle;
+ pu.argptr = arglist;
+ pu.nIDD = nTemplate;
+ return (DialogBoxParam(_g_hOleStdResInst, MAKEINTRESOURCE(nTemplate), hwndParent,
+ PromptUserDlgProc, (LPARAM)&pu));
+}
+
+/* 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
+ * (IDC_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 FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...)
+{
+ va_list arglist;
+ va_start(arglist, hwndParent);
+ LPTSTR szTitle = va_arg(arglist, LPTSTR);
+ int nRet = OleUIPromptUserInternal(nTemplate, hwndParent, szTitle, arglist);
+ 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:
+ *
+ */
+
+#define UPDATELINKS_STARTDELAY 2000 // delay before 1st link updates
+
+BOOL CALLBACK 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(GHND, 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)
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC,0L);
+ return FALSE;
+ }
+
+ if (bWin4)
+ {
+ if (StandardInitCommonControls() >= 0)
+ {
+ // get rect of the existing "progress" control
+ RECT rect;
+ GetWindowRect(GetDlgItem(hDlg, IDC_UL_METER), &rect);
+ ScreenToClient(hDlg, ((POINT*)&rect)+0);
+ ScreenToClient(hDlg, ((POINT*)&rect)+1);
+
+ // create progress control in that rect
+ HWND hProgress = CreateWindowEx(
+ 0, PROGRESS_CLASS, NULL, WS_CHILD|WS_VISIBLE,
+ rect.left, rect.top,
+ rect.right-rect.left, rect.bottom-rect.top, hDlg,
+ (HMENU)IDC_UL_PROGRESS, _g_hOleStdInst, NULL);
+ if (hProgress != NULL)
+ {
+ // initialize the progress control
+ SendMessage(hProgress, PBM_SETRANGE, 0, MAKELONG(0, 100));
+
+ // hide the other "meter" control
+ StandardShowDlgItem(hDlg, IDC_UL_METER, SW_HIDE);
+ }
+ }
+ }
+
+ *lplpUL = (LPUPDATELINKS)lParam;
+ if ((*lplpUL)->lpszTitle)
+ {
+ SetWindowText(hDlg, (*lplpUL)->lpszTitle);
+ }
+ SetTimer(hDlg, 1, UPDATELINKS_STARTDELAY, NULL);
+ return TRUE;
+ }
+
+ case WM_TIMER:
+ KillTimer(hDlg, 1);
+ gh = GetProp(hDlg, STRUCTUREPROP);
+
+ if (NULL!=gh)
+ {
+ // gh was locked previously, lock and unlock to get lplpUL
+ lplpUL = (LPUPDATELINKS*)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->GetNextLink(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->GetLinkUpdateOptions(
+ lpUL->dwLink, (LPDWORD)&dwUpdateOpt);
+
+ if ((hErr == NOERROR) && (dwUpdateOpt == OLEUPDATE_ALWAYS))
+ {
+ hErr = lpUL->lpOleUILinkCntr->UpdateLink(lpUL->dwLink, FALSE, FALSE);
+ lpUL->fError |= (hErr != NOERROR);
+ lpUL->cUpdated++;
+
+ nPercent = (lpUL->cLinks > 0) ? (lpUL->cUpdated * 100 / lpUL->cLinks) : 100;
+ if (nPercent <= 100)
+ {
+ // update percentage
+ wsprintf(szPercent, TEXT("%d%%"), nPercent);
+ SetDlgItemText(hDlg, IDC_UL_PERCENT, szPercent);
+
+ HWND hProgress = GetDlgItem(hDlg, IDC_UL_PROGRESS);
+ if (hProgress == NULL)
+ {
+ // update indicator
+ hwndMeter = GetDlgItem(hDlg, IDC_UL_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);
+ }
+ }
+ else
+ {
+ // update the progress indicator
+ SendMessage(hProgress, PBM_SETPOS, nPercent, 0);
+ }
+ }
+ }
+
+ 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;
+
+ case WM_U_SHOWWINDOW:
+ ShowWindow(hDlg, SW_SHOW);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/* OleUIUpdateLinkS
+ * ----------------
+ *
+ * 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 or user aborted dialog
+ * FALSE oherwise
+ */
+STDAPI_(BOOL) OleUIUpdateLinks(
+ LPOLEUILINKCONTAINER lpOleUILinkCntr, HWND hwndParent, LPTSTR lpszTitle, int cLinks)
+{
+ LPUPDATELINKS lpUL = (LPUPDATELINKS)OleStdMalloc(sizeof(UPDATELINKS));
+ BOOL fError = TRUE;
+
+
+ // Validate interface.
+ if (NULL == lpOleUILinkCntr || IsBadReadPtr(lpOleUILinkCntr, sizeof(IOleUILinkContainer)))
+ goto Error;
+
+
+ // Validate parent-window handle. NULL is considered valid.
+ if (NULL != hwndParent && !IsWindow(hwndParent))
+ goto Error;
+
+ // Validate the dialog title. NULL is considered valid.
+ if (NULL != lpszTitle && IsBadReadPtr(lpszTitle, 1))
+ goto Error;
+
+ if (cLinks < 0)
+ goto Error;
+
+ 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(_g_hOleStdResInst, MAKEINTRESOURCE(IDD_UPDATELINKS),
+ hwndParent, UpdateLinksDlgProc, (LPARAM)lpUL);
+
+ fError = lpUL->fError;
+Error:
+ OleStdFree((LPVOID)lpUL);
+
+ return !fError;
+}