summaryrefslogtreecommitdiffstats
path: root/private/ole2ui32/objprop.cpp
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ole2ui32/objprop.cpp
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ole2ui32/objprop.cpp')
-rw-r--r--private/ole2ui32/objprop.cpp1335
1 files changed, 1335 insertions, 0 deletions
diff --git a/private/ole2ui32/objprop.cpp b/private/ole2ui32/objprop.cpp
new file mode 100644
index 000000000..20b3cabc6
--- /dev/null
+++ b/private/ole2ui32/objprop.cpp
@@ -0,0 +1,1335 @@
+/*
+ * OBJPROP.CPP
+ *
+ * Implements the OleUIObjectProperties function which invokes the complete
+ * Object Properties dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#include "precomp.h"
+#include "common.h"
+#include "utility.h"
+#include "iconbox.h"
+#include "resimage.h"
+#include <stddef.h>
+
+OLEDBGDATA
+
+// Internally used structure
+typedef struct tagGNRLPROPS
+{
+ // Keep this item first as the Standard* functions depend on it here.
+ LPOLEUIGNRLPROPS lpOGP; // Original structure passed.
+ UINT nIDD; // IDD of dialog (used for help info)
+
+ CLSID clsidNew; // new class ID (if conversion done)
+
+} GNRLPROPS, *PGNRLPROPS, FAR* LPGNRLPROPS;
+
+typedef struct tagVIEWPROPS
+{
+ // Keep this item first as the Standard* functions depend on it here.
+ LPOLEUIVIEWPROPS lpOVP; // Original structure passed.
+ UINT nIDD; // IDD of dialog (used for help info)
+
+ BOOL bIconChanged;
+ int nCurrentScale;
+ BOOL bRelativeToOrig;
+ DWORD dvAspect;
+
+} VIEWPROPS, *PVIEWPROPS, FAR* LPVIEWPROPS;
+
+typedef struct tagLINKPROPS
+{
+ // Keep this item first as the Standard* functions depend on it here.
+ LPOLEUILINKPROPS lpOLP; // Original structure passed.
+ UINT nIDD; // IDD of dialog (used for help info)
+
+ DWORD dwUpdate; // original update mode
+ LPTSTR lpszDisplayName;// new link source
+ ULONG nFileLength; // file name part of source
+
+} LINKPROPS, *PLINKPROPS, FAR* LPLINKPROPS;
+
+// Internal function prototypes
+// OBJPROP.CPP
+
+/*
+ * OleUIObjectProperties
+ *
+ * Purpose:
+ * Invokes the standard OLE Object Properties dialog box allowing the user
+ * to change General, View, and Link properties of an OLE object. This
+ * dialog uses the new Windows 95 tabbed dialogs.
+ *
+ * Parameters:
+ * lpOP LPOLEUIObjectProperties pointing to the in-out structure
+ * for this dialog.
+ *
+ * Return Value:
+ * UINT One of the following codes, indicating success or error:
+ * OLEUI_SUCCESS Success
+ * OLEUI_ERR_STRUCTSIZE The dwStructSize value is wrong
+ *
+ */
+
+static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS);
+static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS);
+
+STDAPI_(UINT) OleUIObjectProperties(LPOLEUIOBJECTPROPS lpOP)
+{
+#ifdef UNICODE
+ return (InternalObjectProperties(lpOP, TRUE));
+#else
+ return (InternalObjectProperties(lpOP, FALSE));
+#endif
+}
+
+UINT InternalObjectProperties(LPOLEUIOBJECTPROPS lpOP, BOOL fWide)
+{
+ // Validate Parameters
+ UINT uRet = ValidateObjectProperties(lpOP);
+ if (OLEUI_SUCCESS != uRet)
+ return uRet;
+
+ if (NULL == lpOP->lpObjInfo)
+ {
+ return(OLEUI_OPERR_OBJINFOINVALID);
+ }
+
+ if (IsBadReadPtr(lpOP->lpObjInfo, sizeof(IOleUIObjInfo)))
+ {
+ return(OLEUI_OPERR_OBJINFOINVALID);
+ }
+
+ if (lpOP->dwFlags & OPF_OBJECTISLINK)
+ {
+ if (NULL == lpOP->lpLinkInfo)
+ {
+ return(OLEUI_OPERR_LINKINFOINVALID);
+ }
+
+ if (IsBadReadPtr(lpOP->lpLinkInfo, sizeof(IOleUILinkInfo)))
+ {
+ return(OLEUI_OPERR_LINKINFOINVALID);
+ }
+ }
+
+ // Fill Missing values in lpPS
+ LPPROPSHEETHEADER lpPS = (LPPROPSHEETHEADER)lpOP->lpPS;
+ LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lpPS->ppsp;
+ uRet = PrepareObjectProperties(lpOP);
+ if (OLEUI_SUCCESS != uRet)
+ return uRet;
+
+ LPTSTR lpszShortType = NULL;
+ lpOP->lpObjInfo->GetObjectInfo(lpOP->dwObject, NULL, NULL,
+ NULL, &lpszShortType, NULL);
+ if (lpszShortType == NULL)
+ return OLEUI_ERR_OLEMEMALLOC;
+
+ TCHAR szCaption[256];
+ if (lpPS->pszCaption == NULL)
+ {
+ TCHAR szTemp[256];
+ LoadString(_g_hOleStdResInst,
+ (lpOP->dwFlags & OPF_OBJECTISLINK) ?
+ IDS_LINKOBJECTPROPERTIES : IDS_OBJECTPROPERTIES,
+ szTemp, sizeof(szTemp));
+ wsprintf(szCaption, szTemp, lpszShortType);
+#ifdef UNICODE
+ if (!fWide)
+ {
+ // We're going to actually call the ANSI version of PropertySheet,
+ // so we need to store the caption as an ANSI string.
+ lstrcpy(szTemp, szCaption);
+ WTOA((char *)szCaption, szTemp, 256);
+ }
+#endif
+ lpPS->pszCaption = szCaption;
+ }
+ OleStdFree(lpszShortType);
+ // Invoke the property sheet
+ int nResult = StandardPropertySheet(lpOP->lpPS, fWide);
+
+ // Cleanup any temporary memory allocated during the process
+ if (lpPP == NULL)
+ {
+ OleStdFree((LPVOID)lpOP->lpPS->ppsp);
+ lpOP->lpPS->ppsp = NULL;
+ }
+
+ // map PropertPage return value to OLEUI_ return code
+ if (nResult < 0)
+ uRet = OLEUI_OPERR_PROPERTYSHEET;
+ else if (nResult == 0)
+ uRet = OLEUI_CANCEL;
+ else
+ uRet = OLEUI_OK;
+
+ return uRet;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Validation code
+
+static UINT WINAPI ValidateGnrlProps(LPOLEUIGNRLPROPS lpGP)
+{
+ OleDbgAssert(lpGP != NULL);
+
+ if (lpGP->cbStruct != sizeof(OLEUIGNRLPROPS))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+ if (lpGP->lpfnHook && IsBadCodePtr((FARPROC)lpGP->lpfnHook))
+ return OLEUI_ERR_LPFNHOOKINVALID;
+
+ return OLEUI_SUCCESS;
+}
+
+static UINT WINAPI ValidateViewProps(LPOLEUIVIEWPROPS lpVP)
+{
+ OleDbgAssert(lpVP != NULL);
+
+ if (lpVP->cbStruct != sizeof(OLEUIVIEWPROPS))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+ if (lpVP->lpfnHook && IsBadCodePtr((FARPROC)lpVP->lpfnHook))
+ return OLEUI_ERR_LPFNHOOKINVALID;
+
+ return OLEUI_SUCCESS;
+}
+
+static UINT WINAPI ValidateLinkProps(LPOLEUILINKPROPS lpLP)
+{
+ OleDbgAssert(lpLP != NULL);
+
+ if (lpLP->cbStruct != sizeof(OLEUILINKPROPS))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+ if (lpLP->lpfnHook && IsBadCodePtr((FARPROC)lpLP->lpfnHook))
+ return OLEUI_ERR_LPFNHOOKINVALID;
+
+ return OLEUI_SUCCESS;
+}
+
+static UINT WINAPI ValidateObjectProperties(LPOLEUIOBJECTPROPS lpOP)
+{
+ // Validate LPOLEUIOBJECTPROPS lpOP
+ if (lpOP == NULL)
+ return OLEUI_ERR_STRUCTURENULL;
+
+ if (IsBadWritePtr(lpOP, sizeof(OLEUIOBJECTPROPS)))
+ return OLEUI_ERR_STRUCTUREINVALID;
+
+ // Validate cbStruct field of OLEUIOBJECTPROPS
+ if (lpOP->cbStruct != sizeof(OLEUIOBJECTPROPS))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+
+ // Validate "sub" property pointers
+ if (lpOP->lpGP == NULL || lpOP->lpVP == NULL ||
+ ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP == NULL))
+ return OLEUI_OPERR_SUBPROPNULL;
+
+ if (IsBadWritePtr(lpOP->lpGP, sizeof(OLEUIGNRLPROPS)) ||
+ IsBadWritePtr(lpOP->lpVP, sizeof(OLEUIVIEWPROPS)) ||
+ ((lpOP->dwFlags & OPF_OBJECTISLINK) &&
+ IsBadWritePtr(lpOP->lpLP, sizeof(OLEUILINKPROPS))))
+ return OLEUI_OPERR_SUBPROPINVALID;
+
+ // Validate property sheet data pointers
+ LPPROPSHEETHEADER lpPS = lpOP->lpPS;
+ if (lpPS == NULL)
+ return OLEUI_OPERR_PROPSHEETNULL;
+
+ if (IsBadWritePtr(lpPS, sizeof(PROPSHEETHEADER)))
+ return OLEUI_OPERR_PROPSHEETINVALID;
+
+ DWORD dwSize = lpPS->dwSize;
+ if (dwSize < sizeof(PROPSHEETHEADER))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+
+ // If links specified, validate "sub" link property pointer
+ if (lpOP->dwFlags & OPF_OBJECTISLINK)
+ {
+ if (lpPS->ppsp != NULL && lpPS->nPages < 3)
+ return OLEUI_OPERR_PAGESINCORRECT;
+ }
+ else
+ {
+ if (lpPS->ppsp != NULL && lpPS->nPages < 2)
+ return OLEUI_OPERR_PAGESINCORRECT;
+ }
+
+ if (lpPS->ppsp != NULL &&
+ IsBadWritePtr((PROPSHEETPAGE*)lpPS->ppsp,
+ lpPS->nPages * sizeof(PROPSHEETPAGE)))
+ {
+ return OLEUI_OPERR_INVALIDPAGES;
+ }
+
+ // not setting PSH_PROPSHEETPAGE is not supported
+ if (lpOP->dwFlags & OPF_NOFILLDEFAULT)
+ {
+ if (!(lpPS->dwFlags & PSH_PROPSHEETPAGE))
+ return OLEUI_OPERR_NOTSUPPORTED;
+ }
+ else if (lpPS->dwFlags != 0)
+ {
+ return OLEUI_OPERR_NOTSUPPORTED;
+ }
+
+ // Sanity check any pages provided
+ for (UINT nPage = 0; nPage < lpPS->nPages; nPage++)
+ {
+ LPPROPSHEETPAGE lpPP = (PROPSHEETPAGE*)&lpPS->ppsp[nPage];
+ if (lpPP->dwSize != sizeof(PROPSHEETPAGE))
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+ if (lpPP->pfnDlgProc != NULL)
+ return OLEUI_OPERR_DLGPROCNOTNULL;
+ if (lpPP->lParam != 0)
+ return OLEUI_OPERR_LPARAMNOTZERO;
+ }
+
+ // validate individual prop page structures
+ UINT uRet = ValidateGnrlProps(lpOP->lpGP);
+ if (uRet != OLEUI_SUCCESS)
+ return uRet;
+ uRet = ValidateViewProps(lpOP->lpVP);
+ if (uRet != OLEUI_SUCCESS)
+ return uRet;
+ if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL)
+ {
+ uRet = ValidateLinkProps(lpOP->lpLP);
+ if (uRet != OLEUI_SUCCESS)
+ return uRet;
+ }
+
+ return OLEUI_SUCCESS;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GnrlPropsDialogProc and helpers
+
+// takes a DWORD add commas etc to it and puts the result in the buffer
+LPTSTR AddCommas(DWORD dw, LPTSTR pszResult, UINT nMax)
+{
+ NUMBERFMT numberFmt;
+ numberFmt.NumDigits = 0;
+ numberFmt.LeadingZero = 0;
+
+ TCHAR szSep[5];
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szSep, sizeof(szSep));
+ numberFmt.Grouping = Atol(szSep);
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szSep, sizeof(szSep));
+ numberFmt.lpDecimalSep = numberFmt.lpThousandSep = szSep;
+ numberFmt.NegativeOrder= 0;
+
+ TCHAR szTemp[64];
+ wsprintf(szTemp, TEXT("%lu"), dw);
+
+ GetNumberFormat(LOCALE_USER_DEFAULT, 0, szTemp, &numberFmt, pszResult, nMax);
+ return pszResult;
+}
+
+const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB, IDS_ORDERGB, IDS_ORDERTB};
+
+/* converts numbers into short formats
+ * 532 -> 523 bytes
+ * 1340 -> 1.3KB
+ * 23506 -> 23.5KB
+ * -> 2.4MB
+ * -> 5.2GB
+ */
+LPTSTR ShortSizeFormat64(__int64 dw64, LPTSTR szBuf)
+{
+ int i;
+ UINT wInt, wLen, wDec;
+ TCHAR szTemp[10], szOrder[20], szFormat[5];
+
+ if (dw64 < 1000)
+ {
+ wsprintf(szTemp, TEXT("%d"), DWORD(dw64));
+ i = 0;
+ }
+ else
+ {
+ for (i = 1; i < (sizeof(pwOrders)/sizeof(pwOrders))-1
+ && dw64 >= 1000L * 1024L; dw64 >>= 10, i++)
+ ; /* do nothing */
+
+ wInt = DWORD(dw64 >> 10);
+ AddCommas(wInt, szTemp, sizeof(szTemp)/sizeof(TCHAR));
+ wLen = lstrlen(szTemp);
+ if (wLen < 3)
+ {
+ wDec = DWORD(dw64 - (__int64)wInt * 1024L) * 1000 / 1024;
+ // At this point, wDec should be between 0 and 1000
+ // we want get the top one (or two) digits.
+ wDec /= 10;
+ if (wLen == 2)
+ wDec /= 10;
+
+ // Note that we need to set the format before getting the
+ // intl char.
+ lstrcpy(szFormat, TEXT("%02d"));
+
+ szFormat[2] = '0' + 3 - wLen;
+ GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL,
+ szTemp+wLen, sizeof(szTemp)-wLen);
+ wLen = lstrlen(szTemp);
+ wLen += wsprintf(szTemp+wLen, szFormat, wDec);
+ }
+ }
+
+ LoadString(_g_hOleStdResInst, pwOrders[i], szOrder, sizeof(szOrder));
+ wsprintf(szBuf, szOrder, (LPSTR)szTemp);
+
+ return szBuf;
+}
+
+LPTSTR WINAPI ShortSizeFormat(DWORD dw, LPTSTR szBuf)
+{
+ return ShortSizeFormat64((__int64)dw, szBuf);
+}
+
+BOOL FGnrlPropsRefresh(HWND hDlg, LPGNRLPROPS lpGP)
+{
+ // get object information and fill in default fields
+ LPOLEUIOBJECTPROPS lpOP = lpGP->lpOGP->lpOP;
+ LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo;
+
+ // get object's icon
+ HGLOBAL hMetaPict;
+ lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL);
+ if (hMetaPict != NULL)
+ {
+ HICON hIcon = OleUIMetafilePictExtractIcon(hMetaPict);
+ SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON, STM_SETICON,
+ (WPARAM)hIcon, 0);
+ }
+ OleUIMetafilePictIconFree(hMetaPict);
+
+ // get type, short type, location, and size of object
+ DWORD dwObjSize;
+ LPTSTR lpszLabel = NULL;
+ LPTSTR lpszType = NULL;
+ LPTSTR lpszShortType = NULL;
+ LPTSTR lpszLocation = NULL;
+ lpObjInfo->GetObjectInfo(lpOP->dwObject, &dwObjSize, &lpszLabel,
+ &lpszType, &lpszShortType, &lpszLocation);
+
+ // set name, type, and size of object
+ SetDlgItemText(hDlg, IDC_GP_OBJECTNAME, lpszLabel);
+ SetDlgItemText(hDlg, IDC_GP_OBJECTTYPE, lpszType);
+ SetDlgItemText(hDlg, IDC_GP_OBJECTLOCATION, lpszLocation);
+ TCHAR szTemp[128];
+ if (dwObjSize == (DWORD)-1)
+ {
+ LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szTemp, 64);
+ SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp);
+ }
+ else
+ {
+ // get the master formatting string
+ TCHAR szFormat[64];
+ LoadString(_g_hOleStdResInst, IDS_OBJECTSIZE, szFormat, 64);
+
+ // format the size in two ways (short, and with commas)
+ TCHAR szNum1[20], szNum2[32];
+ ShortSizeFormat(dwObjSize, szNum1);
+ AddCommas(dwObjSize, szNum2, 32);
+ FormatString2(szTemp, szFormat, szNum1, szNum2);
+
+ // set the control's text
+ SetDlgItemText(hDlg, IDC_GP_OBJECTSIZE, szTemp);
+ }
+
+ // enable/disable convert button as necessary
+ BOOL bEnable = TRUE;
+ if (lpOP->dwFlags & (OPF_OBJECTISLINK|OPF_DISABLECONVERT))
+ bEnable = FALSE;
+ else
+ {
+ CLSID clsid; WORD wFormat;
+ lpObjInfo->GetConvertInfo(lpOP->dwObject, &clsid, &wFormat, NULL, NULL, NULL);
+ bEnable = OleUICanConvertOrActivateAs(clsid, FALSE, wFormat);
+ }
+ StandardEnableDlgItem(hDlg, IDC_GP_CONVERT, bEnable);
+
+ // cleanup temporary info strings
+ OleStdFree(lpszLabel);
+ OleStdFree(lpszType);
+ OleStdFree(lpszShortType);
+ OleStdFree(lpszLocation);
+
+ return TRUE;
+}
+
+BOOL FGnrlPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ // Copy the structure at lParam into our instance memory.
+ HFONT hFont;
+ LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardInit(hDlg, sizeof(GNRLPROPS), &hFont);
+
+ // LpvStandardInit send a termination to us already.
+ if (NULL == lpGP)
+ return FALSE;
+
+ LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
+ LPOLEUIGNRLPROPS lpOGP = (LPOLEUIGNRLPROPS)lpPP->lParam;
+ lpGP->lpOGP = lpOGP;
+ lpGP->nIDD = IDD_GNRLPROPS;
+
+ // If we got a font, send it to the necessary controls.
+ if (NULL != hFont)
+ {
+ SendDlgItemMessage(hDlg, IDC_GP_OBJECTNAME, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDC_GP_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDC_GP_OBJECTLOCATION, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDC_GP_OBJECTSIZE, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+ // Initialize the controls
+ FGnrlPropsRefresh(hDlg, lpGP);
+
+ // Call the hook with lCustData in lParam
+ UStandardHook((PVOID)lpGP, hDlg, WM_INITDIALOG, wParam, lpOGP->lCustData);
+ return TRUE;
+}
+
+BOOL CALLBACK GnrlPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ // Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ // This will fail under WM_INITDIALOG, where we allocate it.
+ UINT uHook = 0;
+ LPGNRLPROPS lpGP = (LPGNRLPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
+
+ // If the hook processed the message, we're done.
+ if (0 != uHook)
+ return (BOOL)uHook;
+
+ // Get pointers to important info
+ LPOLEUIGNRLPROPS lpOGP = NULL;
+ LPOLEUIOBJECTPROPS lpOP = NULL;
+ LPOLEUIOBJINFO lpObjInfo = NULL;
+ if (lpGP != NULL)
+ {
+ lpOGP = lpGP->lpOGP;
+ if (lpOGP != NULL)
+ {
+ lpObjInfo = lpOGP->lpOP->lpObjInfo;
+ lpOP = lpOGP->lpOP;
+ }
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FGnrlPropsInit(hDlg, wParam, lParam);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDC_GP_CONVERT:
+ {
+ // Call up convert dialog to obtain new CLSID
+ OLEUICONVERT cv; memset(&cv, 0, sizeof(cv));
+ cv.cbStruct = sizeof(cv);
+ cv.dwFlags |= CF_CONVERTONLY;
+ if (lpOP->dwFlags & OPF_SHOWHELP)
+ cv.dwFlags |= CF_SHOWHELPBUTTON;
+ cv.clsidConvertDefault = lpGP->clsidNew;
+ cv.dvAspect = DVASPECT_CONTENT;
+ lpObjInfo->GetObjectInfo(lpOP->dwObject,
+ NULL, NULL, &cv.lpszUserType, NULL, NULL);
+ lpObjInfo->GetConvertInfo(lpOP->dwObject,
+ &cv.clsid, &cv.wFormat, &cv.clsidConvertDefault,
+ &cv.lpClsidExclude, &cv.cClsidExclude);
+ cv.fIsLinkedObject =
+ (lpOGP->lpOP->dwFlags & OPF_OBJECTISLINK);
+ if (cv.clsidConvertDefault != CLSID_NULL)
+ cv.dwFlags |= CF_SETCONVERTDEFAULT;
+ cv.hWndOwner = GetParent(GetParent(hDlg));
+
+ // allow caller to hook the convert structure
+ uHook = UStandardHook(lpGP, hDlg, uMsgConvert, 0, (LPARAM)&cv);
+ if (0 == uHook)
+ {
+ uHook = (OLEUI_OK == OleUIConvert(&cv));
+ SetFocus(hDlg);
+ }
+
+ // check to see dialog results
+ if (uHook != 0 && (cv.dwFlags & CF_SELECTCONVERTTO))
+ {
+ lpGP->clsidNew = cv.clsidNew;
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ }
+ }
+ return TRUE;
+ }
+ break;
+
+ case PSM_QUERYSIBLINGS:
+ SetWindowLong(hDlg, DWL_MSGRESULT, 0);
+ switch (wParam)
+ {
+ case OLEUI_QUERY_GETCLASSID:
+ *(CLSID*)lParam = lpGP->clsidNew;
+ SetWindowLong(hDlg, DWL_MSGRESULT, 1);
+ return TRUE;
+
+ case OLEUI_QUERY_LINKBROKEN:
+ FGnrlPropsRefresh(hDlg, lpGP);
+ return TRUE;
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((NMHDR*)lParam)->code)
+ {
+ case PSN_HELP:
+ PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_GNRLPROPS, 0));
+ break;
+ case PSN_APPLY:
+ // apply changes if changes made
+ if (lpGP->clsidNew != CLSID_NULL)
+ {
+ // convert the object -- fail the apply if convert fails
+ if (NOERROR != lpObjInfo->ConvertObject(lpOP->dwObject,
+ lpGP->clsidNew))
+ {
+ SetWindowLong(hDlg, DWL_MSGRESULT, 1);
+ return TRUE;
+ }
+ lpGP->clsidNew = CLSID_NULL;
+ }
+ SetWindowLong(hDlg, DWL_MSGRESULT, 0);
+ PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ {
+ HICON hIcon = (HICON)SendDlgItemMessage(hDlg, IDC_GP_OBJECTICON,
+ STM_GETICON, 0, 0);
+ if (hIcon != NULL)
+ DestroyIcon(hIcon);
+ StandardCleanup((PVOID)lpGP, hDlg);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// ViewPropsDialogProc and helpers
+
+void EnableDisableScaleControls(LPVIEWPROPS lpVP, HWND hDlg)
+{
+ LPOLEUIVIEWPROPS lpOVP = lpVP->lpOVP;
+ BOOL bEnable = !(lpOVP->dwFlags & VPF_DISABLESCALE) &&
+ SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0) == 0;
+ StandardEnableDlgItem(hDlg, IDC_VP_SPIN, bEnable);
+ StandardEnableDlgItem(hDlg, IDC_VP_PERCENT, bEnable);
+ StandardEnableDlgItem(hDlg, IDC_VP_SCALETXT, bEnable);
+ bEnable = bEnable && !(lpOVP->dwFlags & VPF_DISABLERELATIVE);
+ StandardEnableDlgItem(hDlg, IDC_VP_RELATIVE, bEnable);
+}
+
+BOOL FViewPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ // Copy the structure at lParam into our instance memory.
+ LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardInit(hDlg, sizeof(VIEWPROPS));
+
+ // LpvStandardInit send a termination to us already.
+ if (NULL == lpVP)
+ return FALSE;
+
+ LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
+ LPOLEUIVIEWPROPS lpOVP = (LPOLEUIVIEWPROPS)lpPP->lParam;
+ lpVP->lpOVP = lpOVP;
+ lpVP->nIDD = IDD_VIEWPROPS;
+
+ // get object information and fill in default fields
+ LPOLEUIOBJECTPROPS lpOP = lpOVP->lpOP;
+ LPOLEUIOBJINFO lpObjInfo = lpOP->lpObjInfo;
+
+ // initialize icon and scale variables
+ HGLOBAL hMetaPict;
+ DWORD dvAspect;
+ int nCurrentScale;
+ lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict,
+ &dvAspect, &nCurrentScale);
+ SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET,
+ 0, (LPARAM)hMetaPict);
+ lpVP->nCurrentScale = nCurrentScale;
+ lpVP->dvAspect = dvAspect;
+
+ // Initialize the result image
+ SendDlgItemMessage(hDlg, IDC_VP_RESULTIMAGE,
+ RIM_IMAGESET, RESULTIMAGE_EDITABLE, 0L);
+
+ // Initialize controls
+ CheckRadioButton(hDlg, IDC_VP_EDITABLE, IDC_VP_ASICON,
+ dvAspect == DVASPECT_CONTENT ? IDC_VP_EDITABLE : IDC_VP_ASICON);
+ SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_SETCHECK,
+ (lpOVP->dwFlags & VPF_SELECTRELATIVE) != 0, 0L);
+ if (!(lpOVP->dwFlags & VPF_DISABLESCALE))
+ SetDlgItemInt(hDlg, IDC_VP_PERCENT, nCurrentScale, FALSE);
+ lpVP->bRelativeToOrig = SendDlgItemMessage(hDlg, IDC_VP_RELATIVE,
+ BM_GETCHECK, 0, 0) != 0;
+
+ // Setup up-down control as buddy to IDC_VP_PERCENT
+ HWND hWndSpin = CreateWindowEx(0, UPDOWN_CLASS, NULL,
+ WS_CHILD|UDS_SETBUDDYINT|UDS_ARROWKEYS|UDS_ALIGNRIGHT, 0, 0, 0, 0,
+ hDlg, (HMENU)IDC_VP_SPIN, _g_hOleStdInst, NULL);
+ if (hWndSpin != NULL)
+ {
+ SendMessage(hWndSpin, UDM_SETRANGE, 0,
+ MAKELPARAM(lpOVP->nScaleMax, lpOVP->nScaleMin));
+ SendMessage(hWndSpin, UDM_SETPOS, 0, nCurrentScale);
+ SendMessage(hWndSpin, UDM_SETBUDDY,
+ (WPARAM)GetDlgItem(hDlg, IDC_VP_PERCENT), 0);
+ ShowWindow(hWndSpin, SW_SHOW);
+ }
+ EnableDisableScaleControls(lpVP, hDlg);
+
+ // Call the hook with lCustData in lParam
+ UStandardHook((PVOID)lpVP, hDlg, WM_INITDIALOG, wParam, lpOVP->lCustData);
+ return TRUE;
+}
+
+BOOL CALLBACK ViewPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ // Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ // This will fail under WM_INITDIALOG, where we allocate it.
+ UINT uHook = 0;
+ LPVIEWPROPS lpVP = (LPVIEWPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
+
+ // If the hook processed the message, we're done.
+ if (0 != uHook)
+ return (BOOL)uHook;
+
+ // Get pointers to important info
+ LPOLEUIVIEWPROPS lpOVP = NULL;
+ LPOLEUIOBJECTPROPS lpOP = NULL;
+ LPOLEUIOBJINFO lpObjInfo = NULL;
+ if (lpVP != NULL)
+ {
+ lpOVP = lpVP->lpOVP;
+ if (lpOVP != NULL)
+ {
+ lpObjInfo = lpOVP->lpOP->lpObjInfo;
+ lpOP = lpOVP->lpOP;
+ }
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FViewPropsInit(hDlg, wParam, lParam);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDC_VP_ASICON:
+ case IDC_VP_EDITABLE:
+ EnableDisableScaleControls(lpVP, hDlg);
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ return TRUE;
+
+ case IDC_VP_CHANGEICON:
+ {
+ // Call up Change Icon dialog to obtain new icon
+ OLEUICHANGEICON ci; memset(&ci, 0, sizeof(ci));
+ ci.cbStruct = sizeof(ci);
+ ci.dwFlags = CIF_SELECTCURRENT;
+ ci.hWndOwner = GetParent(GetParent(hDlg));
+ ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY,
+ IBXM_IMAGEGET, 0, 0L);
+
+ // get classid to look for (may be new class if conversion applied)
+ SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS,
+ OLEUI_QUERY_GETCLASSID, (LPARAM)&ci.clsid);
+ lpObjInfo->GetConvertInfo(lpOP->dwObject,
+ &ci.clsid, NULL, NULL, NULL, NULL);
+ if (lpOP->dwFlags & OPF_SHOWHELP)
+ ci.dwFlags |= CIF_SHOWHELP;
+
+ // allow the caller to hook the change icon
+ uHook = UStandardHook(lpVP, hDlg, uMsgChangeIcon, 0, (LPARAM)&ci);
+ if (0 == uHook)
+ {
+ uHook = (OLEUI_OK == OleUIChangeIcon(&ci));
+ SetFocus(hDlg);
+ }
+ if (0 != uHook)
+ {
+ // apply the changes
+ SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET, 1,
+ (LPARAM)ci.hMetaPict);
+ lpVP->bIconChanged = TRUE;
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ }
+ }
+ return TRUE;
+
+ case IDC_VP_PERCENT:
+ case IDC_VP_RELATIVE:
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ return TRUE;
+ }
+ break;
+
+ case WM_VSCROLL:
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ break;
+
+ case PSM_QUERYSIBLINGS:
+ SetWindowLong(hDlg, DWL_MSGRESULT, 0);
+ switch (wParam)
+ {
+ case OLEUI_QUERY_LINKBROKEN:
+ if (!lpVP->bIconChanged)
+ {
+ // re-init icon, since user hasn't changed it
+ HGLOBAL hMetaPict;
+ lpObjInfo->GetViewInfo(lpOP->dwObject, &hMetaPict, NULL, NULL);
+ SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGESET,
+ 1, (LPARAM)hMetaPict);
+ }
+ return TRUE;
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((NMHDR*)lParam)->code)
+ {
+ case PSN_HELP:
+ PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_VIEWPROPS, 0));
+ break;
+ case PSN_APPLY:
+ {
+ HGLOBAL hMetaPict = NULL;
+ int nCurrentScale = -1;
+ DWORD dvAspect = (DWORD)-1;
+ BOOL bRelativeToOrig = FALSE;
+
+ // handle icon change
+ if (lpVP->bIconChanged)
+ {
+ hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
+ IDC_VP_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
+ lpVP->bIconChanged = FALSE;
+ }
+
+ // handle scale changes
+ if (IsWindowEnabled(GetDlgItem(hDlg, IDC_VP_PERCENT)))
+ {
+ // parse the percentage entered
+ BOOL bValid;
+ nCurrentScale = GetDlgItemInt(hDlg, IDC_VP_PERCENT, &bValid, FALSE);
+ if (!bValid)
+ {
+ PopupMessage(GetParent(hDlg), IDS_VIEWPROPS,
+ IDS_INVALIDPERCENTAGE, MB_OK|MB_ICONEXCLAMATION);
+
+ // cancel the call
+ SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
+ return TRUE;
+ }
+ // normalize range
+ int nScaleMin, nScaleMax;
+ if (lpOVP->nScaleMin > lpOVP->nScaleMax)
+ {
+ nScaleMin = lpOVP->nScaleMax;
+ nScaleMax = lpOVP->nScaleMin;
+ }
+ else
+ {
+ nScaleMin = lpOVP->nScaleMin;
+ nScaleMax = lpOVP->nScaleMax;
+ }
+ // check range for validity
+ if (nCurrentScale < nScaleMin || nCurrentScale > nScaleMax)
+ {
+ // format appropriate message
+ TCHAR szCaption[128];
+ LoadString(_g_hOleStdResInst, IDS_VIEWPROPS, szCaption, 128);
+ TCHAR szFormat[128];
+ LoadString(_g_hOleStdResInst, IDS_RANGEERROR, szFormat, 128);
+ TCHAR szTemp[256], szNum1[32], szNum2[32];
+ wsprintf(szNum1, _T("%d"), lpOVP->nScaleMin);
+ wsprintf(szNum2, _T("%d"), lpOVP->nScaleMax);
+ FormatString2(szTemp, szFormat, szNum1, szNum2);
+ MessageBox(GetParent(hDlg), szTemp, szCaption, MB_OK|MB_ICONEXCLAMATION);
+
+ // and cancel the call
+ SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_INVALID_NOCHANGEPAGE);
+ return TRUE;
+ }
+
+ // otherwise scale is in correct range
+ bRelativeToOrig =
+ SendDlgItemMessage(hDlg, IDC_VP_RELATIVE, BM_GETCHECK, 0, 0) != 0;
+ if (nCurrentScale != lpVP->nCurrentScale ||
+ bRelativeToOrig != lpVP->bRelativeToOrig)
+ {
+ lpVP->nCurrentScale = nCurrentScale;
+ lpVP->bRelativeToOrig = bRelativeToOrig;
+ }
+ }
+
+ // handle aspect changes
+ if (SendDlgItemMessage(hDlg, IDC_VP_ASICON, BM_GETCHECK, 0, 0L))
+ dvAspect = DVASPECT_ICON;
+ else
+ dvAspect = DVASPECT_CONTENT;
+ if (dvAspect == lpVP->dvAspect)
+ dvAspect = (DWORD)-1;
+ else
+ {
+ lpVP->dvAspect = dvAspect;
+ bRelativeToOrig = 1;
+ }
+
+ lpObjInfo->SetViewInfo(lpOP->dwObject, hMetaPict, dvAspect,
+ nCurrentScale, bRelativeToOrig);
+ }
+ SetWindowLong(hDlg, DWL_MSGRESULT, PSNRET_NOERROR);
+ PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ SendDlgItemMessage(hDlg, IDC_VP_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0);
+ StandardCleanup((PVOID)lpVP, hDlg);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// LinkPropsDialogProc and helpers
+
+static BOOL IsNullTime(const FILETIME* lpFileTime)
+{
+ FILETIME fileTimeNull = { 0, 0 };
+ return CompareFileTime(&fileTimeNull, lpFileTime) == 0;
+}
+
+static BOOL SetDlgItemDate(HWND hDlg, int nID, const FILETIME* lpFileTime)
+{
+ if (IsNullTime(lpFileTime))
+ return FALSE;
+
+ // convert UTC file time to system time
+ FILETIME localTime;
+ FileTimeToLocalFileTime(lpFileTime, &localTime);
+ SYSTEMTIME systemTime;
+ FileTimeToSystemTime(&localTime, &systemTime);
+
+ TCHAR szDate[80];
+ GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systemTime,
+ NULL, szDate, sizeof(szDate));
+
+ SetDlgItemText(hDlg, nID, szDate);
+ return TRUE;
+}
+
+static BOOL SetDlgItemTime(HWND hDlg, int nID, const FILETIME* lpFileTime)
+{
+ if (IsNullTime(lpFileTime))
+ return FALSE;
+
+ // convert UTC file time to system time
+ FILETIME localTime;
+ FileTimeToLocalFileTime(lpFileTime, &localTime);
+ SYSTEMTIME systemTime;
+ FileTimeToSystemTime(&localTime, &systemTime);
+
+ if (systemTime.wHour || systemTime.wMinute || systemTime.wSecond)
+ {
+ TCHAR szTime[80];
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, &systemTime,
+ NULL, szTime, sizeof(szTime));
+
+ SetDlgItemText(hDlg, nID, szTime);
+ }
+ return TRUE;
+}
+
+BOOL FLinkPropsInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ // Copy the structure at lParam into our instance memory.
+ HFONT hFont;
+ LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardInit(hDlg, sizeof(LINKPROPS), &hFont);
+
+ // LpvStandardInit send a termination to us already.
+ if (NULL == lpLP)
+ return FALSE;
+
+ LPPROPSHEETPAGE lpPP = (LPPROPSHEETPAGE)lParam;
+ LPOLEUILINKPROPS lpOLP = (LPOLEUILINKPROPS)lpPP->lParam;
+ lpLP->lpOLP = lpOLP;
+ lpLP->nIDD = IDD_LINKPROPS;
+
+ // If we got a font, send it to the necessary controls.
+ if (NULL != hFont)
+ {
+ // Do this for as many controls as you need it for.
+ SendDlgItemMessage(hDlg, IDC_LP_LINKSOURCE, WM_SETFONT, (WPARAM)hFont, 0);
+ SendDlgItemMessage(hDlg, IDC_LP_DATE, WM_SETFONT, (WPARAM)hFont, 0);
+ SendDlgItemMessage(hDlg, IDC_LP_TIME, WM_SETFONT, (WPARAM)hFont, 0);
+ }
+
+ // general "Unknown" string for unknown items
+ TCHAR szUnknown[64];
+ LoadString(_g_hOleStdResInst, IDS_OLE2UIUNKNOWN, szUnknown, 64);
+
+ // get object information and fill in default fields
+ LPOLEUIOBJECTPROPS lpOP = lpOLP->lpOP;
+ LPOLEUILINKINFO lpLinkInfo = lpOP->lpLinkInfo;
+ FILETIME lastUpdate; memset(&lastUpdate, 0, sizeof(lastUpdate));
+ lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate);
+
+ // initialize time and date static text
+ if (IsNullTime(&lastUpdate))
+ {
+ // time and date are unknown
+ SetDlgItemText(hDlg, IDC_LP_DATE, szUnknown);
+ SetDlgItemText(hDlg, IDC_LP_TIME, szUnknown);
+ }
+ else
+ {
+ // time and date are known
+ SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate);
+ SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate);
+ }
+
+ // initialize source display name
+ LPTSTR lpszDisplayName;
+ lpLinkInfo->GetLinkSource(lpOP->dwLink, &lpszDisplayName,
+ &lpLP->nFileLength, NULL, NULL, NULL, NULL);
+ SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName);
+ OleStdFree(lpszDisplayName);
+
+ // initialize automatic/manual update field
+ DWORD dwUpdate;
+ lpLinkInfo->GetLinkUpdateOptions(lpOP->dwLink, &dwUpdate);
+ CheckRadioButton(hDlg, IDC_LP_AUTOMATIC, IDC_LP_MANUAL,
+ dwUpdate == OLEUPDATE_ALWAYS ? IDC_LP_AUTOMATIC : IDC_LP_MANUAL);
+ lpLP->dwUpdate = dwUpdate;
+
+ // Call the hook with lCustData in lParam
+ UStandardHook((PVOID)lpLP, hDlg, WM_INITDIALOG, wParam, lpOLP->lCustData);
+ return TRUE;
+}
+
+BOOL CALLBACK LinkPropsDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ // Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ // This will fail under WM_INITDIALOG, where we allocate it.
+ UINT uHook = 0;
+ LPLINKPROPS lpLP = (LPLINKPROPS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
+
+ // If the hook processed the message, we're done.
+ if (0 != uHook)
+ return (BOOL)uHook;
+
+ // Get pointers to important info
+ LPOLEUILINKPROPS lpOLP = NULL;
+ LPOLEUIOBJECTPROPS lpOP = NULL;
+ LPOLEUILINKINFO lpLinkInfo;
+ if (lpLP != NULL)
+ {
+ lpOLP = lpLP->lpOLP;
+ if (lpOLP != NULL)
+ {
+ lpLinkInfo = lpOLP->lpOP->lpLinkInfo;
+ lpOP = lpOLP->lpOP;
+ }
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FLinkPropsInit(hDlg, wParam, lParam);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDC_LP_OPENSOURCE:
+ // force update
+ SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0);
+
+ // launch the object
+ lpLinkInfo->OpenLinkSource(lpOP->dwLink);
+
+ // close the dialog
+ SendMessage(GetParent(hDlg), WM_COMMAND, IDOK, 0);
+ break;
+
+ case IDC_LP_UPDATENOW:
+ {
+ // force update
+ SendMessage(GetParent(hDlg), PSM_APPLY, 0, 0);
+
+ // update the link via container provided callback
+ if (lpLinkInfo->UpdateLink(lpOP->dwLink, TRUE, FALSE) != NOERROR)
+ break;
+
+ // since link was updated, update the time/date display
+ SYSTEMTIME systemTime; GetSystemTime(&systemTime);
+ FILETIME localTime; SystemTimeToFileTime(&systemTime, &localTime);
+ FILETIME lastUpdate; LocalFileTimeToFileTime(&localTime, &lastUpdate);
+ lpLinkInfo->GetLastUpdate(lpOP->dwLink, &lastUpdate);
+
+ SetDlgItemDate(hDlg, IDC_LP_DATE, &lastUpdate);
+ SetDlgItemTime(hDlg, IDC_LP_TIME, &lastUpdate);
+
+ // modification that cannot be undone
+ SendMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
+ }
+ break;
+
+ case IDC_LP_BREAKLINK:
+ {
+ UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS,
+ IDS_CONFIRMBREAKLINK, MB_YESNO|MB_ICONQUESTION);
+ if (uRet == IDYES)
+ {
+ // cancel the link turning it into a picture
+ lpLinkInfo->CancelLink(lpOP->dwLink);
+
+ // allow other pages to refresh
+ lpOP->dwFlags &= ~OPF_OBJECTISLINK;
+ SendMessage(GetParent(hDlg), PSM_QUERYSIBLINGS,
+ OLEUI_QUERY_LINKBROKEN, 0);
+
+ // remove the links page (since this is no longer a link)
+ SendMessage(GetParent(hDlg), PSM_REMOVEPAGE, 2, 0);
+
+ }
+ }
+ break;
+
+ case IDC_LP_CHANGESOURCE:
+ {
+ // get current source in OLE memory
+ UINT nLen = GetWindowTextLength(GetDlgItem(hDlg, IDC_LP_LINKSOURCE));
+ LPTSTR lpszDisplayName = (LPTSTR)OleStdMalloc((nLen+1) * sizeof(TCHAR));
+ GetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpszDisplayName, nLen+1);
+ if (lpszDisplayName == NULL)
+ break;
+
+ // fill in the OLEUICHANGESOURCE struct
+ OLEUICHANGESOURCE cs; memset(&cs, 0, sizeof(cs));
+ cs.cbStruct = sizeof(cs);
+ cs.hWndOwner = GetParent(GetParent(hDlg));
+ cs.dwFlags = CSF_ONLYGETSOURCE;
+ if (lpOP->dwFlags & OPF_SHOWHELP)
+ cs.dwFlags |= CSF_SHOWHELP;
+ cs.lpOleUILinkContainer = lpLinkInfo;
+ cs.dwLink = lpOP->dwLink;
+ cs.lpszDisplayName = lpszDisplayName;
+ cs.nFileLength = lpLP->nFileLength;
+
+ // allow the Change Souce dialog to be hooked
+ UINT uRet = UStandardHook(lpLP, hDlg, uMsgChangeSource, 0,
+ (LPARAM)&cs);
+ if (!uRet)
+ {
+ uRet = (OLEUI_OK == OleUIChangeSource(&cs));
+ SetFocus(hDlg);
+ }
+ if (uRet)
+ {
+ OleStdFree(lpLP->lpszDisplayName);
+
+ lpLP->lpszDisplayName = cs.lpszDisplayName;
+ lpLP->nFileLength = cs.nFileLength;
+ SetDlgItemText(hDlg, IDC_LP_LINKSOURCE, lpLP->lpszDisplayName);
+
+ OleStdFree(cs.lpszTo);
+ OleStdFree(cs.lpszFrom);
+
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ }
+ }
+ break;
+
+ case IDC_LP_MANUAL:
+ case IDC_LP_AUTOMATIC:
+ SendMessage(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0);
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch (((NMHDR*)lParam)->code)
+ {
+ case PSN_HELP:
+ PostMessage(GetParent(GetParent(hDlg)), uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_LINKPROPS, 0));
+ break;
+ case PSN_APPLY:
+ {
+ // update link update options first
+ DWORD dwUpdate;
+ if (SendDlgItemMessage(hDlg, IDC_LP_AUTOMATIC, BM_GETCHECK, 0, 0))
+ dwUpdate = OLEUPDATE_ALWAYS;
+ else
+ dwUpdate = OLEUPDATE_ONCALL;
+ if (dwUpdate != lpLP->dwUpdate)
+ lpLinkInfo->SetLinkUpdateOptions(lpOP->dwLink, dwUpdate);
+
+ // set the link source
+ if (lpLP->lpszDisplayName != NULL)
+ {
+ // try setting with validation first
+ ULONG chEaten;
+ if (NOERROR != lpLinkInfo->SetLinkSource(lpOP->dwLink,
+ lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten,
+ TRUE))
+ {
+ UINT uRet = PopupMessage(GetParent(hDlg), IDS_LINKPROPS,
+ IDS_INVALIDSOURCE, MB_ICONQUESTION|MB_YESNO);
+ if (uRet == IDYES)
+ {
+ // user wants to correct the link source
+ SetWindowLong(hDlg, DWL_MSGRESULT, 1);
+ return TRUE;
+ }
+ // user doesn't care if link source is bogus
+ lpLinkInfo->SetLinkSource(lpOP->dwLink,
+ lpLP->lpszDisplayName, lpLP->nFileLength, &chEaten,
+ FALSE);
+ }
+ OleStdFree(lpLP->lpszDisplayName);
+ lpLP->lpszDisplayName = NULL;
+ }
+ }
+ SetWindowLong(hDlg, DWL_MSGRESULT, 0);
+ PostMessage(GetParent(hDlg), PSM_CANCELTOCLOSE, 0, 0);
+ return TRUE;
+ }
+ break;
+
+ case WM_DESTROY:
+ if (lpLP != NULL)
+ {
+ OleStdFree(lpLP->lpszDisplayName);
+ lpLP->lpszDisplayName = NULL;
+ }
+ StandardCleanup((PVOID)lpLP, hDlg);
+ return TRUE;
+
+ default:
+ if (lpOP != NULL && lpOP->lpPS->hwndParent && iMsg == uMsgBrowseOFN)
+ {
+ SendMessage(lpOP->lpPS->hwndParent, uMsgBrowseOFN, wParam, lParam);
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Property Page initialization code
+
+struct PROPPAGEDATA
+{
+ UINT nTemplateID;
+ UINT nTemplateID4;
+ DLGPROC pfnDlgProc;
+ size_t nPtrOffset;
+};
+
+#define PTR_OFFSET(x) offsetof(OLEUIOBJECTPROPS, x)
+static PROPPAGEDATA pageData[3] =
+{
+ { IDD_GNRLPROPS,IDD_GNRLPROPS4, GnrlPropsDialogProc, PTR_OFFSET(lpGP), },
+ { IDD_VIEWPROPS,IDD_VIEWPROPS, ViewPropsDialogProc, PTR_OFFSET(lpVP), },
+ { IDD_LINKPROPS,IDD_LINKPROPS4, LinkPropsDialogProc, PTR_OFFSET(lpLP), },
+};
+#undef PTR_OFFSET
+
+static UINT WINAPI PrepareObjectProperties(LPOLEUIOBJECTPROPS lpOP)
+{
+ // setup back pointers from page structs to sheet structs
+ lpOP->lpGP->lpOP = lpOP;
+ lpOP->lpVP->lpOP = lpOP;
+ if ((lpOP->dwFlags & OPF_OBJECTISLINK) && lpOP->lpLP != NULL)
+ lpOP->lpLP->lpOP = lpOP;
+
+ // pre-init GNRLPROPS struct
+ LPOLEUIGNRLPROPS lpGP = lpOP->lpGP;
+
+ // get ready to initialize PROPSHEET structs
+ LPPROPSHEETHEADER lpPS = lpOP->lpPS;
+ LPPROPSHEETPAGE lpPPs = (LPPROPSHEETPAGE)lpPS->ppsp;
+ UINT nMaxPage = (lpOP->dwFlags & OPF_OBJECTISLINK ? 3 : 2);
+
+ // setting OPF_NOFILLDEFAULT allows you to control almost everything
+ if (!(lpOP->dwFlags & OPF_NOFILLDEFAULT))
+ {
+ // get array of 3 PROPSHEETPAGE structs if not provided
+ if (lpPS->ppsp == NULL)
+ {
+ lpPS->nPages = nMaxPage;
+ lpPPs = (LPPROPSHEETPAGE)
+ OleStdMalloc(nMaxPage * sizeof(PROPSHEETPAGE));
+ if (lpPPs == NULL)
+ return OLEUI_ERR_OLEMEMALLOC;
+ memset(lpPPs, 0, nMaxPage * sizeof(PROPSHEETPAGE));
+ lpPS->ppsp = lpPPs;
+ }
+
+ // fill in defaults for lpPS
+ lpPS->dwFlags |= PSH_PROPSHEETPAGE;
+ if (lpPS->hInstance == NULL)
+ lpPS->hInstance = _g_hOleStdResInst;
+
+ // fill Defaults for Standard Property Pages
+ for (UINT nPage = 0; nPage < nMaxPage; nPage++)
+ {
+ LPPROPSHEETPAGE lpPP = &lpPPs[nPage];
+ PROPPAGEDATA* pPageData = &pageData[nPage];
+ if (lpPP->dwSize == 0)
+ lpPP->dwSize = sizeof(PROPSHEETPAGE);
+ if (lpPP->hInstance == NULL)
+ lpPP->hInstance = _g_hOleStdResInst;
+ UINT nIDD = bWin4 ?
+ pPageData->nTemplateID4 : pPageData->nTemplateID;
+ if (lpPP->pszTemplate == NULL)
+ lpPP->pszTemplate = MAKEINTRESOURCE(nIDD);
+ }
+ }
+
+ // fill Property Page info which cannot be overridden
+ for (UINT nPage = 0; nPage < nMaxPage; nPage++)
+ {
+ LPPROPSHEETPAGE lpPP = &lpPPs[nPage];
+ PROPPAGEDATA* pPageData = &pageData[nPage];
+ lpPP->pfnDlgProc = pPageData->pfnDlgProc;
+ lpPP->lParam = (LONG)
+ *(OLEUIGNRLPROPS**)((LPBYTE)lpOP + pPageData->nPtrOffset);
+ }
+ return OLEUI_SUCCESS;
+}
+
+/////////////////////////////////////////////////////////////////////////////