summaryrefslogtreecommitdiffstats
path: root/private/oleutest/letest/ole2ui
diff options
context:
space:
mode:
Diffstat (limited to 'private/oleutest/letest/ole2ui')
-rw-r--r--private/oleutest/letest/ole2ui/bang.icobin0 -> 1846 bytes
-rw-r--r--private/oleutest/letest/ole2ui/busy.c551
-rw-r--r--private/oleutest/letest/ole2ui/busy.dlg13
-rw-r--r--private/oleutest/letest/ole2ui/busy.h45
-rw-r--r--private/oleutest/letest/ole2ui/common.c423
-rw-r--r--private/oleutest/letest/ole2ui/common.h166
-rw-r--r--private/oleutest/letest/ole2ui/convert.c1802
-rw-r--r--private/oleutest/letest/ole2ui/convert.dlg32
-rw-r--r--private/oleutest/letest/ole2ui/convert.h63
-rw-r--r--private/oleutest/letest/ole2ui/daytona/makefile6
-rw-r--r--private/oleutest/letest/ole2ui/daytona/ole2u32a.src200
-rw-r--r--private/oleutest/letest/ole2ui/daytona/ole2ui.src199
-rw-r--r--private/oleutest/letest/ole2ui/daytona/sources64
-rw-r--r--private/oleutest/letest/ole2ui/dballoc.cpp900
-rw-r--r--private/oleutest/letest/ole2ui/dballoc.h36
-rw-r--r--private/oleutest/letest/ole2ui/dbgutil.c419
-rw-r--r--private/oleutest/letest/ole2ui/debug.h69
-rw-r--r--private/oleutest/letest/ole2ui/default.icobin0 -> 766 bytes
-rw-r--r--private/oleutest/letest/ole2ui/defuimak.ini20
-rw-r--r--private/oleutest/letest/ole2ui/depend87
-rw-r--r--private/oleutest/letest/ole2ui/depend.mk569
-rw-r--r--private/oleutest/letest/ole2ui/dirs3
-rw-r--r--private/oleutest/letest/ole2ui/dllentry.c55
-rw-r--r--private/oleutest/letest/ole2ui/dllfuncs.c110
-rw-r--r--private/oleutest/letest/ole2ui/drawicon.c729
-rw-r--r--private/oleutest/letest/ole2ui/edlinks.h135
-rw-r--r--private/oleutest/letest/ole2ui/egares.bmpbin0 -> 6838 bytes
-rw-r--r--private/oleutest/letest/ole2ui/enumfetc.c308
-rw-r--r--private/oleutest/letest/ole2ui/enumfetc.h13
-rw-r--r--private/oleutest/letest/ole2ui/enumstat.c336
-rw-r--r--private/oleutest/letest/ole2ui/filelist.mk75
-rw-r--r--private/oleutest/letest/ole2ui/fileopen.dlg33
-rw-r--r--private/oleutest/letest/ole2ui/geticon.c1177
-rw-r--r--private/oleutest/letest/ole2ui/geticon.h18
-rw-r--r--private/oleutest/letest/ole2ui/hatch.c325
-rw-r--r--private/oleutest/letest/ole2ui/hivgares.bmpbin0 -> 20326 bytes
-rw-r--r--private/oleutest/letest/ole2ui/icon.c857
-rw-r--r--private/oleutest/letest/ole2ui/icon.dlg48
-rw-r--r--private/oleutest/letest/ole2ui/icon.h59
-rw-r--r--private/oleutest/letest/ole2ui/iconbox.c253
-rw-r--r--private/oleutest/letest/ole2ui/iconbox.h31
-rw-r--r--private/oleutest/letest/ole2ui/insobj.c1724
-rw-r--r--private/oleutest/letest/ole2ui/insobj.dlg51
-rw-r--r--private/oleutest/letest/ole2ui/insobj.h52
-rw-r--r--private/oleutest/letest/ole2ui/links.c2146
-rw-r--r--private/oleutest/letest/ole2ui/links.dlg35
-rw-r--r--private/oleutest/letest/ole2ui/makefile12
-rw-r--r--private/oleutest/letest/ole2ui/makefile.32590
-rw-r--r--private/oleutest/letest/ole2ui/makefile.old607
-rw-r--r--private/oleutest/letest/ole2ui/makelib503
-rw-r--r--private/oleutest/letest/ole2ui/msgfiltr.c809
-rw-r--r--private/oleutest/letest/ole2ui/msgfiltr.h64
-rw-r--r--private/oleutest/letest/ole2ui/objfdbk.c246
-rw-r--r--private/oleutest/letest/ole2ui/ole2ui.c971
-rw-r--r--private/oleutest/letest/ole2ui/ole2ui.h958
-rw-r--r--private/oleutest/letest/ole2ui/ole2ui.mak272
-rw-r--r--private/oleutest/letest/ole2ui/ole2ui.rc65
-rw-r--r--private/oleutest/letest/ole2ui/olestd.c3048
-rw-r--r--private/oleutest/letest/ole2ui/olestd.h852
-rw-r--r--private/oleutest/letest/ole2ui/olestr.c32
-rw-r--r--private/oleutest/letest/ole2ui/olestr.h21
-rw-r--r--private/oleutest/letest/ole2ui/olethunk.c649
-rw-r--r--private/oleutest/letest/ole2ui/olethunk.h193
-rw-r--r--private/oleutest/letest/ole2ui/oleutl.c660
-rw-r--r--private/oleutest/letest/ole2ui/outlui.d32138
-rw-r--r--private/oleutest/letest/ole2ui/pastespl.c1713
-rw-r--r--private/oleutest/letest/ole2ui/pastespl.dlg40
-rw-r--r--private/oleutest/letest/ole2ui/pastespl.h110
-rw-r--r--private/oleutest/letest/ole2ui/precomp.c23
-rw-r--r--private/oleutest/letest/ole2ui/prompt.dlg80
-rw-r--r--private/oleutest/letest/ole2ui/regdb.c401
-rw-r--r--private/oleutest/letest/ole2ui/regdb.h8
-rw-r--r--private/oleutest/letest/ole2ui/resimage.c363
-rw-r--r--private/oleutest/letest/ole2ui/resimage.h61
-rw-r--r--private/oleutest/letest/ole2ui/stdpal.c94
-rw-r--r--private/oleutest/letest/ole2ui/stdpal.h292
-rw-r--r--private/oleutest/letest/ole2ui/strings.rc124
-rw-r--r--private/oleutest/letest/ole2ui/suminfo.cpp1371
-rw-r--r--private/oleutest/letest/ole2ui/suminfo.h331
-rw-r--r--private/oleutest/letest/ole2ui/targtdev.c328
-rw-r--r--private/oleutest/letest/ole2ui/template.c243
-rw-r--r--private/oleutest/letest/ole2ui/template.h119
-rw-r--r--private/oleutest/letest/ole2ui/uiclass.h2
-rw-r--r--private/oleutest/letest/ole2ui/uimake.cmd1
-rw-r--r--private/oleutest/letest/ole2ui/uimake.ini24
-rw-r--r--private/oleutest/letest/ole2ui/utility.c1039
-rw-r--r--private/oleutest/letest/ole2ui/utility.h37
-rw-r--r--private/oleutest/letest/ole2ui/verlocal.h54
-rw-r--r--private/oleutest/letest/ole2ui/vgares.bmpbin0 -> 9078 bytes
-rw-r--r--private/oleutest/letest/ole2ui/wn_dos.h174
90 files changed, 31959 insertions, 0 deletions
diff --git a/private/oleutest/letest/ole2ui/bang.ico b/private/oleutest/letest/ole2ui/bang.ico
new file mode 100644
index 000000000..90fe0f220
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/bang.ico
Binary files differ
diff --git a/private/oleutest/letest/ole2ui/busy.c b/private/oleutest/letest/ole2ui/busy.c
new file mode 100644
index 000000000..7be5c7414
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/busy.c
@@ -0,0 +1,551 @@
+/*
+ * BUSY.C
+ *
+ * Implements the OleUIBusy function which invokes the "Server Busy"
+ * dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+#include "utility.h"
+#include "busy.h"
+#include <ctype.h> // for tolower() and toupper()
+
+#ifndef WIN32
+#include <toolhelp.h>
+#endif
+
+
+/*
+ * OleUIBusy
+ *
+ * Purpose:
+ * Invokes the standard OLE "Server Busy" dialog box which
+ * notifies the user that the server application is not receiving
+ * messages. The dialog then asks the user to either cancel
+ * the operation, switch to the task which is blocked, or continue
+ * waiting.
+ *
+ * Parameters:
+ * lpBZ LPOLEUIBUSY pointing to the in-out structure
+ * for this dialog.
+ *
+ * Return Value:
+ * OLEUI_BZERR_HTASKINVALID : Error
+ * OLEUI_BZ_SWITCHTOSELECTED : Success, user selected "switch to"
+ * OLEUI_BZ_RETRYSELECTED : Success, user selected "retry"
+ * OLEUI_CANCEL : Success, user selected "cancel"
+ */
+
+STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY lpOBZ)
+ {
+ UINT uRet = 0;
+ HGLOBAL hMemDlg=NULL;
+
+#if !defined( WIN32 )
+// BUGBUG32: this is not yet ported to NT
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpOBZ, sizeof(OLEUIBUSY)
+ , &hMemDlg);
+
+ // Error out if the standard validation failed
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+ // Validate HTASK
+ if (!IsTask(lpOBZ->hTask))
+ uRet = OLEUI_BZERR_HTASKINVALID;
+
+ // Error out if our secondary validation failed
+ if (OLEUI_ERR_STANDARDMIN <= uRet)
+ {
+ if (NULL!=hMemDlg)
+ FreeResource(hMemDlg);
+
+ return uRet;
+ }
+
+ // Invoke the dialog.
+ uRet=UStandardInvocation(BusyDialogProc, (LPOLEUISTANDARD)lpOBZ,
+ hMemDlg, MAKEINTRESOURCE(IDD_BUSY));
+#endif
+
+ return uRet;
+}
+
+
+/*
+ * BusyDialogProc
+ *
+ * Purpose:
+ * Implements the OLE Busy dialog as invoked through the OleUIBusy function.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ *
+ */
+
+BOOL CALLBACK EXPORT BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+ {
+ LPBUSY lpBZ;
+ UINT uRet = 0;
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ lpBZ=(LPBUSY)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
+
+ //If the hook processed the message, we're done.
+ if (0!=uRet)
+ return (BOOL)uRet;
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ BusyCleanup(hDlg);
+ StandardCleanup(lpBZ, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ // Process our special "close" message. If we get this message,
+ // this means that the call got unblocked, so we need to
+ // return OLEUI_BZ_CALLUNBLOCKED to our calling app.
+ if (iMsg == uMsgCloseBusyDlg)
+ {
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_CALLUNBLOCKED, 0L);
+ return TRUE;
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FBusyInit(hDlg, wParam, lParam);
+ return TRUE;
+
+ case WM_ACTIVATEAPP:
+ {
+ /* try to bring down our Busy/NotResponding dialog as if
+ ** the user entered RETRY.
+ */
+ BOOL fActive = (BOOL)wParam;
+ if (fActive) {
+ // If this is the app BUSY case, then bring down our
+ // dialog when switching BACK to our app
+ if (lpBZ && !(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG))
+ SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L);
+ } else {
+ // If this is the app NOT RESPONDING case, then bring down
+ // our dialog when switching AWAY to another app
+ if (lpBZ && (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG))
+ SendMessage(hDlg,uMsgEndDialog,OLEUI_BZ_RETRYSELECTED,0L);
+ }
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDBZ_SWITCHTO:
+ {
+ BOOL fNotRespondingDlg =
+ (BOOL)(lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG);
+
+ // If user selects "Switch To...", switch activation
+ // directly to the window which is causing the problem.
+ if (IsWindow(lpBZ->hWndBlocked))
+ MakeWindowActive(lpBZ->hWndBlocked);
+ else
+ StartTaskManager(); // Fail safe: Start Task Manager
+
+ // If this is the app not responding case, then we want
+ // to bring down the dialog when "SwitchTo" is selected.
+ // If the app is busy (RetryRejectedCall situation) then
+ // we do NOT want to bring down the dialog. this is
+ // the OLE2.0 user model design.
+ if (fNotRespondingDlg)
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_SWITCHTOSELECTED, 0L);
+ break;
+ }
+ case IDBZ_RETRY:
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_BZ_RETRYSELECTED, 0L);
+ break;
+
+ case IDCANCEL:
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+ }
+
+
+/*
+ * FBusyInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Busy dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+ {
+ LPBUSY lpBZ;
+ LPOLEUIBUSY lpOBZ;
+ HFONT hFont;
+ LPTSTR lpTaskName;
+ LPTSTR lpWindowName;
+ HICON hIcon;
+
+ lpBZ=(LPBUSY)LpvStandardInit(hDlg, sizeof(OLEUIBUSY), TRUE, &hFont);
+
+ // PvStandardInit sent a termination to us already.
+ if (NULL==lpBZ)
+ return FALSE;
+
+ // Our original structure is in lParam
+ lpOBZ = (LPOLEUIBUSY)lParam;
+
+ // Copy it to our instance of the structure (in lpBZ)
+ lpBZ->lpOBZ=lpOBZ;
+
+ //Copy other information from lpOBZ that we might modify.
+ lpBZ->dwFlags = lpOBZ->dwFlags;
+
+ // Set default information
+ lpBZ->hWndBlocked = NULL;
+
+ // Insert HWND of our dialog into the address pointed to by
+ // lphWndDialog. This can be used by the app who called
+ // OleUIBusy to bring down the dialog with uMsgCloseBusyDialog
+ if (lpOBZ->lphWndDialog &&
+ !IsBadWritePtr((VOID FAR *)lpOBZ->lphWndDialog, sizeof(HWND)))
+ {
+ *lpOBZ->lphWndDialog = hDlg;
+ }
+
+ // Update text in text box --
+ // GetTaskInfo will return two pointers, one to the task name
+ // (file name) and one to the window name. We need to call
+ // OleStdFree on these when we're done with them. We also
+ // get the HWND which is blocked in this call
+ //
+ // In the case where this call fails, a default message should already
+ // be present in the dialog template, so no action is needed
+
+ if (GetTaskInfo(hDlg, lpOBZ->hTask, &lpTaskName, &lpWindowName, &lpBZ->hWndBlocked))
+ {
+ // Build string to present to user, place in IDBZ_MESSAGE1 control
+ BuildBusyDialogString(hDlg, lpBZ->dwFlags, IDBZ_MESSAGE1, lpTaskName, lpWindowName);
+ OleStdFree(lpTaskName);
+ OleStdFree(lpWindowName);
+ }
+
+ // Update icon with the system "exclamation" icon
+ hIcon = LoadIcon(NULL, IDI_EXCLAMATION);
+ SendDlgItemMessage(hDlg, IDBZ_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
+
+ // Disable/Enable controls
+ if ((lpBZ->dwFlags & BZ_DISABLECANCELBUTTON) ||
+ (lpBZ->dwFlags & BZ_NOTRESPONDINGDIALOG)) // Disable cancel for "not responding" dialog
+ EnableWindow(GetDlgItem(hDlg, IDCANCEL), FALSE);
+
+ if (lpBZ->dwFlags & BZ_DISABLESWITCHTOBUTTON)
+ EnableWindow(GetDlgItem(hDlg, IDBZ_SWITCHTO), FALSE);
+
+ if (lpBZ->dwFlags & BZ_DISABLERETRYBUTTON)
+ EnableWindow(GetDlgItem(hDlg, IDBZ_RETRY), FALSE);
+
+ // Call the hook with lCustData in lParam
+ UStandardHook((LPVOID)lpBZ, hDlg, WM_INITDIALOG, wParam, lpOBZ->lCustData);
+
+ // Update caption if lpszCaption was specified
+ if (lpBZ->lpOBZ->lpszCaption && !IsBadReadPtr(lpBZ->lpOBZ->lpszCaption, 1)
+ && lpBZ->lpOBZ->lpszCaption[0] != '\0')
+ SetWindowText(hDlg, lpBZ->lpOBZ->lpszCaption);
+
+ return TRUE;
+ }
+
+
+/*
+ * BuildBusyDialogString
+ *
+ * Purpose:
+ * Builds the string that will be displayed in the dialog from the
+ * task name and window name parameters.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * dwFlags DWORD containing flags passed into dialog
+ * iControl Control ID to place the text string
+ * lpTaskName LPSTR pointing to name of task (e.g. C:\TEST\TEST.EXE)
+ * lpWindowName LPSTR for name of window
+ *
+ * Caveats:
+ * The caller of this function MUST de-allocate the lpTaskName and
+ * lpWindowName pointers itself with OleStdFree
+ *
+ * Return Value:
+ * void
+ */
+
+void BuildBusyDialogString(HWND hDlg, DWORD dwFlags, int iControl, LPTSTR lpTaskName, LPTSTR lpWindowName)
+{
+ LPTSTR pszT, psz1, psz2, psz3;
+ UINT cch;
+ LPTSTR pszDot, pszSlash;
+ UINT uiStringNum;
+
+ /*
+ * We need scratch memory for loading the stringtable string,
+ * the task name, and constructing the final string. We therefore
+ * allocate three buffers as large as the maximum message
+ * length (512) plus the object type, guaranteeing that we have enough
+ * in all cases.
+ */
+ cch=512;
+
+ // Use OLE-supplied allocation
+ if ((pszT = OleStdMalloc((ULONG)(3*cch))) == NULL)
+ return;
+
+ psz1=pszT;
+ psz2=psz1+cch;
+ psz3=psz2+cch;
+
+ // Parse base name out of path name, use psz2 for the task
+ // name to display
+ // In Win32, _fstrcpy is mapped to handle UNICODE stuff
+ _fstrcpy(psz2, lpTaskName);
+ pszDot = _fstrrchr(psz2, TEXT('.'));
+ pszSlash = _fstrrchr(psz2, TEXT('\\')); // Find last backslash in path
+
+ if (pszDot != NULL)
+#ifdef UNICODE
+ *pszDot = TEXT('\0'); // Null terminate at the DOT
+#else
+ *pszDot = '\0'; // Null terminate at the DOT
+#endif
+
+ if (pszSlash != NULL)
+ psz2 = pszSlash + 1; // Nuke everything up to this point
+
+#ifdef LOWERCASE_NAME
+ // Compile this with /DLOWERCASE_NAME if you want the lower-case
+ // module name to be displayed in the dialog rather than the
+ // all-caps name.
+ {
+ int i,l;
+
+ // Now, lowercase all letters except first one
+ l = _fstrlen(psz2);
+ for(i=0;i<l;i++)
+ psz2[i] = tolower(psz2[i]);
+
+ psz2[0] = toupper(psz2[0]);
+ }
+#endif
+
+ // Check size of lpWindowName. We can reasonably fit about 80
+ // characters into the text control, so truncate more than 80 chars
+ if (_fstrlen(lpWindowName)> 80)
+#ifdef UNICODE
+ lpWindowName[80] = TEXT('\0');
+#else
+ lpWindowName[80] = '\0';
+#endif
+
+ // Load the format string out of stringtable, choose a different
+ // string depending on what flags are passed in to the dialog
+ if (dwFlags & BZ_NOTRESPONDINGDIALOG)
+ uiStringNum = IDS_BZRESULTTEXTNOTRESPONDING;
+ else
+ uiStringNum = IDS_BZRESULTTEXTBUSY;
+
+ if (LoadString(ghInst, uiStringNum, psz1, cch) == 0)
+ return;
+
+ // Build the string. The format string looks like this:
+ // "This action cannot be completed because the '%s' application
+ // (%s) is [busy | not responding]. Choose \"Switch To\" to activate '%s' and
+ // correct the problem."
+
+ wsprintf(psz3, psz1, (LPSTR)psz2, (LPTSTR)lpWindowName, (LPTSTR)psz2);
+ SetDlgItemText(hDlg, iControl, (LPTSTR)psz3);
+ OleStdFree(pszT);
+
+ return;
+}
+
+
+
+/*
+ * BusyCleanup
+ *
+ * Purpose:
+ * Performs busy-specific cleanup before termination.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box so we can access controls.
+ *
+ * Return Value:
+ * None
+ */
+void BusyCleanup(HWND hDlg)
+{
+ return;
+}
+
+
+
+/*
+ * GetTaskInfo()
+ *
+ * Purpose: Gets information about the specified task and places the
+ * module name, window name and top-level HWND for the task in the specified
+ * pointers
+ *
+ * NOTE: The two string pointers allocated in this routine are
+ * the responsibility of the CALLER to de-allocate.
+ *
+ * Parameters:
+ * hWnd HWND who called this function
+ * htask HTASK which we want to find out more info about
+ * lplpszTaskName Location that the module name is returned
+ * lplpszWindowName Location where the window name is returned
+ *
+ */
+
+BOOL GetTaskInfo(HWND hWnd, HTASK htask, LPTSTR FAR* lplpszTaskName, LPTSTR FAR*lplpszWindowName, HWND FAR*lphWnd)
+{
+ BOOL fRet = FALSE;
+#if !defined( WIN32 )
+ TASKENTRY te;
+#endif
+ HWND hwndNext;
+ LPTSTR lpszTN = NULL;
+ LPTSTR lpszWN = NULL;
+ HWND hwndFind = NULL;
+
+ // Clear out return values in case of error
+ *lplpszTaskName = NULL;
+ *lplpszWindowName = NULL;
+
+#if !defined( WIN32 )
+ te.dwSize = sizeof(TASKENTRY);
+ if (TaskFindHandle(&te, htask))
+#endif
+ {
+ // Now, enumerate top-level windows in system
+ hwndNext = GetWindow(hWnd, GW_HWNDFIRST);
+ while (hwndNext)
+ {
+ // See if we can find a non-owned top level window whose
+ // hInstance matches the one we just got passed. If we find one,
+ // we can be fairly certain that this is the top-level window for
+ // the task which is blocked.
+ //
+ // REVIEW: Will this filter hold true for InProcServer DLL-created
+ // windows?
+ //
+ if ((hwndNext != hWnd) &&
+#if !defined( WIN32 )
+ (GetWindowWord(hwndNext, GWW_HINSTANCE) == (WORD)te.hInst) &&
+#else
+ ((HTASK) GetWindowThreadProcessId(hwndNext,NULL) == htask) &&
+#endif
+ (IsWindowVisible(hwndNext)) &&
+ !GetWindow(hwndNext, GW_OWNER))
+ {
+ // We found our window! Alloc space for new strings
+ if ((lpszTN = OleStdMalloc(OLEUI_CCHPATHMAX_SIZE)) == NULL)
+ return TRUE; // continue task window enumeration
+
+ if ((lpszWN = OleStdMalloc(OLEUI_CCHPATHMAX_SIZE)) == NULL)
+ return TRUE; // continue task window enumeration
+
+ // We found the window we were looking for, copy info to
+ // local vars
+ GetWindowText(hwndNext, lpszWN, OLEUI_CCHPATHMAX);
+#if !defined( WIN32 )
+ LSTRCPYN(lpszTN, te.szModule, OLEUI_CCHPATHMAX);
+#else
+ /* WIN32 NOTE: we are not able to get a module name
+ ** given a thread process id on WIN32. the best we
+ ** can do is use the window title as the module/app
+ ** name.
+ */
+ LSTRCPYN(lpszTN, lpszWN, OLEUI_CCHPATHMAX);
+#endif
+ hwndFind = hwndNext;
+
+ fRet = TRUE;
+ goto OKDone;
+ }
+
+ hwndNext = GetWindow(hwndNext, GW_HWNDNEXT);
+ }
+ }
+
+OKDone:
+
+ // OK, everything was successful. Set string pointers to point to
+ // our data.
+
+ *lplpszTaskName = lpszTN;
+ *lplpszWindowName = lpszWN;
+ *lphWnd = hwndFind;
+
+ return fRet;
+}
+
+
+/*
+ * StartTaskManager()
+ *
+ * Purpose: Starts Task Manager. Used to bring up task manager to
+ * assist in switching to a given blocked task.
+ *
+ */
+
+StartTaskManager()
+{
+ WinExec("taskman.exe", SW_SHOW);
+ return TRUE;
+}
+
+
+
+/*
+ * MakeWindowActive()
+ *
+ * Purpose: Makes specified window the active window.
+ *
+ */
+
+void MakeWindowActive(HWND hWndSwitchTo)
+{
+ // Move the new window to the top of the Z-order
+ SetWindowPos(hWndSwitchTo, HWND_TOP, 0, 0, 0, 0,
+ SWP_NOSIZE | SWP_NOMOVE);
+
+ // If it's iconic, we need to restore it.
+ if (IsIconic(hWndSwitchTo))
+ ShowWindow(hWndSwitchTo, SW_RESTORE);
+}
diff --git a/private/oleutest/letest/ole2ui/busy.dlg b/private/oleutest/letest/ole2ui/busy.dlg
new file mode 100644
index 000000000..c2151956c
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/busy.dlg
@@ -0,0 +1,13 @@
+IDD_BUSY DIALOG DISCARDABLE 0, 0, 214, 76
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Server Busy"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ DEFPUSHBUTTON "&Switch To...", IDBZ_SWITCHTO, 33, 55, 53, 15
+ PUSHBUTTON "&Cancel", IDCANCEL, 152, 55, 53, 15
+ PUSHBUTTON "&Retry", IDBZ_RETRY, 92, 55, 53, 15
+ LTEXT "This action cannot be completed because the other application is busy. Choose 'Switch To' to activate the busy application and correct the problem.", IDBZ_MESSAGE1, 35, 11, 167, 35
+ ICON "", IDBZ_ICON, 8, 18, 18, 20
+END
+
+
diff --git a/private/oleutest/letest/ole2ui/busy.h b/private/oleutest/letest/ole2ui/busy.h
new file mode 100644
index 000000000..3656aecf6
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/busy.h
@@ -0,0 +1,45 @@
+/*
+ * BUSY.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Busy dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#ifndef _BUSY_H_
+#define _BUSY_H_
+
+//Internally used structure
+typedef struct tagBUSY
+ {
+ //Keep this item first as the Standard* functions depend on it here.
+ LPOLEUIBUSY lpOBZ; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog or that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+
+ DWORD dwFlags; // Flags passed in
+ HWND hWndBlocked; // HWND of app which is blocking
+ } BUSY, *PBUSY, FAR *LPBUSY;
+
+// Internal function prototypes
+BOOL GetTaskInfo(HWND hWnd, HTASK htask, LPTSTR FAR* lplpszTaskName, LPTSTR FAR*lplpszWindowName, HWND FAR*lphWnd);
+void BuildBusyDialogString(HWND, DWORD, int, LPTSTR, LPTSTR);
+BOOL CALLBACK EXPORT BusyDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
+void BusyCleanup(HWND hDlg);
+BOOL FBusyInit(HWND hDlg, WPARAM wParam, LPARAM lParam);
+BOOL InitEnumeration(void);
+void UnInitEnumeration(void);
+ StartTaskManager(void);
+void MakeWindowActive(HWND hWndSwitchTo);
+
+#endif //_BUSY_H_
+
+
+
+
diff --git a/private/oleutest/letest/ole2ui/common.c b/private/oleutest/letest/ole2ui/common.c
new file mode 100644
index 000000000..40f450c72
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/common.c
@@ -0,0 +1,423 @@
+/*
+ * COMMON.C
+ *
+ * Standardized (and centralized) pieces of each OLE2UI dialog function:
+ * UStandardValidation Validates standard fields in each dialog structure
+ * UStandardInvocation Invokes a dialog through DialogBoxIndirectParam
+ * LpvStandardInit Common WM_INITDIALOG processing
+ * LpvStandardEntry Common code to execute on dialog proc entry.
+ * FStandardHook Centralized hook calling function.
+ * StandardCleanup Common exit/cleanup code.
+ * OleUIShowDlgItem Show-Enable/Hide-Disable dialog item
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+#include "utility.h"
+#include <malloc.h>
+
+
+/*
+ * UStandardValidation
+ *
+ * Purpose:
+ * Performs validation on the standard pieces of any dialog structure,
+ * that is, the fields defined in the OLEUISTANDARD structure.
+ *
+ * Parameters:
+ * lpUI const LPOLEUISTANDARD pointing to the shared data of
+ * all structs.
+ * cbExpect const UINT structure size desired by the caller.
+ * phDlgMem const HGLOBAL FAR * in which to store a loaded customized
+ * template, if one exists.
+ *
+ * Return Value:
+ * UINT OLEUI_SUCCESS if all validation succeeded. Otherwise
+ * it will be one of the standard error codes.
+ */
+
+UINT WINAPI UStandardValidation(const LPOLEUISTANDARD lpUI, const UINT cbExpect
+ , const HGLOBAL FAR *phMemDlg)
+ {
+ HRSRC hRes=NULL;
+ HGLOBAL hMem=NULL;
+
+
+ /*
+ * 1. Validate non-NULL pointer parameter. Note: We don't validate
+ * phDlg since it's not passed from an external source.
+ */
+ if (NULL==lpUI)
+ return OLEUI_ERR_STRUCTURENULL;
+
+ //2. Validate that the structure is readable and writable.
+ if (IsBadReadPtr(lpUI, cbExpect) || IsBadWritePtr(lpUI, cbExpect))
+ return OLEUI_ERR_STRUCTUREINVALID;
+
+ //3. Validate the structure size
+ if (cbExpect!=lpUI->cbStruct)
+ return OLEUI_ERR_CBSTRUCTINCORRECT;
+
+ //4. Validate owner-window handle. NULL is considered valid.
+ if (NULL!=lpUI->hWndOwner && !IsWindow(lpUI->hWndOwner))
+ return OLEUI_ERR_HWNDOWNERINVALID;
+
+ //5. Validate the dialog caption. NULL is considered valid.
+ if (NULL!=lpUI->lpszCaption && IsBadReadPtr(lpUI->lpszCaption, 1))
+ return OLEUI_ERR_LPSZCAPTIONINVALID;
+
+ //6. Validate the hook pointer. NULL is considered valid.
+ if ((LPFNOLEUIHOOK)NULL!=lpUI->lpfnHook
+ && IsBadCodePtr((FARPROC)lpUI->lpfnHook))
+ return OLEUI_ERR_LPFNHOOKINVALID;
+
+ /*
+ * 7. If hInstance is non-NULL, we have to also check lpszTemplate.
+ * Otherwise, lpszTemplate is not used and requires no validation.
+ * lpszTemplate cannot be NULL if used.
+ */
+ if (NULL!=lpUI->hInstance)
+ {
+ //Best we can try is one character
+ if (NULL==lpUI->lpszTemplate || IsBadReadPtr(lpUI->lpszTemplate, 1))
+ return OLEUI_ERR_LPSZTEMPLATEINVALID;
+
+ hRes=FindResource(lpUI->hInstance, lpUI->lpszTemplate, RT_DIALOG);
+
+ //This is the only thing that catches invalid non-NULL hInstance
+ if (NULL==hRes)
+ return OLEUI_ERR_FINDTEMPLATEFAILURE;
+
+ hMem=LoadResource(lpUI->hInstance, hRes);
+
+ if (NULL==hMem)
+ return OLEUI_ERR_LOADTEMPLATEFAILURE;
+ }
+
+
+ //8. If hResource is non-NULL, be sure we can lock it.
+ if (NULL!=lpUI->hResource)
+ {
+ if ((LPSTR)NULL==GlobalLock(lpUI->hResource))
+ return OLEUI_ERR_HRESOURCEINVALID;
+
+ GlobalUnlock(lpUI->hResource);
+ }
+
+ /*
+ * Here we have hMem==NULL if we should use the standard template
+ * or the one in lpUI->hResource. If hMem is non-NULL, then we
+ * loaded one from the calling application's resources which the
+ * caller of this function has to free if it sees any other error.
+ */
+ *(HGLOBAL FAR *)phMemDlg=hMem;
+ return OLEUI_SUCCESS;
+ }
+
+
+
+
+
+/*
+ * UStandardInvocation
+ *
+ * Purpose:
+ * Provides standard template loading and calling on DialogBoxIndirectParam
+ * for all the OLE UI dialogs.
+ *
+ * Parameters:
+ * lpDlgProc DLGPROC of the dialog function.
+ * lpUI LPOLEUISTANDARD containing the dialog structure.
+ * hMemDlg HGLOBAL containing the dialog template. If this
+ * is NULL and lpUI->hResource is NULL, then we load
+ * the standard template given the name in lpszStdTemplate
+ * lpszStdTemplate LPCSTR standard template to load if hMemDlg is NULL
+ * and lpUI->hResource is NULL.
+ *
+ * Return Value:
+ * UINT OLEUI_SUCCESS if all is well, otherwise and error
+ * code.
+ */
+
+UINT WINAPI UStandardInvocation
+#ifdef WIN32
+(DLGPROC lpDlgProc, LPOLEUISTANDARD lpUI, HGLOBAL hMemDlg, LPTSTR lpszStdTemplate)
+#else
+(DLGPROC lpDlgProc, LPOLEUISTANDARD lpUI, HGLOBAL hMemDlg, LPCTSTR lpszStdTemplate)
+#endif
+ {
+ HGLOBAL hTemplate=hMemDlg;
+ HRSRC hRes;
+ int iRet;
+
+ //Make sure we have a template, then lock it down
+ if (NULL==hTemplate)
+ hTemplate=lpUI->hResource;
+
+ if (NULL==hTemplate)
+ {
+ hRes=FindResource(ghInst, (LPCTSTR) lpszStdTemplate, RT_DIALOG);
+
+ if (NULL==hRes)
+ {
+ return OLEUI_ERR_FINDTEMPLATEFAILURE;
+ }
+
+ hTemplate=LoadResource(ghInst, hRes);
+
+ if (NULL==hTemplate)
+ {
+ return OLEUI_ERR_LOADTEMPLATEFAILURE;
+ }
+ }
+
+ /*
+ * hTemplate has the template to use, so now we can invoke the dialog.
+ * Since we have exported all of our dialog procedures using the
+ * _export keyword, we do not need to call MakeProcInstance,
+ * we can ue the dialog procedure address directly.
+ */
+
+ iRet=DialogBoxIndirectParam(ghInst, hTemplate, lpUI->hWndOwner
+ , lpDlgProc, (LPARAM)lpUI);
+
+ /*
+ * Cleanup the template if we explicitly loaded it. Caller is
+ * responsible for already loaded template resources.
+ */
+ if (hTemplate!=lpUI->hResource)
+ FreeResource(hTemplate);
+
+ if (-1==iRet)
+ return OLEUI_ERR_DIALOGFAILURE;
+
+ //Return the code from EndDialog, generally OLEUI_OK or OLEUI_CANCEL
+ return (UINT)iRet;
+ }
+
+
+
+
+
+
+/*
+ * LpvStandardInit
+ *
+ * Purpose:
+ * Default actions for WM_INITDIALOG handling in the dialog, allocating
+ * a dialog-specific structure, setting that memory as a dialog property,
+ * and creating a small font if necessary setting that font as a property.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * cbStruct UINT size of dialog-specific structure to allocate.
+ * fCreateFont BOOL indicating if we need to create a small Helv
+ * font for this dialog.
+ * phFont HFONT FAR * in which to place a created font. Can be
+ * NULL if fCreateFont is FALSE.
+ *
+ * Return Value:
+ * LPVOID Pointer to global memory allocated for the dialog.
+ * The memory will have been set as a dialog property
+ * using the STRUCTUREPROP label.
+ */
+
+LPVOID WINAPI LpvStandardInit(HWND hDlg, UINT cbStruct, BOOL fCreateFont, HFONT FAR * phFont)
+ {
+ LPVOID lpv;
+ HFONT hFont;
+ LOGFONT lf;
+ HGLOBAL gh;
+
+ //Must have at least sizeof(OLEUISTANDARD) bytes in cbStruct
+ if (sizeof(OLEUISTANDARD) > cbStruct || (fCreateFont && NULL==phFont))
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
+ return NULL;
+ }
+
+ gh=GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT, cbStruct);
+
+ if (NULL==gh)
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
+ return NULL;
+ }
+ lpv = GlobalLock(gh);
+ SetProp(hDlg, STRUCTUREPROP, gh);
+
+ if (fCreateFont) {
+ //Create the non-bold font for result and file texts. We call
+ hFont=(HFONT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
+ GetObject(hFont, sizeof(LOGFONT), &lf);
+ lf.lfWeight=FW_NORMAL;
+
+ //Attempt to create the font. If this fails, then we return no font.
+ *phFont=CreateFontIndirect(&lf);
+
+ //If we couldn't create the font, we'll do with the default.
+ if (NULL!=*phFont)
+ SetProp(hDlg, FONTPROP, (HANDLE)*phFont);
+ }
+
+ return lpv;
+ }
+
+
+
+
+
+/*
+ * LpvStandardEntry
+ *
+ * Purpose:
+ * Retrieves the dialog's structure property and calls the hook
+ * as necessary. This should be called on entry into all dialog
+ * procedures.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * iMsg UINT message to the dialog
+ * wParam, lParam WPARAM, LPARAM message parameters
+ * puHookResult UINT FAR * in which this function stores the return value
+ * from the hook if it is called. If no hook is available,
+ * this will be FALSE.
+ *
+ * Return Value:
+ * LPVOID Pointer to the dialog's extra structure held in the
+ * STRUCTUREPROP property.
+ */
+
+LPVOID WINAPI LpvStandardEntry(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam
+ , UINT FAR * puHookResult)
+ {
+ LPVOID lpv = NULL;
+ HGLOBAL gh;
+
+ // This will fail under WM_INITDIALOG, where we allocate using StandardInit
+ gh = GetProp(hDlg, STRUCTUREPROP);
+
+ if (NULL!=puHookResult && NULL!=gh)
+ {
+ *puHookResult=0;
+
+ // gh was locked previously, lock and unlock to get lpv
+ lpv = GlobalLock(gh);
+ GlobalUnlock(gh);
+
+ //Call the hook for all messages except WM_INITDIALOG
+ if (NULL!=lpv && WM_INITDIALOG!=iMsg)
+ *puHookResult=UStandardHook(lpv, hDlg, iMsg, wParam, lParam);
+ }
+
+ return lpv;
+ }
+
+
+
+
+/*
+ * UStandardHook
+ *
+ * Purpose:
+ * Provides a generic hook calling function assuming that all private
+ * dialog structures have a far pointer to their assocated public
+ * structure as the first field, and that the first part of the public
+ * structure matches an OLEUISTANDARD.
+ *
+ * Parameters:
+ * pv PVOID to the dialog structure.
+ * hDlg HWND to send with the call to the hook.
+ * iMsg UINT message to send to the hook.
+ * wParam, lParam WPARAM, LPARAM message parameters
+ *
+ * Return Value:
+ * UINT Return value from the hook, zero to indicate that
+ * default action should occur, nonzero to specify
+ * that the hook did process the message. In some
+ * circumstances it will be important for the hook to
+ * return a non-trivial non-zero value here, such as
+ * a brush from WM_CTLCOLOR, in which case the caller
+ * should return that value from the dialog procedure.
+ */
+
+UINT WINAPI UStandardHook(LPVOID lpv, HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+ {
+ LPOLEUISTANDARD lpUI;
+ UINT uRet=0;
+
+ lpUI=*((LPOLEUISTANDARD FAR *)lpv);
+
+ if (NULL!=lpUI && NULL!=lpUI->lpfnHook)
+ {
+ /*
+ * In order for the hook to have the proper DS, they should be
+ * compiling with -GA -GEs so and usin __export to get everything
+ * set up properly.
+ */
+ uRet=(*lpUI->lpfnHook)(hDlg, iMsg, wParam, lParam);
+ }
+
+ return uRet;
+ }
+
+
+
+
+
+/*
+ * StandardCleanup
+ *
+ * Purpose:
+ * Removes properties and reverses any other standard initiazation
+ * done through StandardSetup.
+ *
+ * Parameters:
+ * lpv LPVOID containing the private dialog structure.
+ * hDlg HWND of the dialog closing.
+ *
+ * Return Value:
+ * None
+ */
+
+void WINAPI StandardCleanup(LPVOID lpv, HWND hDlg)
+ {
+ HFONT hFont;
+ HGLOBAL gh;
+
+ hFont=(HFONT)GetProp(hDlg, FONTPROP);
+
+ if (NULL!=hFont)
+ DeleteObject(hFont);
+
+ RemoveProp(hDlg, FONTPROP);
+
+ gh = RemoveProp(hDlg, STRUCTUREPROP);
+ if (gh)
+ {
+ GlobalUnlock(gh);
+ GlobalFree(gh);
+ }
+ return;
+ }
+
+
+/* StandardShowDlgItem
+** -------------------
+** Show & Enable or Hide & Disable a dialog item as appropriate.
+** it is NOT sufficient to simply hide the item; it must be disabled
+** too or the keyboard accelerator still functions.
+*/
+void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow)
+{
+ if (SW_HIDE == nCmdShow) {
+ ShowWindow(GetDlgItem(hDlg, idControl), SW_HIDE);
+ EnableWindow(GetDlgItem(hDlg, idControl), FALSE);
+ } else {
+ ShowWindow(GetDlgItem(hDlg, idControl), SW_SHOWNORMAL);
+ EnableWindow(GetDlgItem(hDlg, idControl), TRUE);
+ }
+}
diff --git a/private/oleutest/letest/ole2ui/common.h b/private/oleutest/letest/ole2ui/common.h
new file mode 100644
index 000000000..00466661f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/common.h
@@ -0,0 +1,166 @@
+/*
+ * COMMON.H
+ *
+ * Structures and definitions applicable to all OLE 2.0 UI dialogs.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+
+//Macros to handle control message packing between Win16 and Win32
+#ifdef WIN32
+
+#ifndef COMMANDPARAMS
+#define COMMANDPARAMS(wID, wCode, hWndMsg) \
+ WORD wID = LOWORD(wParam); \
+ WORD wCode = HIWORD(wParam); \
+ HWND hWndMsg = (HWND)(UINT)lParam;
+#endif //COMMANDPARAMS
+
+#ifndef SendCommand
+#define SendCommand(hWnd, wID, wCode, hControl) \
+ SendMessage(hWnd, WM_COMMAND, MAKELONG(wID, wCode) \
+ , (LPARAM)hControl)
+#endif //SendCommand
+
+#else //Start !WIN32
+
+#ifndef COMMANDPARAMS
+#define COMMANDPARAMS(wID, wCode, hWndMsg) \
+ WORD wID = LOWORD(wParam); \
+ WORD wCode = HIWORD(lParam); \
+ HWND hWndMsg = (HWND)(UINT)lParam;
+#endif //COMMANDPARAMS
+
+#ifndef SendCommand
+#define SendCommand(hWnd, wID, wCode, hControl) \
+ SendMessage(hWnd, WM_COMMAND, wID \
+ , MAKELONG(hControl, wCode))
+#endif //SendCommand
+
+#endif //!WIN32
+
+
+
+//Property labels used to store dialog structures and fonts
+#define STRUCTUREPROP TEXT("Structure")
+#define FONTPROP TEXT("Font")
+
+
+/*
+ * Standard structure for all dialogs. This commonality lets us make
+ * a single piece of code that will validate this entire structure and
+ * perform any necessary initialization.
+ */
+
+typedef struct tagOLEUISTANDARD
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+ } OLEUISTANDARD, *POLEUISTANDARD, FAR *LPOLEUISTANDARD;
+
+
+
+//Function prototypes
+//COMMON.C
+UINT WINAPI UStandardValidation(const LPOLEUISTANDARD, const UINT, const HGLOBAL FAR *);
+
+#ifdef WIN32
+UINT WINAPI UStandardInvocation(DLGPROC, LPOLEUISTANDARD, HGLOBAL, LPTSTR);
+#else
+UINT WINAPI UStandardInvocation(DLGPROC, LPOLEUISTANDARD, HGLOBAL, LPCTSTR);
+#endif
+
+LPVOID WINAPI LpvStandardInit(HWND, UINT, BOOL, HFONT FAR *);
+LPVOID WINAPI LpvStandardEntry(HWND, UINT, WPARAM, LPARAM, UINT FAR *);
+UINT WINAPI UStandardHook(LPVOID, HWND, UINT, WPARAM, LPARAM);
+void WINAPI StandardCleanup(LPVOID, HWND);
+void WINAPI StandardShowDlgItem(HWND hDlg, int idControl, int nCmdShow);
+
+
+//DRAWICON.C
+
+//Structure for label and source extraction from a metafile
+typedef struct tagLABELEXTRACT
+ {
+ LPTSTR lpsz;
+ UINT Index; // index in lpsz (so we can retrieve 2+ lines)
+ DWORD PrevIndex; // index of last line (so we can mimic word wrap)
+
+ union
+ {
+ UINT cch; //Length of label for label extraction
+ UINT iIcon; //Index of icon in source extraction.
+ } u;
+
+ //For internal use in enum procs
+ BOOL fFoundIconOnly;
+ BOOL fFoundSource;
+ BOOL fFoundIndex;
+ } LABELEXTRACT, FAR * LPLABELEXTRACT;
+
+
+//Structure for extracting icons from a metafile (CreateIcon parameters)
+typedef struct tagICONEXTRACT
+ {
+ HICON hIcon; //Icon created in the enumeration proc.
+
+ /*
+ * Since we want to handle multitasking well we have the caller
+ * of the enumeration proc instantiate these variables instead of
+ * using statics in the enum proc (which would be bad).
+ */
+ BOOL fAND;
+ HGLOBAL hMemAND; //Enumeration proc allocates and copies
+ } ICONEXTRACT, FAR * LPICONEXTRACT;
+
+
+//Structure to use to pass info to EnumMetafileDraw
+typedef struct tagDRAWINFO
+ {
+ RECT Rect;
+ BOOL fIconOnly;
+ } DRAWINFO, FAR * LPDRAWINFO;
+
+
+int CALLBACK EXPORT EnumMetafileIconDraw(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPARAM);
+int CALLBACK EXPORT EnumMetafileExtractLabel(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT);
+int CALLBACK EXPORT EnumMetafileExtractIcon(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPICONEXTRACT);
+int CALLBACK EXPORT EnumMetafileExtractIconSource(HDC, HANDLETABLE FAR *, METARECORD FAR *, int, LPLABELEXTRACT);
+
+
+//Shared globals: our instance, registered messages used from all dialogs and clipboard
+// formats used by the PasteSpecial dialog
+extern HINSTANCE ghInst;
+
+extern UINT uMsgHelp;
+extern UINT uMsgEndDialog;
+extern UINT uMsgBrowse;
+extern UINT uMsgChangeIcon;
+extern UINT uMsgFileOKString;
+extern UINT uMsgCloseBusyDlg;
+
+extern UINT cfObjectDescriptor;
+extern UINT cfLinkSrcDescriptor;
+extern UINT cfEmbedSource;
+extern UINT cfEmbeddedObject;
+extern UINT cfLinkSource;
+extern UINT cfOwnerLink;
+extern UINT cfFileName;
+
+//Standard control identifiers
+#define ID_NULL 98
+
+#endif //_COMMON_H_
diff --git a/private/oleutest/letest/ole2ui/convert.c b/private/oleutest/letest/ole2ui/convert.c
new file mode 100644
index 000000000..e5ca54131
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/convert.c
@@ -0,0 +1,1802 @@
+/*
+ * CONVERT.C
+ *
+ * Implements the OleUIConvert function which invokes the complete
+ * Convert dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include <stdlib.h>
+#include "common.h"
+#include "utility.h"
+#include "geticon.h"
+#include "regdb.h"
+#include "convert.h"
+
+#define CF_CLIPBOARDMIN 0xc000
+#define CF_CLIPBOARDMAX 0xffff
+
+#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
+
+static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library
+
+static TCHAR szVanillaDocIcon[] = TEXT("DefIcon");
+
+/*
+ * OleUIConvert
+ *
+ * Purpose:
+ * Invokes the standard OLE Change Type dialog box allowing the user
+ * to change the type of the single specified object, or change the
+ * type of all OLE objects of a specified type.
+ *
+ * Parameters:
+ * lpCV LPOLEUICONVERT 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
+ */
+
+STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT lpCV)
+ {
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpCV, sizeof(OLEUICONVERT)
+ , &hMemDlg);
+
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+ // Validate structure members passed in.
+#if defined( OBSOLETE )
+ if (!IsValidClassID(lpCV->clsid))
+ uRet = OLEUI_CTERR_CLASSIDINVALID;
+#endif
+
+ if ( (lpCV->dwFlags & CF_SETCONVERTDEFAULT)
+ && (!IsValidClassID(lpCV->clsidConvertDefault)) )
+ uRet = OLEUI_CTERR_CLASSIDINVALID;
+
+ if ( (lpCV->dwFlags & CF_SETACTIVATEDEFAULT)
+ && (!IsValidClassID(lpCV->clsidActivateDefault)) )
+ uRet = OLEUI_CTERR_CLASSIDINVALID;
+
+ if ( (lpCV->dvAspect != DVASPECT_ICON)
+ && (lpCV->dvAspect != DVASPECT_CONTENT) )
+ uRet = OLEUI_CTERR_DVASPECTINVALID;
+
+ if ( (lpCV->wFormat >= CF_CLIPBOARDMIN)
+ && (lpCV->wFormat <= CF_CLIPBOARDMAX) )
+ {
+ TCHAR szTemp[8];
+
+ if (0 == GetClipboardFormatName(lpCV->wFormat, (LPTSTR)szTemp, 8))
+ uRet = OLEUI_CTERR_CBFORMATINVALID;
+ }
+
+
+ if ( (NULL != lpCV->lpszUserType)
+ && (IsBadReadPtr(lpCV->lpszUserType, 1)) )
+ uRet = OLEUI_CTERR_STRINGINVALID;
+
+ if ( (NULL != lpCV->lpszDefLabel)
+ && (IsBadReadPtr(lpCV->lpszDefLabel, 1)) )
+ uRet = OLEUI_CTERR_STRINGINVALID;
+
+ if (0!=lpCV->cClsidExclude)
+ {
+ if (NULL!=lpCV->lpClsidExclude && IsBadReadPtr(lpCV->lpClsidExclude
+ , lpCV->cClsidExclude*sizeof(CLSID)))
+ uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
+ }
+
+
+ if (OLEUI_ERR_STANDARDMIN <= uRet)
+ {
+ if (NULL!=hMemDlg)
+ FreeResource(hMemDlg);
+
+ return uRet;
+ }
+
+ //Now that we've validated everything, we can invoke the dialog.
+ uRet=UStandardInvocation(ConvertDialogProc, (LPOLEUISTANDARD)lpCV,
+ hMemDlg, MAKEINTRESOURCE(IDD_CONVERT));
+
+ return uRet;
+ }
+
+
+
+
+
+/*
+ * ConvertDialogProc
+ *
+ * Purpose:
+ * Implements the OLE Convert dialog as invoked through the
+ * OleUIConvert function.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ *
+ */
+
+BOOL CALLBACK EXPORT ConvertDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+ {
+ LPCONVERT lpCV;
+ UINT uRet = 0;
+ OLEUICHANGEICON ci;
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ lpCV=(LPCONVERT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, (UINT FAR *)&uRet);
+
+ //If the hook processed the message, we're done.
+ if (0!=uRet)
+ return (BOOL)uRet;
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ ConvertCleanup(hDlg, lpCV);
+ StandardCleanup(lpCV, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ // Process help message from Change Icon
+ if (iMsg == uMsgHelp)
+ {
+
+ PostMessage(lpCV->lpOCV->hWndOwner, uMsgHelp, wParam, lParam);
+ return FALSE;
+
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FConvertInit(hDlg, wParam, lParam);
+ return TRUE;
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDCV_ACTIVATELIST:
+ case IDCV_CONVERTLIST:
+ switch (wCode)
+ {
+ case LBN_SELCHANGE:
+
+ // Change "Results" window to reflect current selection
+ SetConvertResults(hDlg, lpCV);
+
+ // Update the icon we display, if we are indeed
+ // displaying an icon.
+ if ( (lpCV->dwFlags & CF_SELECTCONVERTTO)
+ && (lpCV->dvAspect == DVASPECT_ICON)
+ && (!lpCV->fCustomIcon) )
+ UpdateCVClassIcon(hDlg, lpCV, hWndMsg);
+
+ break;
+
+ case LBN_DBLCLK:
+ //Same as pressing OK.
+ SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
+ break;
+ }
+ break;
+
+ case IDCV_CONVERTTO:
+ case IDCV_ACTIVATEAS:
+ {
+ HWND hList, hListInvisible;
+ LRESULT lRetVal;
+ BOOL fState;
+
+ hList = lpCV->hListVisible;
+ hListInvisible = lpCV->hListInvisible;
+
+
+ if (IDCV_CONVERTTO == wParam)
+ {
+
+ // User just click on the button again - it was
+ // already selected.
+ if (lpCV->dwFlags & CF_SELECTCONVERTTO)
+ break;
+
+
+ // Turn painting updates off.
+ SendMessage(hDlg, WM_SETREDRAW, FALSE, 0L);
+
+
+ // If we're working with a linked object, don't
+ // add the activate list - just the object's
+ // class should appear in the listbox.
+
+ SwapWindows(hDlg,
+ hList,
+ hListInvisible);
+
+ lpCV->hListVisible = hListInvisible;
+ lpCV->hListInvisible = hList;
+
+ EnableWindow(lpCV->hListInvisible, FALSE);
+ EnableWindow(lpCV->hListVisible, TRUE);
+
+ // Update our flags.
+ lpCV->dwFlags &= ~CF_SELECTACTIVATEAS;
+ lpCV->dwFlags |= CF_SELECTCONVERTTO;
+
+ }
+ else
+ {
+ if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
+ break;
+
+ // Turn painting updates off.
+ SendMessage(hDlg, WM_SETREDRAW, FALSE, 0L);
+
+ SwapWindows(hDlg,
+ hList,
+ hListInvisible);
+
+ lpCV->hListVisible = hListInvisible;
+ lpCV->hListInvisible = hList;
+
+ EnableWindow(lpCV->hListInvisible, FALSE);
+ EnableWindow(lpCV->hListVisible, TRUE);
+
+
+ // Update our flags.
+ lpCV->dwFlags |= CF_SELECTACTIVATEAS;
+ lpCV->dwFlags &= ~CF_SELECTCONVERTTO;
+ }
+
+
+ if (lpCV->dwFlags & CF_SELECTCONVERTTO)
+ lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszConvertDefault);
+ else
+ lRetVal = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)lpCV->lpszActivateDefault);
+
+ if (LB_ERR == lRetVal)
+ {
+ TCHAR szCurrentObject[40];
+
+ GetDlgItemText(hDlg, IDCV_OBJECTTYPE, (LPTSTR)szCurrentObject, 40);
+ SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szCurrentObject);
+ }
+
+ // Turn updates back on.
+ SendMessage(hDlg, WM_SETREDRAW, TRUE, 0L);
+
+ InvalidateRect(lpCV->hListVisible, NULL, TRUE);
+ UpdateWindow(lpCV->hListVisible);
+
+ if ((lpCV->dvAspect & DVASPECT_ICON) && (lpCV->dwFlags & CF_SELECTCONVERTTO))
+ UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible);
+
+ // Hide the icon stuff when Activate is selected...show
+ // it again when Convert is selected.
+
+ fState = ((lpCV->dwFlags & CF_SELECTACTIVATEAS) ||
+ (lpCV->dwFlags & CF_DISABLEDISPLAYASICON)) ?
+ SW_HIDE : SW_SHOW;
+
+ StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, fState);
+
+ // Only display the icon if convert is selected AND
+ // display as icon is checked.
+ if ((SW_SHOW==fState) && (DVASPECT_ICON!=lpCV->dvAspect))
+ fState = SW_HIDE;
+
+ StandardShowDlgItem(hDlg, IDCV_CHANGEICON, fState);
+ StandardShowDlgItem(hDlg, IDCV_ICON, fState);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, fState);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, fState);
+
+ SetConvertResults(hDlg, lpCV);
+
+ }
+ break;
+
+
+ case IDOK:
+ {
+
+ LRESULT iCurSel;
+ LPTSTR lpszCLSID;
+ TCHAR szBuffer[256];
+
+ // Set OUT parameters
+
+ //
+ // Set output flags to current ones
+ //
+ lpCV->lpOCV->dwFlags = lpCV->dwFlags;
+
+
+ // Update the dvAspect and fObjectsIconChanged members
+ // as appropriate.
+ //
+ if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
+ {
+ // DON'T update aspect if activate as was selected.
+ lpCV->lpOCV->fObjectsIconChanged = FALSE;
+ }
+ else
+ lpCV->lpOCV->dvAspect = lpCV->dvAspect;
+
+
+ //
+ // Get the new clsid
+ //
+ iCurSel = SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0);
+ SendMessage(lpCV->hListVisible, LB_GETTEXT, iCurSel, (LPARAM)szBuffer);
+
+ lpszCLSID = PointerToNthField((LPTSTR)szBuffer, 2, TEXT('\t'));
+
+ CLSIDFromStringA(lpszCLSID, (&(lpCV->lpOCV->clsidNew)));
+
+ // Free the hMetaPict we got in.
+ OleUIMetafilePictIconFree(lpCV->lpOCV->hMetaPict);
+
+ //
+ // Get the hMetaPict (if display as icon is checked)
+ //
+ if (DVASPECT_ICON == lpCV->dvAspect)
+ {
+ HICON hIcon;
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ INT Index;
+
+
+ // Create the hMetaPict here from icon, label,
+ // index, and path
+
+ hIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_GETICON, 0, 0L);
+
+ // the combined length of the 2 label lines won't ever be more than
+ // OLEUI_CCHLABELMAX.
+ Index = (INT)SendDlgItemMessage(hDlg, IDCV_ICONLABEL1,
+ WM_GETTEXT, OLEUI_CCHLABELMAX, (LPARAM)szLabel);
+
+ if (Index < OLEUI_CCHLABELMAX)
+ {
+ LPTSTR lpszSecondLine = szLabel + Index;
+
+
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_GETTEXT,
+ OLEUI_CCHLABELMAX-Index,
+ (LPARAM)lpszSecondLine);
+ }
+
+#ifdef OLE201
+ lpCV->lpOCV->hMetaPict =
+ OleUIMetafilePictFromIconAndLabel(hIcon,
+ (LPTSTR)szLabel,
+ lpCV->lpszIconSource,
+ lpCV->IconIndex);
+#endif
+
+ }
+ else
+ lpCV->lpOCV->hMetaPict = (HGLOBAL)NULL;
+
+
+ //
+ // End the dialog
+ //
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ }
+ break;
+
+ case IDCANCEL:
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+
+
+ case ID_OLEUIHELP:
+ PostMessage(lpCV->lpOCV->hWndOwner,
+ uMsgHelp, (WPARAM)hDlg, MAKELPARAM(IDD_CONVERT, 0));
+ break;
+
+ case IDCV_DISPLAYASICON:
+ {
+
+ int i;
+ BOOL fCheck;
+
+ fCheck=IsDlgButtonChecked(hDlg, wID);
+
+ if (fCheck)
+ lpCV->dvAspect = DVASPECT_ICON;
+ else
+ lpCV->dvAspect = DVASPECT_CONTENT;
+
+ if (fCheck && (!lpCV->fCustomIcon))
+ UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible);
+
+ //Show or hide the icon depending on the check state.
+
+ i=(fCheck) ? SW_SHOWNORMAL : SW_HIDE;
+
+ StandardShowDlgItem(hDlg, IDCV_CHANGEICON, i);
+ StandardShowDlgItem(hDlg, IDCV_ICON, i);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, i);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, i);
+
+ SetConvertResults(hDlg, lpCV);
+
+ }
+ break;
+
+ case IDCV_CHANGEICON:
+ {
+ LPMALLOC pIMalloc;
+ LPTSTR pszString, pszCLSID;
+ INT iSel;
+ HICON hIcon;
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ INT Index;
+
+
+ //Initialize the structure for the hook.
+ _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
+
+ // Create the hMetaPict here from icon, label,
+ // index, and path
+
+ hIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_GETICON, 0, 0L);
+
+ // the combined length of the 2 label lines won't ever be more than
+ // OLEUI_CCHLABELMAX.
+
+ Index = (INT)SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_GETTEXT,
+ OLEUI_CCHLABELMAX, (LPARAM)szLabel);
+
+ if (Index < OLEUI_CCHLABELMAX)
+ {
+ LPTSTR lpszSecondLine;
+
+ lpszSecondLine = szLabel + Index;
+
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_GETTEXT,
+ OLEUI_CCHLABELMAX-Index,
+ (LPARAM)lpszSecondLine);
+ }
+
+#ifdef OLE201
+ ci.hMetaPict =
+ OleUIMetafilePictFromIconAndLabel(hIcon,
+ szLabel,
+ lpCV->lpszIconSource,
+ lpCV->IconIndex);
+#endif
+
+ ci.cbStruct =sizeof(ci);
+ ci.hWndOwner=hDlg;
+ ci.dwFlags = CIF_SELECTCURRENT;
+
+ // Only show help if we're showing it for this dialog.
+ if (lpCV->dwFlags & CF_SHOWHELPBUTTON)
+ ci.dwFlags |= CIF_SHOWHELP;
+
+ iSel = (INT)SendMessage(lpCV->hListVisible, LB_GETCURSEL, 0, 0L);
+
+ CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+
+ pszString = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc,
+ OLEUI_CCHLABELMAX_SIZE +
+ OLEUI_CCHCLSIDSTRING_SIZE);
+
+ // Get whole string
+ SendMessage(lpCV->hListVisible, LB_GETTEXT, iSel, (LONG)pszString);
+
+ // Set pointer to CLSID (string)
+ pszCLSID = PointerToNthField(pszString, 2, TEXT('\t'));
+
+ // Get the clsid to pass to change icon.
+ CLSIDFromStringA(pszCLSID, &(ci.clsid));
+
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszString);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+
+ //Let the hook in to customize Change Icon if desired.
+ uRet=UStandardHook(lpCV, hDlg, uMsgChangeIcon
+ , 0, (LONG)(LPTSTR)&ci);
+
+ if (0==uRet)
+ uRet=(UINT)(OLEUI_OK==OleUIChangeIcon((LPOLEUICHANGEICON)&ci));
+
+ //Update the display if necessary.
+ if (0!=uRet)
+ {
+ HICON hIcon;
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ DWORD dwWrapIndex;
+
+
+ hIcon = OleUIMetafilePictExtractIcon(ci.hMetaPict);
+
+ SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
+
+ OleUIMetafilePictExtractIconSource(ci.hMetaPict, lpCV->lpszIconSource, &(lpCV->IconIndex));
+
+ OleUIMetafilePictExtractLabel(ci.hMetaPict, szLabel, OLEUI_CCHLABELMAX, &dwWrapIndex);
+
+ if (0 == dwWrapIndex) // no second line
+ {
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel);
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)TEXT(""));
+ }
+ else
+ {
+
+ LPTSTR lpszSecondLine;
+
+ lpszSecondLine = szLabel + dwWrapIndex;
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2,
+ WM_SETTEXT, 0, (LPARAM)lpszSecondLine);
+
+ *lpszSecondLine = TEXT('\0');
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL1,
+ WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel);
+ }
+
+
+ // Update our custom/default flag
+
+ if (ci.dwFlags & CIF_SELECTDEFAULT)
+ lpCV->fCustomIcon = FALSE; // we're in default mode (icon changes on each LB selchange)
+ else if (ci.dwFlags & CIF_SELECTFROMFILE)
+ lpCV->fCustomIcon = TRUE; // we're in custom mode (icon doesn't change)
+ // no change in fCustomIcon if user selected current
+
+
+ lpCV->lpOCV->fObjectsIconChanged = TRUE;
+ }
+ }
+ break;
+
+ }
+ break;
+ }
+ return FALSE;
+ }
+
+
+/*
+ * FConvertInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Convert dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FConvertInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+ {
+ LPCONVERT lpCV;
+ LPOLEUICONVERT lpOCV;
+ LPMALLOC pIMalloc;
+ HFONT hFont; // non-bold version of dialog's font
+ RECT rc;
+ DWORD dw;
+ INT cItemsActivate;
+ HKEY hKey;
+ LONG lRet;
+ UINT nRet;
+
+
+ //Copy the structure at lParam into our instance memory.
+ lpCV=(LPCONVERT)LpvStandardInit(hDlg, sizeof(CONVERT), TRUE, (HFONT FAR *)&hFont);
+
+ //PvStandardInit send a termination to us already.
+ if (NULL==lpCV)
+ return FALSE;
+
+ lpOCV=(LPOLEUICONVERT)lParam;
+
+ lpCV->lpOCV=lpOCV;
+
+ lpCV->fCustomIcon = FALSE;
+
+ //Copy other information from lpOCV that we might modify.
+ lpCV->dwFlags = lpOCV->dwFlags;
+ lpCV->clsid = lpOCV->clsid;
+ lpCV->dvAspect = lpOCV->dvAspect;
+ lpCV->hListVisible = GetDlgItem(hDlg, IDCV_ACTIVATELIST);
+ lpCV->hListInvisible = GetDlgItem(hDlg, IDCV_CONVERTLIST);
+ lpCV->lpszCurrentObject = lpOCV->lpszUserType;
+
+ lpOCV->clsidNew = CLSID_NULL;
+
+ lpOCV->fObjectsIconChanged = FALSE;
+
+ //Allocate space for our strings
+ if (NOERROR != CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ return FALSE;
+
+ lpCV->lpszConvertDefault = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHLABELMAX_SIZE);
+ lpCV->lpszActivateDefault = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHLABELMAX_SIZE);
+ lpCV->lpszIconSource = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHPATHMAX_SIZE);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+
+ //If we got a font, send it to the necessary controls.
+ if (NULL!=hFont)
+ {
+ SendDlgItemMessage(hDlg, IDCV_OBJECTTYPE, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDCV_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+ //Hide the help button if necessary
+ if (!(lpCV->dwFlags & CF_SHOWHELPBUTTON))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+ //Fill the Object Type listbox with entries from the reg DB.
+ nRet = FillClassList(lpOCV->clsid,
+ lpCV->hListVisible,
+ lpCV->hListInvisible,
+ &(lpCV->lpszCurrentObject),
+ lpOCV->fIsLinkedObject,
+ lpOCV->wFormat,
+ lpOCV->cClsidExclude,
+ lpOCV->lpClsidExclude);
+
+ if (nRet == -1) {
+ // bring down dialog if error when filling list box
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
+ }
+
+ // Set the name of the current object.
+ SetDlgItemText(hDlg, IDCV_OBJECTTYPE, (LPTSTR)lpCV->lpszCurrentObject);
+
+ // Disable the "Activate As" button if the Activate list doesn't
+ // have any objects in it.
+
+ cItemsActivate = (INT)SendMessage(lpCV->hListVisible, LB_GETCOUNT, 0, 0L);
+
+ if (1 >= cItemsActivate || (lpCV->dwFlags & CF_DISABLEACTIVATEAS))
+ EnableWindow(GetDlgItem(hDlg, IDCV_ACTIVATEAS), FALSE);
+
+ //Set the tab width in the list to push all the tabs off the side.
+ GetClientRect(lpCV->hListVisible, (LPRECT)&rc);
+ dw=GetDialogBaseUnits();
+ rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
+ SendMessage(lpCV->hListVisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rc.right));
+ SendMessage(lpCV->hListInvisible, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)(&rc.right));
+
+
+ // Make sure that either "Convert To" or "Activate As" is selected
+ // and initialize listbox contents and selection accordingly
+ if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
+ {
+ // Don't need to adjust listbox here because FillClassList
+ // initializes to the "Activate As" state.
+ CheckRadioButton(hDlg, IDCV_CONVERTTO, IDCV_ACTIVATEAS, IDCV_ACTIVATEAS);
+
+ // Hide the icon stuff when Activate is selected...it gets shown
+ // again when Convert is selected.
+
+ StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE);
+ }
+ else
+ {
+ // Default case. If user hasn't selected either flag, we will
+ // come here anyway.
+ // swap listboxes.
+
+ HWND hWndTemp = lpCV->hListVisible;
+
+ if ( lpCV->dwFlags & CF_DISABLEDISPLAYASICON ) {
+ StandardShowDlgItem(hDlg, IDCV_DISPLAYASICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE);
+ }
+
+ lpCV->dwFlags |= CF_SELECTCONVERTTO; // Make sure flag is set
+ CheckRadioButton(hDlg, IDCV_CONVERTTO, IDCV_ACTIVATEAS, IDCV_CONVERTTO);
+
+ SwapWindows(hDlg, lpCV->hListVisible, lpCV->hListInvisible);
+
+ lpCV->hListVisible = lpCV->hListInvisible;
+ lpCV->hListInvisible = hWndTemp;
+
+ EnableWindow(lpCV->hListInvisible, FALSE);
+ EnableWindow(lpCV->hListVisible, TRUE);
+ }
+
+
+
+ // Initialize Default strings.
+
+ // Default convert string is easy...just user the user type name from
+ // the clsid we got, or the current object
+ if ( (lpCV->dwFlags & CF_SETCONVERTDEFAULT)
+ && (IsValidClassID(lpCV->lpOCV->clsidConvertDefault)) )
+ {
+ dw = OleStdGetUserTypeOfClass((LPCLSID)(&lpCV->lpOCV->clsidConvertDefault),
+ lpCV->lpszConvertDefault,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL);
+
+ if (0 == dw)
+ lstrcpy((LPTSTR)lpCV->lpszConvertDefault, (LPTSTR)lpCV->lpszCurrentObject);
+ }
+ else
+ lstrcpy((LPTSTR)lpCV->lpszConvertDefault, (LPTSTR)lpCV->lpszCurrentObject);
+
+
+ // Default activate is a bit trickier. We want to use the user type
+ // name if from the clsid we got (assuming we got one), or the current
+ // object if it fails or we didn't get a clsid. But...if there's a
+ // Treat As entry in the reg db, then we use that instead. So... the
+ // logic boils down to this:
+ //
+ // if ("Treat As" in reg db)
+ // use it;
+ // else
+ // if (CF_SETACTIVATEDEFAULT)
+ // use it;
+ // else
+ // use current object;
+
+
+
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), (HKEY FAR *)&hKey);
+
+ if (lRet != ERROR_SUCCESS)
+ goto CheckInputFlag;
+
+ else
+ {
+ LPTSTR lpszCLSID;
+ TCHAR szKey[OLEUI_CCHKEYMAX];
+ CLSID clsid;
+ TCHAR szValue[OLEUI_CCHKEYMAX];
+
+ StringFromCLSIDA(&(lpCV->lpOCV->clsid), &lpszCLSID);
+ lstrcpy(szKey, lpszCLSID);
+ lstrcat(szKey, TEXT("\\TreatAs"));
+
+ dw = OLEUI_CCHKEYMAX_SIZE;
+ lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, (LPDWORD)&dw);
+
+ if (lRet != ERROR_SUCCESS)
+ {
+
+ RegCloseKey(hKey);
+ OleStdFreeString(lpszCLSID, NULL);
+ goto CheckInputFlag;
+ }
+ else
+ {
+ CLSIDFromStringA(szValue, &clsid);
+
+ if (0 == OleStdGetUserTypeOfClass(&clsid,
+ lpCV->lpszActivateDefault,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL))
+ {
+ RegCloseKey(hKey);
+ OleStdFreeString(lpszCLSID, NULL);
+ goto CheckInputFlag;
+ }
+ }
+ RegCloseKey(hKey);
+ OleStdFreeString(lpszCLSID, NULL);
+ goto SelectStringInListbox;
+ }
+
+
+CheckInputFlag:
+ if ( (lpCV->dwFlags & CF_SETACTIVATEDEFAULT)
+ && (IsValidClassID(lpCV->lpOCV->clsidActivateDefault)) )
+ {
+ dw = OleStdGetUserTypeOfClass((LPCLSID)(&lpCV->lpOCV->clsidActivateDefault),
+ lpCV->lpszActivateDefault,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL);
+
+ if (0 == dw)
+ lstrcpy((LPTSTR)lpCV->lpszActivateDefault, (LPTSTR)lpCV->lpszCurrentObject);
+ }
+ else
+ lstrcpy((LPTSTR)(lpCV->lpszActivateDefault), (LPTSTR)lpCV->lpszCurrentObject);
+
+
+SelectStringInListbox:
+
+ if (lpCV->dwFlags & CF_SELECTCONVERTTO)
+ lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)(lpCV->lpszConvertDefault));
+
+ else
+ lRet = SendMessage(lpCV->hListVisible, LB_SELECTSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)(lpCV->lpszActivateDefault));
+
+ if (LB_ERR == lRet)
+ SendMessage(lpCV->hListVisible, LB_SETCURSEL, (WPARAM)0, 0L);
+
+
+ // Initialize icon stuff
+ if (DVASPECT_ICON == lpCV->dvAspect )
+ {
+ SendDlgItemMessage(hDlg, IDCV_DISPLAYASICON, BM_SETCHECK, TRUE, 0L);
+
+ if ((HGLOBAL)NULL != lpOCV->hMetaPict)
+ {
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ HICON hIcon;
+ DWORD dwWrapIndex;
+
+
+ // Set the icon to the icon from the hMetaPict,
+ // set the label to the label from the hMetaPict.
+
+ if (0 != OleUIMetafilePictExtractLabel(lpOCV->hMetaPict, (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, &dwWrapIndex))
+ {
+ if (0 == dwWrapIndex) // no second line
+ {
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel);
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)TEXT(""));
+ }
+ else
+ {
+
+ LPTSTR lpszSecondLine;
+
+ lpszSecondLine = szLabel + dwWrapIndex;
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2,
+ WM_SETTEXT, 0, (LPARAM)lpszSecondLine);
+
+ *lpszSecondLine = TEXT('\0');
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL1,
+ WM_SETTEXT, 0, (LPARAM)(LPTSTR)szLabel);
+ }
+
+
+ }
+
+ hIcon = OleUIMetafilePictExtractIcon(lpOCV->hMetaPict);
+
+ if (NULL != hIcon)
+ {
+ SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
+ lpCV->fCustomIcon = TRUE;
+ }
+
+ OleUIMetafilePictExtractIconSource(lpOCV->hMetaPict,
+ (LPTSTR)(lpCV->lpszIconSource),
+ &(lpCV->IconIndex));
+
+ }
+ else
+ UpdateCVClassIcon(hDlg, lpCV, lpCV->hListVisible);
+ }
+ else
+ {
+ // Hide & disable icon stuff
+ StandardShowDlgItem(hDlg, IDCV_ICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL1, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_ICONLABEL2, SW_HIDE);
+ StandardShowDlgItem(hDlg, IDCV_CHANGEICON, SW_HIDE);
+ }
+
+ // Call the hook with lCustData in lParam
+ UStandardHook((LPVOID)lpCV, hDlg, WM_INITDIALOG, wParam, lpOCV->lCustData);
+ // Update results window
+ SetConvertResults(hDlg, lpCV);
+
+ // Update caption if lpszCaption was specified
+ if (lpCV->lpOCV->lpszCaption && !IsBadReadPtr(lpCV->lpOCV->lpszCaption, 1)
+ && lpCV->lpOCV->lpszCaption[0] != '\0')
+ SetWindowText(hDlg, (LPTSTR)lpCV->lpOCV->lpszCaption);
+
+ return TRUE;
+ }
+
+
+/*
+ * FillClassList
+ *
+ * Purpose:
+ * Enumerates available OLE object classes from the registration
+ * database that we can convert or activate the specified clsid from.
+ *
+ * Note that this function removes any prior contents of the listbox.
+ *
+ * Parameters:
+ * clsid Class ID for class to find convert classes for
+ * hList HWND to the listbox to fill.
+ * hListActivate HWND to invisible listbox that stores "activate as" list.
+ * lpszClassName LPSTR to put the (hr) class name of the clsid; we
+ * do it here since we've already got the reg db open.
+ * fIsLinkedObject BOOL is the original object a linked object
+ * wFormat WORD specifying the format of the original class.
+ * cClsidExclude UINT number of entries in exclude list
+ * lpClsidExclude LPCLSID array classes to exclude for list
+ *
+ * Return Value:
+ * UINT Number of strings added to the listbox, -1 on failure.
+ */
+
+UINT FillClassList(
+ CLSID clsid,
+ HWND hList,
+ HWND hListInvisible,
+ LPTSTR FAR *lplpszCurrentClass,
+ BOOL fIsLinkedObject,
+ WORD wFormat,
+ UINT cClsidExclude,
+ LPCLSID lpClsidExclude)
+{
+
+ DWORD dw;
+ UINT cStrings=0;
+ HKEY hKey;
+ LONG lRet;
+ TCHAR szFormatKey[OLEUI_CCHKEYMAX];
+ TCHAR szClass[OLEUI_CCHKEYMAX];
+ TCHAR szFormat[OLEUI_CCHKEYMAX];
+ TCHAR szHRClassName[OLEUI_CCHKEYMAX];
+ CLSID clsidForList;
+
+ LPTSTR lpszCLSID;
+
+
+ //Clean out the existing strings.
+ SendMessage(hList, LB_RESETCONTENT, 0, 0L);
+ SendMessage(hListInvisible, LB_RESETCONTENT, 0, 0L);
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, (LPCTSTR) TEXT("CLSID"), (HKEY FAR *)&hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return (UINT)-1;
+
+ if (NULL == *lplpszCurrentClass)
+ {
+ // alloc buffer here...
+
+ LPMALLOC pIMalloc = NULL;
+ HRESULT hrErr;
+
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+
+ if (hrErr != NOERROR)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // Allocate space for lpszCurrentClass
+ *lplpszCurrentClass = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+
+ lRet = OleStdGetUserTypeOfClass((REFCLSID)&clsid,
+ *lplpszCurrentClass,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL);
+
+ if (0 ==lRet)
+ {
+ INT n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, *lplpszCurrentClass,
+ OLEUI_CCHKEYMAX);
+ if (!n)
+ {
+ OutputDebugString(TEXT("Cannot LoadString\n"));
+ RegCloseKey(hKey);
+ return (UINT)-1;
+ }
+ }
+ }
+
+ // Get the class name of the original class.
+ StringFromCLSIDA(&clsid, &lpszCLSID);
+
+
+ // Here, we step through the entire registration db looking for
+ // class that can read or write the original class' format. We
+ // maintain two lists - an activate list and a convert list. The
+ // activate list is a subset of the convert list - activate == read/write
+ // and convert == read. We swap the listboxes as needed with
+ // SwapWindows, and keep track of which is which in the lpCV structure.
+
+ // Every item has the following format:
+ //
+ // Class Name\tclsid\0
+
+
+ cStrings=0;
+ lRet=RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE);
+
+ while ((LONG)ERROR_SUCCESS==lRet)
+ {
+ INT j;
+ BOOL fExclude=FALSE;
+
+
+ //Check if this CLSID is in the exclusion list.
+ CLSIDFromStringA(szClass, &clsidForList);
+
+ for (j=0; j < (int)cClsidExclude; j++)
+ {
+ if (IsEqualCLSID(&clsidForList, (LPCLSID)(lpClsidExclude+j)))
+ {
+ fExclude=TRUE;
+ break;
+ }
+ }
+ if (fExclude)
+ goto Next; // don't add this class to list
+
+ // Check for a \Conversion\Readwritable\Main - if its
+ // readwriteable, then the class can be added to the ActivateAs
+ // list.
+ // NOTE: the presence of this key should NOT automatically be
+ // used to add the class to the CONVERT list.
+
+ lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass);
+ lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readwritable\\Main"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+
+ lRet=RegQueryValue(hKey, (LPTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw);
+
+ if ( ((LONG)ERROR_SUCCESS==lRet)
+ && (FormatIncluded((LPTSTR)szFormat, wFormat)) )
+ {
+ // Here, we've got a list of formats that this class can read
+ // and write. We need to see if the original class' format is
+ // in this list. We do that by looking for wFormat in
+ // szFormat - if it in there, then we add this class to the
+ // ACTIVATEAS list only. we do NOT automatically add it to the
+ // CONVERT list. Readable and Readwritable format lists should
+ // be handled separately.
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, (LPTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+ lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t"));
+
+ // only add if not already in list
+ if (LB_ERR==SendMessage(hList,LB_FINDSTRING, 0,
+ (LPARAM)(LPSTR)szHRClassName)) {
+ lstrcat((LPTSTR)szHRClassName, (LPTSTR)szClass);
+ SendMessage(hList, LB_ADDSTRING, 0,
+ (DWORD)(LPTSTR)szHRClassName);
+ }
+ }
+
+ }
+
+
+ // Here we'll check to see if the original class' format is in the
+ // readable list. if so, we will add the class to the CONVERTLIST
+
+
+ // We've got a special case for a linked object here.
+ // If an object is linked, then the only class that
+ // should appear in the convert list is the object's
+ // class. So, here we check to see if the object is
+ // linked. If it is, then we compare the classes. If
+ // they aren't the same, then we just go to the next key.
+
+ if ( (!fIsLinkedObject)||(lstrcmp((LPCTSTR)lpszCLSID, szClass) == 0))
+ {
+
+ //Check for a \Conversion\Readable\Main entry
+ lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass);
+ lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readable\\Main"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+
+ // Check to see if this class can read the original class
+ // format. If it can, add the string to the listbox as
+ // CONVERT_LIST.
+
+ lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LPDWORD)&dw);
+
+ if ( ((LONG)ERROR_SUCCESS==lRet)
+ && (FormatIncluded((LPTSTR)szFormat, wFormat)) )
+ {
+
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, (LPCTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+ lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t"));
+
+ // only add if not already in list
+ if (LB_ERR==SendMessage(hListInvisible,LB_FINDSTRING, 0,
+ (LPARAM)(LPSTR)szHRClassName)) {
+ lstrcat((LPTSTR)szHRClassName, szClass);
+ SendMessage(hListInvisible, LB_ADDSTRING, 0,
+ (DWORD)(LPTSTR)szHRClassName);
+ }
+ } // end if
+
+ } // end if
+ } // end else
+Next:
+ //Continue with the next key.
+ lRet=RegEnumKey(hKey, cStrings++, (LPTSTR)szClass, OLEUI_CCHKEYMAX_SIZE);
+
+ } // end while
+
+ // If the original class isn't already in the list, add it.
+
+ lstrcpy((LPTSTR)szHRClassName, *lplpszCurrentClass);
+ lstrcat((LPTSTR)szHRClassName, (LPTSTR) TEXT("\t"));
+
+ lRet = SendMessage(hList, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szHRClassName);
+
+ // only add it if it's not there already.
+ if (LB_ERR == lRet) {
+ lstrcat((LPTSTR)szHRClassName, lpszCLSID);
+ SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)szHRClassName);
+ }
+
+ lRet = SendMessage(hListInvisible, LB_FINDSTRING, (WPARAM)-1, (LPARAM)(LPTSTR)szHRClassName);
+
+ // only add it if it's not there already.
+ if (LB_ERR == lRet)
+ SendMessage(hListInvisible, LB_ADDSTRING, 0, (LPARAM)(LPTSTR)szHRClassName);
+
+ // Free the string we got from StringFromCLSID.
+ // OLE2NOTE: StringFromCLSID uses your IMalloc to alloc a
+ // string, so you need to be sure to free the string you
+ // get back, otherwise you'll have leaky memory.
+
+ OleStdFreeString(lpszCLSID, NULL);
+
+ RegCloseKey(hKey);
+
+ return cStrings;
+}
+
+
+/*
+ * OleUICanConvertOrActivateAs
+ *
+ * Purpose:
+ * Determine if there is any OLE object class from the registration
+ * database that we can convert or activate the specified clsid from.
+ *
+ * Parameters:
+ * rClsid REFCLSID Class ID for class to find convert classes for
+ * fIsLinkedObject BOOL is the original object a linked object
+ * wFormat WORD specifying the format of the original class.
+ *
+ * Return Value:
+ * BOOL TRUE if Convert command should be enabled, else FALSE
+ */
+
+STDAPI_(BOOL) OleUICanConvertOrActivateAs(
+ REFCLSID rClsid,
+ BOOL fIsLinkedObject,
+ WORD wFormat
+)
+{
+
+ DWORD dw;
+ UINT cStrings=0;
+ HKEY hKey;
+ LONG lRet;
+ TCHAR szFormatKey[OLEUI_CCHKEYMAX];
+ TCHAR szClass[OLEUI_CCHKEYMAX];
+ TCHAR szFormat[OLEUI_CCHKEYMAX];
+ TCHAR szHRClassName[OLEUI_CCHKEYMAX];
+ BOOL fEnableConvert = FALSE;
+
+ LPTSTR lpszCLSID;
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, "CLSID", (HKEY FAR *)&hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return FALSE;
+
+ // Get the class name of the original class.
+ StringFromCLSIDA(rClsid, &lpszCLSID);
+
+ // Here, we step through the entire registration db looking for
+ // class that can read or write the original class' format.
+ // This loop stops if a single class is found.
+
+ cStrings=0;
+ lRet=RegEnumKey(hKey, cStrings++, szClass, OLEUI_CCHKEYMAX_SIZE);
+
+ while ((LONG)ERROR_SUCCESS==lRet)
+ {
+ if (lstrcmp(lpszCLSID, szClass)== 0)
+ goto next; // we don't want to consider the source class
+
+ // Check for a \Conversion\ReadWriteable\Main entry first - if its
+ // readwriteable, then we don't need to bother checking to see if
+ // its readable.
+
+ lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass);
+ lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readwritable\\Main"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+
+ lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw);
+
+ if ( (LONG)ERROR_SUCCESS != lRet)
+ {
+ // Try \\DataFormats\DefaultFile too
+
+ lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass);
+ lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\DataFormats\\DefaultFile"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+
+ lRet=RegQueryValue(hKey, (LPCTSTR)szFormatKey, (LPTSTR)szFormat, (LONG FAR *)&dw);
+ }
+
+
+ if ( ((LONG)ERROR_SUCCESS==lRet)
+ && (FormatIncluded((LPTSTR)szFormat, wFormat)) )
+ {
+
+ // Here, we've got a list of formats that this class can read
+ // and write. We need to see if the original class' format is
+ // in this list. We do that by looking for wFormat in
+ // szFormat - if it in there, then we add this class to the
+ // both lists and continue. If not, then we look at the
+ // class' readable formats.
+
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, (LPCTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+ fEnableConvert = TRUE;
+ break; // STOP -- found one!
+ }
+
+ }
+
+
+ // We either didn't find the readwritable key, or the
+ // list of readwritable formats didn't include the
+ // original class format. So, here we'll check to
+ // see if its in the readable list.
+
+
+ // We've got a special case for a linked object here.
+ // If an object is linked, then the only class that
+ // should appear in the convert list is the object's
+ // class. So, here we check to see if the object is
+ // linked. If it is, then we compare the classes. If
+ // they aren't the same, then we just go to the next key.
+
+ else if ( (!fIsLinkedObject)||
+ (lstrcmp((LPTSTR)lpszCLSID, (LPTSTR)szClass)== 0))
+ {
+
+ //Check for a \Conversion\Readable\Main entry
+ lstrcpy((LPTSTR)szFormatKey, (LPTSTR)szClass);
+ lstrcat((LPTSTR)szFormatKey, (LPTSTR) TEXT("\\Conversion\\Readable\\Main"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+
+ // Check to see if this class can read the original class
+ // format. If it can, add the string to the listbox as
+ // CONVERT_LIST.
+
+ lRet=RegQueryValue(hKey, (LPTSTR)szFormatKey, (LPTSTR)szFormat, (LPDWORD)&dw);
+
+ if ( ((LONG)ERROR_SUCCESS==lRet)
+ && (FormatIncluded((LPTSTR)szFormat, wFormat)) )
+ {
+
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, (LPTSTR)szClass, (LPTSTR)szHRClassName, (LPDWORD)&dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+
+ fEnableConvert = TRUE;
+ break; // STOP -- found one!
+ } // end if
+
+ } // end if
+ } // end else
+next:
+ //Continue with the next key.
+ lRet=RegEnumKey(hKey, cStrings++, (LPTSTR)szClass, OLEUI_CCHKEYMAX_SIZE);
+
+ } // end while
+
+ // Free the string we got from StringFromCLSID.
+ // OLE2NOTE: StringFromCLSID uses your IMalloc to alloc a
+ // string, so you need to be sure to free the string you
+ // get back, otherwise you'll have leaky memory.
+
+ OleStdFreeString(lpszCLSID, NULL);
+
+ RegCloseKey(hKey);
+
+ return fEnableConvert;
+}
+
+
+/*
+ * FormatIncluded
+ *
+ * Purpose:
+ * Parses the string for format from the word.
+ *
+ * Parameters:
+ * szStringToSearch String to parse
+ * wFormat format to find
+ *
+ * Return Value:
+ * BOOL TRUE if format is found in string,
+ * FALSE otherwise.
+ */
+BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat)
+{
+
+ LPTSTR lpToken;
+ TCHAR seps[] = TEXT(",");
+ static TCHAR szFormat[255]; // max size of atom (what GetClipboardName returns)
+
+
+ if (wFormat < 0xC000) // RegisterClipboardFormat returns values
+ {
+ char szTemp[11];
+
+ _itoa(wFormat, szTemp, 10); // between 0xC000 and 0xFFFF.
+
+#ifdef UNICODE
+ mbstowcs(szFormat, szTemp, 11);
+#else
+ strncpy(szFormat, szTemp, 11);
+#endif
+
+ }
+
+ else
+ GetClipboardFormatName(wFormat, szFormat, 255);
+
+ lpToken = (LPTSTR)_fstrtok(szStringToSearch, seps);
+
+ while (lpToken != NULL)
+ {
+
+ if (0 ==lstrcmpi(lpToken, szFormat))
+ return TRUE;
+
+ else
+ lpToken = (LPTSTR)_fstrtok(NULL, seps);
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * UpdateCVClassIcon
+ *
+ * Purpose:
+ * Handles LBN_SELCHANGE for the Object Type listbox. On a selection
+ * change, we extract an icon from the server handling the currently
+ * selected object type using the utility function HIconFromClass.
+ * Note that we depend on the behavior of FillClassList to stuff the
+ * object class after a tab in the listbox string that we hide from
+ * view (see WM_INITDIALOG).
+ *
+ * Parameters
+ * hDlg HWND of the dialog box.
+ * lpCV LPCONVERT pointing to the dialog structure
+ * hList HWND of the Object Type listbox.
+ *
+ * Return Value:
+ * None
+ */
+
+void UpdateCVClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList)
+ {
+ UINT iSel;
+ DWORD cb;
+ HGLOBAL hMem;
+ LPTSTR pszName, pszCLSID;
+ CLSID clsid;
+ HICON hIcon, hOldIcon;
+ UINT cch, uWrapIndex;
+ RECT LabelRect;
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ LPTSTR lpszLabel = szLabel;
+ HFONT hFont;
+ HWND hLabel1;
+
+ /*
+ * When we change object type selection, get the new icon for that
+ * type into our structure and update it in the display.
+ */
+
+ iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+
+ if (LB_ERR==(INT)iSel)
+ return;
+
+ //Allocate a string to hold the entire listbox string
+ cb=SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
+
+ hMem=GlobalAlloc(GHND, cb+1);
+
+ if (NULL==hMem)
+ return;
+
+ pszName=GlobalLock(hMem);
+
+ // Get whole string
+ SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName);
+
+ // Set pointer to CLSID (string)
+ pszCLSID = PointerToNthField(pszName, 2, TEXT('\t'));
+
+ //Create the class ID with this string.
+ CLSIDFromStringA(pszCLSID, &clsid);
+
+ hIcon = HIconAndSourceFromClass(&clsid, (LPTSTR)(lpCV->lpszIconSource), &(lpCV->IconIndex));
+
+ if (NULL == hIcon) // Use Vanilla Document
+ {
+ lstrcpy((LPTSTR)(lpCV->lpszIconSource), (LPTSTR)szOLE2DLL);
+ lpCV->IconIndex = 0; // 1st icon in OLE2.DLL
+ hIcon = ExtractIcon(ghInst,
+ (LPTSTR)(lpCV->lpszIconSource),
+ lpCV->IconIndex);
+ }
+
+ //Replace the current display with this new one.
+ hOldIcon = (HICON)SendDlgItemMessage(hDlg, IDCV_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
+
+ hLabel1 = GetDlgItem(hDlg, IDCV_ICONLABEL1);
+
+ GetWindowRect(hLabel1, &LabelRect);
+
+ // Get the label
+ if (lpCV->lpOCV->lpszDefLabel) {
+ // width is used as 1.5 times width of icon window
+ lpszLabel = ChopText(hLabel1, ((LabelRect.right-LabelRect.left)*3)/2, (LPTSTR)lpCV->lpOCV->lpszDefLabel);
+ LSTRCPYN(szLabel, lpCV->lpOCV->lpszDefLabel, sizeof(szLabel)/sizeof(TCHAR));
+ } else {
+ if ((cch = OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME,
+ (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) == 0) {
+ // If we can't get the AuxUserType2, then try the long name
+ if ((cch = OleStdGetUserTypeOfClass(&clsid, (LPTSTR)szLabel,
+ OLEUI_CCHKEYMAX_SIZE, NULL)) == 0) {
+ // last resort; use "Document" as label
+ LoadString(ghInst,IDS_DEFICONLABEL,(LPTSTR)szLabel,OLEUI_CCHLABELMAX);
+ cch = lstrlen((LPCTSTR)szLabel);
+ }
+ }
+ }
+
+ hFont = (HFONT)SendMessage(hLabel1, WM_GETFONT, 0, 0L);
+
+ // Figure out where to split the label
+ uWrapIndex = OleStdIconLabelTextOut(NULL, hFont, 0, 0, 0, &LabelRect, (LPTSTR)lpszLabel, cch, NULL);
+
+ if (0 == uWrapIndex)
+ {
+ SendMessage(hLabel1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)lpszLabel);
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)(LPTSTR)"");
+ }
+ else
+ {
+ TCHAR chKeep;
+ LPTSTR lpszSecondLine;
+
+ chKeep = szLabel[uWrapIndex];
+ lpszLabel[uWrapIndex] = TEXT('\0');
+
+ SendMessage(hLabel1, WM_SETTEXT, 0, (LPARAM)(LPTSTR)lpszLabel);
+
+ lpszLabel[uWrapIndex] = chKeep;
+ lpszSecondLine = lpszLabel + uWrapIndex;
+
+ SendDlgItemMessage(hDlg, IDCV_ICONLABEL2, WM_SETTEXT, 0, (LPARAM)lpszSecondLine);
+ }
+
+ // get rid of the old icon
+ if ((HICON)NULL != hOldIcon)
+ DestroyIcon(hOldIcon);
+
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ return;
+ }
+
+
+
+
+
+
+BOOL IsValidClassID(CLSID cID)
+{
+ if (0 == _fmemcmp(&cID, &CLSID_NULL, sizeof(CLSID))) // if (CLSID_NULL == cID)
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+
+/*
+ * SetConvertResults
+ *
+ * Purpose:
+ * Centralizes setting of the Result display in the Convert
+ * dialog. Handles loading the appropriate string from the module's
+ * resources and setting the text, displaying the proper result picture,
+ * and showing the proper icon.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box so we can access controls.
+ * lpCV LPCONVERT in which we assume that the dwFlags is
+ * set to the appropriate radio button selection, and
+ * the list box has the appropriate class selected.
+ *
+ * Return Value:
+ * None
+ */
+
+void SetConvertResults(HWND hDlg, LPCONVERT lpCV)
+ {
+ LPTSTR pszT, // temp
+ lpszOutput, // text sent in SetDlgItemText
+ lpszDefObj, // string containing default object class
+ lpszSelObj, // string containing selected object class
+ lpszString; // stirng we get from loadstring
+
+ UINT i, cch;
+ HGLOBAL hMem;
+
+ HWND hList; // handle to listbox (so we can just use SendMsg i
+ // instead of SendDlgItemMsg).
+
+
+ hList = lpCV->hListVisible;
+ /*
+ * We need scratch memory for loading the stringtable string, loading
+ * the object type from the listbox, loading the source object
+ * type, and constructing the final string. We therefore allocate
+ * four buffers as large as the maximum message length (512) plus
+ * the object type, guaranteeing that we have enough
+ * in all cases.
+ */
+ i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+
+ cch=512+(UINT)SendMessage(hList, LB_GETTEXTLEN, i, 0L);
+
+ hMem=GlobalAlloc(GHND, (DWORD)(4*cch));
+
+ if (NULL==hMem)
+ return;
+
+ lpszOutput = (LPTSTR)GlobalLock(hMem);
+ lpszSelObj = lpszOutput + cch;
+ lpszDefObj = lpszSelObj + cch;
+ lpszString = lpszDefObj + cch;
+
+ // Get selected object and null terminate human-readable name (1st field).
+ SendMessage(hList, LB_GETTEXT, i, (LONG)lpszSelObj);
+
+ pszT = PointerToNthField(lpszSelObj, 2, TEXT('\t'));
+
+#ifdef WIN32
+ // AnsiPrev is obsolete in Win32
+ pszT = CharPrev((LPCTSTR) lpszSelObj, (LPCTSTR) pszT);
+#else
+ pszT = AnsiPrev((LPCTSTR) lpszSelObj, (LPCTSTR) pszT);
+#endif
+
+ *pszT = TEXT('\0');
+
+ // Get default object
+
+ GetDlgItemText(hDlg, IDCV_OBJECTTYPE, lpszDefObj, 512);
+
+
+ //Default is an empty string.
+ *lpszOutput=0;
+
+
+ if (lpCV->dwFlags & CF_SELECTCONVERTTO)
+ {
+
+ if (lpCV->lpOCV->fIsLinkedObject) // working with linked object
+ LoadString(ghInst, IDS_CVRESULTCONVERTLINK, lpszOutput, cch);
+
+ else
+ {
+ // converting to a new class
+ if (0 !=lstrcmp(lpszDefObj, lpszSelObj))
+ {
+ if (0 != LoadString(ghInst, IDS_CVRESULTCONVERTTO, lpszString, cch))
+ wsprintf(lpszOutput, lpszString, lpszDefObj, lpszSelObj);
+
+ }
+ else // converting to the same class (no conversion)
+ {
+
+ if (0 != LoadString(ghInst, IDS_CVRESULTNOCHANGE, lpszString, cch))
+ wsprintf(lpszOutput, lpszString, lpszDefObj);
+ }
+
+ }
+
+ if (lpCV->dvAspect == DVASPECT_ICON) // Display as icon is checked
+ {
+ if (0 != LoadString(ghInst, IDS_CVRESULTDISPLAYASICON, lpszString, cch))
+ lstrcat(lpszOutput, lpszString);
+ }
+ }
+
+ if (lpCV->dwFlags & CF_SELECTACTIVATEAS)
+ {
+
+ if (0!=LoadString(ghInst, IDS_CVRESULTACTIVATEAS, lpszString, cch))
+ wsprintf(lpszOutput, lpszString, lpszDefObj, lpszSelObj);
+
+ // activating as a new class
+ if (0 !=lstrcmp(lpszDefObj, lpszSelObj))
+ {
+ if (0!=LoadString(ghInst, IDS_CVRESULTACTIVATEDIFF, lpszString, cch))
+ lstrcat(lpszOutput, lpszString);
+ }
+ else // activating as itself.
+ {
+ lstrcat(lpszOutput, TEXT("."));
+ }
+ }
+
+
+ //If LoadString failed, we simply clear out the results (*lpszOutput=0 above)
+ SetDlgItemText(hDlg, IDCV_RESULTTEXT, lpszOutput);
+
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ return;
+ }
+
+
+
+
+
+
+/*
+ * ConvertCleanup
+ *
+ * Purpose:
+ * Performs convert-specific cleanup before Convert termination.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box so we can access controls.
+ *
+ * Return Value:
+ * None
+ */
+void ConvertCleanup(HWND hDlg, LPCONVERT lpCV)
+{
+
+ LPMALLOC pIMalloc;
+
+
+ // Free our strings. Zero out the user type name string
+ // the the calling app doesn't free to it.
+
+ if (NOERROR == CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ {
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszConvertDefault);
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszActivateDefault);
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpCV->lpszIconSource);
+ if (lpCV->lpOCV->lpszUserType) {
+ pIMalloc->lpVtbl->Free(pIMalloc,(LPVOID)lpCV->lpOCV->lpszUserType);
+ lpCV->lpOCV->lpszUserType = NULL;
+ }
+ if (lpCV->lpOCV->lpszDefLabel) {
+ pIMalloc->lpVtbl->Free(pIMalloc,(LPVOID)lpCV->lpOCV->lpszDefLabel);
+ lpCV->lpOCV->lpszDefLabel = NULL;
+ }
+
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ }
+
+ return;
+}
+
+
+
+
+
+/*
+ * SwapWindows
+ *
+ * Purpose:
+ * Moves hWnd1 to hWnd2's position and hWnd2 to hWnd1's position.
+ * Does NOT change sizes.
+ *
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box so we can turn redraw off
+ *
+ * Return Value:
+ * None
+ */
+void SwapWindows(HWND hDlg, HWND hWnd1, HWND hWnd2)
+{
+
+ RECT Rect1, Rect2;
+
+
+ GetWindowRect(hWnd1, &Rect1);
+ GetWindowRect(hWnd2, &Rect2);
+
+ ScreenToClient(hDlg, (LPPOINT)&Rect1.left);
+ ScreenToClient(hDlg, (LPPOINT)&Rect1.right);
+
+ ScreenToClient(hDlg, (LPPOINT)&Rect2.left);
+ ScreenToClient(hDlg, (LPPOINT)&Rect2.right);
+
+ SetWindowPos(hWnd1,
+ NULL,
+ Rect2.left,
+ Rect2.top,
+ 0,
+ 0,
+ SWP_NOZORDER | SWP_NOSIZE);
+
+ SetWindowPos(hWnd2,
+ NULL,
+ Rect1.left,
+ Rect1.top,
+ 0,
+ 0,
+ SWP_NOZORDER | SWP_NOSIZE);
+
+ return;
+
+}
+
diff --git a/private/oleutest/letest/ole2ui/convert.dlg b/private/oleutest/letest/ole2ui/convert.dlg
new file mode 100644
index 000000000..4f6f4dfc0
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/convert.dlg
@@ -0,0 +1,32 @@
+
+IDD_CONVERT DIALOG 60, 26, 270, 146
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Convert"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ RTEXT "Current Type:", IDCV_STXCURTYPE, 5, 7, 47, 8
+ LTEXT "Current Object Type", IDCV_OBJECTTYPE, 55, 7, 129, 8
+ LTEXT "Object T&ype:", IDCV_STXCONVERTTO, 71, 21, 89, 8
+ LISTBOX IDCV_ACTIVATELIST, 71, 32, 118, 53,
+ LBS_USETABSTOPS | LBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ LISTBOX IDCV_CONVERTLIST, 350, 180, 118, 53,
+ LBS_USETABSTOPS | LBS_SORT | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 197, 6, 67, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 197, 24, 66, 14
+ PUSHBUTTON "&Help", ID_OLEUIHELP, 197, 42, 66, 14
+ CONTROL "&Display As Icon", IDCV_DISPLAYASICON, "Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP, 200, 61, 64, 10
+ GROUPBOX "Result", IDCV_GRPRESULT, 6, 87, 183, 50
+ CONTROL "&Convert to:", IDCV_CONVERTTO, "Button",
+ BS_AUTORADIOBUTTON, 6, 34, 59, 10
+ CONTROL "&Activate as:", IDCV_ACTIVATEAS, "Button",
+ BS_AUTORADIOBUTTON, 7, 58, 59, 10
+ LTEXT "Result Text...", IDCV_RESULTTEXT, 11, 98, 174, 27
+ ICON "", IDCV_ICON, 221, 75, 18, 20
+ CTEXT "", IDCV_ICONLABEL1, 197, 100, 66, 8
+ CTEXT "", IDCV_ICONLABEL2, 197, 108, 66, 12
+ PUSHBUTTON "Change &Icon...", IDCV_CHANGEICON, 197, 121, 67, 14
+END
+
+
+
diff --git a/private/oleutest/letest/ole2ui/convert.h b/private/oleutest/letest/ole2ui/convert.h
new file mode 100644
index 000000000..c6df6aa4f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/convert.h
@@ -0,0 +1,63 @@
+/*
+ * CONVERT.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Convert dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _CONVERT_H_
+#define _CONVERT_H_
+
+
+//Internally used structure
+typedef struct tagCONVERT
+ {
+ //Keep this item first as the Standard* functions depend on it here.
+ LPOLEUICONVERT lpOCV; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+
+ DWORD dwFlags; // Flags passed in
+ HWND hListVisible; // listbox that is currently visible
+ HWND hListInvisible; // listbox that is currently hidden
+ CLSID clsid; // Class ID sent in to dialog: IN only
+ DWORD dvAspect;
+ BOOL fCustomIcon;
+ UINT IconIndex; // index (in exe) of current icon
+ LPTSTR lpszIconSource; // path to current icon source
+ LPTSTR lpszCurrentObject;
+ LPTSTR lpszConvertDefault;
+ LPTSTR lpszActivateDefault;
+ } CONVERT, *PCONVERT, FAR *LPCONVERT;
+
+
+
+//Internal function prototypes in CONVERT.C
+BOOL CALLBACK EXPORT ConvertDialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL FConvertInit(HWND hDlg, WPARAM, LPARAM);
+UINT FPopulateListbox(HWND hListbox, CLSID cID);
+BOOL IsValidClassID(CLSID cID);
+void SetConvertResults(HWND, LPCONVERT);
+UINT FillClassList(
+ CLSID clsid,
+ HWND hList,
+ HWND hListInvisible,
+ LPTSTR FAR *lplpszCurrentClass,
+ BOOL fIsLinkedObject,
+ WORD wFormat,
+ UINT cClsidExclude,
+ LPCLSID lpClsidExclude);
+BOOL FormatIncluded(LPTSTR szStringToSearch, WORD wFormat);
+void UpdateCVClassIcon(HWND hDlg, LPCONVERT lpCV, HWND hList);
+void SwapWindows(HWND, HWND, HWND);
+void ConvertCleanup(HWND hDlg, LPCONVERT lpCV);
+
+#endif // _CONVERT_H_
diff --git a/private/oleutest/letest/ole2ui/daytona/makefile b/private/oleutest/letest/ole2ui/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/daytona/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/oleutest/letest/ole2ui/daytona/ole2u32a.src b/private/oleutest/letest/ole2ui/daytona/ole2u32a.src
new file mode 100644
index 000000000..fe30edf8e
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/daytona/ole2u32a.src
@@ -0,0 +1,200 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY ole2u32a
+
+DESCRIPTION 'ole2u32a'
+
+EXPORTS
+
+ SetDCToAnisotropic
+ SetDCToDrawInHimetricRect
+ ResetOrigDC
+ XformRectInPixelsToHimetric
+ XformRectInHimetricToPixels
+ XformSizeInPixelsToHimetric
+ XformSizeInHimetricToPixels
+ XformWidthInHimetricToPixels
+ XformWidthInPixelsToHimetric
+ XformHeightInHimetricToPixels
+ XformHeightInPixelsToHimetric
+ ParseCmdLine
+ OleStdIsOleLink
+ OleStdQueryInterface
+ OleStdCreateRootStorage
+ OleStdOpenRootStorage
+ OleStdOpenOrCreateRootStorage
+ OleStdCreateChildStorage
+ OleStdOpenChildStorage
+ OleStdCommitStorage
+ OleStdCreateStorageOnHGlobal
+ OleStdCreateTempStorage
+ OleStdDoConvert
+ OleStdGetTreatAsFmtUserType
+ OleStdDoTreatAsClass
+ OleStdSetupAdvises
+ OleStdSwitchDisplayAspect
+ OleStdSetIconInCache
+ OleStdGetData
+ OleStdMarkPasteEntryList
+ OleStdGetPriorityClipboardFormat
+ OleStdIsDuplicateFormat
+ OleStdRegisterAsRunning
+ OleStdRevokeAsRunning
+ OleStdNoteFileChangeTime
+ OleStdNoteObjectChangeTime
+ OleStdGetOleObjectData
+ OleStdGetLinkSourceData
+ OleStdGetObjectDescriptorData
+ OleStdGetObjectDescriptorDataFromOleObject
+ OleStdFillObjectDescriptorFromData
+ OleStdGetMetafilePictFromOleObject
+ OleStdCreateTempFileMoniker
+ OleStdGetFirstMoniker
+ OleStdGetLenFilePrefixOfMoniker
+ OleStdMalloc
+ OleStdRealloc
+ OleStdFree
+ OleStdGetSize
+ OleStdFreeString
+ OleStdCopyString
+ OleStdGetItemToken
+ OleStdInitVtbl
+ OleStdCheckVtbl
+ OleStdVerifyRelease
+ OleStdRelease
+ OleStdCreateDC
+ OleStdCreateIC
+ OleStdDeleteTargetDevice
+ OleStdCopyTargetDevice
+ OleStdCopyFormatEtc
+ FnAssert
+ OleDbgPrint
+ OleDbgPrintAlways
+ OleDbgSetDbgLevel
+ OleDbgGetDbgLevel
+ OleDbgIndent
+ OleDbgPrintRefCnt
+ OleDbgPrintRefCntAlways
+ OleDbgPrintRect
+ OleDbgPrintRectAlways
+ OleDbgPrintScodeAlways
+ OleUIInitialize
+ OleUIUnInitialize
+ OleUIAddVerbMenu
+ OleUIMetafilePictIconFree
+ OleUIMetafilePictIconDraw
+ OleUIMetafilePictExtractLabel
+ OleUIMetafilePictExtractIcon
+ OleUIMetafilePictExtractIconSource
+ OleUIInsertObject
+ OleUIPasteSpecial
+ OleUIEditLinks
+ OleUIChangeIcon
+ OleUIConvert
+ OleUIBusy
+ OleUIUpdateLinks
+ OleUIDrawHandles
+ OleUICanConvertOrActivateAs
+ OleUIDrawShading
+ OleUIShowObject
+ OleUIPromptUser
+ RegisterHatchWindowClass
+ CreateHatchWindow
+ GetHatchWidth
+ GetHatchRect
+ SetHatchRect
+ SetHatchWindowSize
+ OleStdEnumFmtEtc_Create
+ OleStdGetAuxUserType
+ OleStdGetUserTypeOfClass
+ OleStdIconLabelTextOut
+ OleStdMsgFilter_Create
+ OleStdMsgFilter_SetInComingCallStatus
+ OleStdMsgFilter_GetInComingCallStatus
+ OleStdMsgFilter_EnableBusyDialog
+ OleStdMsgFilter_EnableNotRespondingDialog
+ OleStdMsgFilter_SetParentWindow
+ OleStdGetMiscStatusOfClass
+ OleStdGetDefaultFileFormatOfClass
+ OleStdDestroyAllElements
+ OleStdCreateDbAlloc
+ OleStdInitSummaryInfo
+ OleStdFreeSummaryInfo
+ OleStdClearSummaryInfo
+ OleStdReadSummaryInfo
+ OleStdWriteSummaryInfo
+ OleStdGetSecurityProperty
+ OleStdSetSecurityProperty
+ OleStdGetStringProperty
+ OleStdSetStringProperty
+ OleStdGetStringZProperty
+ OleStdGetDocProperty
+ OleStdSetDocProperty
+ OleStdGetThumbNailProperty
+ OleStdSetThumbNailProperty
+ OleStdGetDateProperty
+ OleStdSetDateProperty
+ OleStdMsgFilter_SetHandleInComingCallbackProc
+ OleStdEnumStatData_Create
+ OleStdCopyStatData
+ OleStdCreateStandardPalette
+ OleStdMkParseDisplayName
+ CopyAndFreeOLESTR
+ CopyAndFreeSTR
+ CreateOLESTR
+ CreateSTR
+ CLSIDFromStringA
+ CLSIDFromProgIDA
+ CreateFileMonikerA
+ CreateItemMonikerA
+ GetClassFileA
+ MkParseDisplayNameA
+ OleCreateFromFileA
+ OleCreateLinkToFileA
+ OleGetIconOfClassA
+ OleGetIconOfFileA
+ OleMetafilePictFromIconAndLabelA
+ OleRegGetUserTypeA
+ ProgIDFromCLSIDA
+ ReadFmtUserTypeStgA
+ StgCreateDocfileA
+ StgOpenStorageA
+ StgSetTimesA
+ StringFromCLSIDA
+ WriteFmtUserTypeStgA
+ CallIMonikerGetDisplayNameA
+ CallIOleLinkGetSourceDisplayNameA
+ CallIOleLinkSetSourceDisplayNameA
+ CallIOleInPlaceFrameSetStatusTextA
+ CallIOleInPlaceUIWindowSetActiveObjectA
+ CallIOleObjectGetUserTypeA
+ CallIOleObjectSetHostNamesA
+ CallIStorageCreateStorageA
+ CallIStorageDestroyElementA
+ CallIStorageOpenStorageA
+ CallIStorageCreateStreamA
+ CallIStorageOpenStreamA
diff --git a/private/oleutest/letest/ole2ui/daytona/ole2ui.src b/private/oleutest/letest/ole2ui/daytona/ole2ui.src
new file mode 100644
index 000000000..24b82dcf6
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/daytona/ole2ui.src
@@ -0,0 +1,199 @@
+#if 0
+
+ Microsoft Windows
+ Copyright (C) Microsoft Corporation, 1992 - 1992.
+ All rights reserved.
+
+ This .def file is preprocessed by the compiler to create the version for
+ the current build in the appropriate subdir. Basically, whatever you
+ would have used in your code to control what is compiled when can be
+ used in this file for the same purpose. The following defines are in
+ use at the time this file was written:
+
+ FLAT - Used to indicate a NT/DOS7 build
+ i386 - Intel i386/i486 build
+ MIPS - MIPS R3000/R4000 build
+ ALPHA - DEC Alpha build
+ DBG - Used to control Debug/Retail. Set to 1 if Debug,
+ 0 if Retail.
+ WIN31 - Win16 build
+ __OS2__ - OS/2 build (used by CT mostly)
+
+ If none of these are used, it is assumed the entire file can be used
+ for all builds.
+
+#endif
+
+LIBRARY ole2ui
+
+DESCRIPTION 'ole2ui'
+
+EXPORTS
+
+ SetDCToAnisotropic
+ SetDCToDrawInHimetricRect
+ ResetOrigDC
+ XformRectInPixelsToHimetric
+ XformRectInHimetricToPixels
+ XformSizeInPixelsToHimetric
+ XformSizeInHimetricToPixels
+ XformWidthInHimetricToPixels
+ XformWidthInPixelsToHimetric
+ XformHeightInHimetricToPixels
+ XformHeightInPixelsToHimetric
+ ParseCmdLine
+ OleStdIsOleLink
+ OleStdQueryInterface
+ OleStdCreateRootStorage
+ OleStdOpenRootStorage
+ OleStdOpenOrCreateRootStorage
+ OleStdCreateChildStorage
+ OleStdOpenChildStorage
+ OleStdCommitStorage
+ OleStdCreateStorageOnHGlobal
+ OleStdCreateTempStorage
+ OleStdDoConvert
+ OleStdGetTreatAsFmtUserType
+ OleStdDoTreatAsClass
+ OleStdSetupAdvises
+ OleStdSwitchDisplayAspect
+ OleStdSetIconInCache
+ OleStdGetData
+ OleStdMarkPasteEntryList
+ OleStdGetPriorityClipboardFormat
+ OleStdIsDuplicateFormat
+ OleStdRegisterAsRunning
+ OleStdRevokeAsRunning
+ OleStdNoteFileChangeTime
+ OleStdNoteObjectChangeTime
+ OleStdGetOleObjectData
+ OleStdGetLinkSourceData
+ OleStdGetObjectDescriptorData
+ OleStdGetObjectDescriptorDataFromOleObject
+ OleStdFillObjectDescriptorFromData
+ OleStdGetMetafilePictFromOleObject
+ OleStdCreateTempFileMoniker
+ OleStdGetFirstMoniker
+ OleStdGetLenFilePrefixOfMoniker
+ OleStdMalloc
+ OleStdRealloc
+ OleStdFree
+ OleStdGetSize
+ OleStdFreeString
+ OleStdCopyString
+ OleStdGetItemToken
+ OleStdInitVtbl
+ OleStdCheckVtbl
+ OleStdVerifyRelease
+ OleStdRelease
+ OleStdCreateDC
+ OleStdCreateIC
+ OleStdDeleteTargetDevice
+ OleStdCopyTargetDevice
+ OleStdCopyFormatEtc
+ OleDbgPrint
+ OleDbgPrintAlways
+ OleDbgSetDbgLevel
+ OleDbgGetDbgLevel
+ OleDbgIndent
+ OleDbgPrintRefCnt
+ OleDbgPrintRefCntAlways
+ OleDbgPrintRect
+ OleDbgPrintRectAlways
+ OleDbgPrintScodeAlways
+ OleUIInitialize
+ OleUIUnInitialize
+ OleUIAddVerbMenu
+ OleUIMetafilePictIconFree
+ OleUIMetafilePictIconDraw
+ OleUIMetafilePictExtractLabel
+ OleUIMetafilePictExtractIcon
+ OleUIMetafilePictExtractIconSource
+ OleUIInsertObject
+ OleUIPasteSpecial
+ OleUIEditLinks
+ OleUIChangeIcon
+ OleUIConvert
+ OleUIBusy
+ OleUIUpdateLinks
+ OleUIDrawHandles
+ OleUICanConvertOrActivateAs
+ OleUIDrawShading
+ OleUIShowObject
+ OleUIPromptUser
+ RegisterHatchWindowClass
+ CreateHatchWindow
+ GetHatchWidth
+ GetHatchRect
+ SetHatchRect
+ SetHatchWindowSize
+ OleStdEnumFmtEtc_Create
+ OleStdGetAuxUserType
+ OleStdGetUserTypeOfClass
+ OleStdIconLabelTextOut
+ OleStdMsgFilter_Create
+ OleStdMsgFilter_SetInComingCallStatus
+ OleStdMsgFilter_GetInComingCallStatus
+ OleStdMsgFilter_EnableBusyDialog
+ OleStdMsgFilter_EnableNotRespondingDialog
+ OleStdMsgFilter_SetParentWindow
+ OleStdGetMiscStatusOfClass
+ OleStdGetDefaultFileFormatOfClass
+ OleStdDestroyAllElements
+ OleStdCreateDbAlloc
+ OleStdInitSummaryInfo
+ OleStdFreeSummaryInfo
+ OleStdClearSummaryInfo
+ OleStdReadSummaryInfo
+ OleStdWriteSummaryInfo
+ OleStdGetSecurityProperty
+ OleStdSetSecurityProperty
+ OleStdGetStringProperty
+ OleStdSetStringProperty
+ OleStdGetStringZProperty
+ OleStdGetDocProperty
+ OleStdSetDocProperty
+ OleStdGetThumbNailProperty
+ OleStdSetThumbNailProperty
+ OleStdGetDateProperty
+ OleStdSetDateProperty
+ OleStdMsgFilter_SetHandleInComingCallbackProc
+ OleStdEnumStatData_Create
+ OleStdCopyStatData
+ OleStdCreateStandardPalette
+ OleStdMkParseDisplayName
+ CopyAndFreeOLESTR
+ CopyAndFreeSTR
+ CreateOLESTR
+ CreateSTR
+ CLSIDFromStringA
+ CLSIDFromProgIDA
+ CreateFileMonikerA
+ CreateItemMonikerA
+ GetClassFileA
+ MkParseDisplayNameA
+ OleCreateFromFileA
+ OleCreateLinkToFileA
+ OleGetIconOfClassA
+ OleGetIconOfFileA
+ OleMetafilePictFromIconAndLabelA
+ OleRegGetUserTypeA
+ ProgIDFromCLSIDA
+ ReadFmtUserTypeStgA
+ StgCreateDocfileA
+ StgOpenStorageA
+ StgSetTimesA
+ StringFromCLSIDA
+ WriteFmtUserTypeStgA
+ CallIMonikerGetDisplayNameA
+ CallIOleLinkGetSourceDisplayNameA
+ CallIOleLinkSetSourceDisplayNameA
+ CallIOleInPlaceFrameSetStatusTextA
+ CallIOleInPlaceUIWindowSetActiveObjectA
+ CallIOleObjectGetUserTypeA
+ CallIOleObjectSetHostNamesA
+ CallIStorageCreateStorageA
+ CallIStorageDestroyElementA
+ CallIStorageOpenStorageA
+ CallIStorageCreateStreamA
+ CallIStorageOpenStreamA
diff --git a/private/oleutest/letest/ole2ui/daytona/sources b/private/oleutest/letest/ole2ui/daytona/sources
new file mode 100644
index 000000000..91c6ca237
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/daytona/sources
@@ -0,0 +1,64 @@
+
+MAJORCOMP = cairole
+MINORCOMP = com
+
+TARGETNAME= ole2u32a
+TARGETPATH= obj
+TARGETTYPE= DYNLINK
+
+DLLDEF= obj\*\ole2u32a.def
+DLLENTRY= DllEntryPoint
+DLLBASE=@$(BASEDIR)\PUBLIC\SDK\LIB\coffbase.txt,usermode
+
+INCLUDES=..
+
+C_DEFINES=-DWIN32 -DDEBUG -DINC_OLE2 -DCLIENT -DWINDOWS -DOLE201
+
+SOURCES= \
+ ..\BUSY.C \
+ ..\COMMON.C \
+ ..\CONVERT.C \
+ ..\DBALLOC.CPP \
+ ..\DBGUTIL.C \
+ ..\DLLENTRY.C \
+ ..\DLLFUNCS.C \
+ ..\DRAWICON.C \
+ ..\ENUMFETC.C \
+ ..\ENUMSTAT.C \
+ ..\GETICON.C \
+ ..\HATCH.C \
+ ..\ICON.C \
+ ..\ICONBOX.C \
+ ..\INSOBJ.C \
+ ..\LINKS.C \
+ ..\MSGFILTR.C \
+ ..\OBJFDBK.C \
+ ..\OLE2UI.C \
+ ..\OLESTD.C \
+ ..\OLETHUNK.C \
+ ..\OLEUTL.C \
+ ..\PASTESPL.C \
+ ..\PRECOMP.C \
+ ..\REGDB.C \
+ ..\RESIMAGE.C \
+ ..\STDPAL.C \
+ ..\SUMINFO.CPP \
+ ..\TARGTDEV.C \
+ ..\UTILITY.C \
+ ..\OLE2UI.RC
+
+UMTYPE=windows
+
+TARGETLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\ole32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\uuid.lib
+
+USE_CRTDLL= 1
+
+MISCFILES=..\..\data\letest12.olc
diff --git a/private/oleutest/letest/ole2ui/dballoc.cpp b/private/oleutest/letest/ole2ui/dballoc.cpp
new file mode 100644
index 000000000..b62259c64
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dballoc.cpp
@@ -0,0 +1,900 @@
+
+/***
+*dballoc.cpp
+*
+* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* This file contains a debug implementation of the IMalloc interface.
+*
+* This implementation is basically a simple wrapping of the C runtime,
+* with additional work to detect memory leakage, and memory overwrite.
+*
+* Leakage is detected by tracking each allocation in an address
+* instance table, and then checking to see if the table is empty
+* when the last reference to the allocator is released.
+*
+* Memory overwrite is detected by placing a signature at the end
+* of every allocated block, and checking to make sure the signature
+* is unchanged when the block is freed.
+*
+* This implementation also has additional param validation code, as
+* well as additional check make sure that instances that are passed
+* to Free() were actually allocated by the corresponding instance
+* of the allocator.
+*
+*
+* Creating an instance of this debug allocator that uses the default
+* output interface would look like the following,
+*
+*
+* BOOL init_application_instance()
+* {
+* HRESULT hresult;
+* IMalloc FAR* pmalloc;
+*
+* pmalloc = NULL;
+*
+* if((hresult = OleStdCreateDbAlloc(0,&pmalloc))!=NOERROR)
+* goto LReturn;
+*
+* hresult = OleInitialize(pmalloc);
+*
+* // release pmalloc to let OLE hold the only ref to the it. later
+* // when OleUnitialize is called, memory leaks will be reported.
+* if(pmalloc != NULL)
+* pmalloc->Release();
+*
+* LReturn:
+*
+* return (hresult == NOERROR) ? TRUE : FALSE;
+* }
+*
+*
+* CONSIDER: could add an option to force error generation, something
+* like DBALLOC_ERRORGEN
+*
+* CONSIDER: add support for heap-checking. say for example,
+* DBALLOC_HEAPCHECK would do a heapcheck every free? every 'n'
+* calls to free? ...
+*
+*
+*Implementation Notes:
+*
+* The method IMalloc::DidAlloc() is allowed to always return
+* "Dont Know" (-1). This method is called by Ole, and they take
+* some appropriate action when they get this answer.
+
+The debugging allocator has the option to catch bugs where code is writing off
+the end of allocated memory. This is implemented by using NT's virtual memory
+services. To switch on this option, use
+
+#define DBALLOC_POWERDEBUG
+
+Note it will ONLY WORK ON NT. This option consumes a very large amount of
+memory. Basically, for every allocation, it cooks the allocation so that the
+end of the allocation will fall on a page boundary. An extra page of memory
+is allocated after the requested memory. The protection bits for this page
+are altered so that it is an error to read or write to it. Any incident of
+writing past the end of allocated memory is trapped at the point of the error.
+
+This consumes a great deal of memory because at least two pages must be
+allocated for each allocation.
+*
+*****************************************************************************/
+
+
+// Note: this file is designed to be stand-alone; it includes a
+// carefully chosen, minimal set of headers.
+//
+// For conditional compilation we use the ole2 conventions,
+// _MAC = mac
+// WIN32 = Win32 (NT really)
+// <nothing> = defaults to Win16
+
+
+// REVIEW: the following needs to modified to handle _MAC
+#define STRICT
+#ifndef INC_OLE2
+ #define INC_OLE2
+#endif
+
+#include <windows.h>
+
+#include "ole2.h"
+
+#if defined( __TURBOC__)
+#define __STDC__ (1)
+#endif
+
+#define WINDLL 1 // make far pointer version of stdargs.h
+#include <stdarg.h>
+
+#if defined( __TURBOC__)
+#undef __STDC__
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <limits.h>
+
+#include "dballoc.h"
+
+
+#define DIM(X) (sizeof(X)/sizeof((X)[0]))
+
+#define UNREACHED 0
+
+#if defined(WIN32)
+# define MEMCMP(PV1, PV2, CB) memcmp((PV1), (PV2), (CB))
+# define MEMCPY(PV1, PV2, CB) memcpy((PV1), (PV2), (CB))
+# define MEMSET(PV, VAL, CB) memset((PV), (VAL), (CB))
+# define MALLOC(CB) malloc(CB)
+# define REALLOC(PV, CB) realloc((PV), (CB))
+# define FREE(PV) free(PV)
+
+#ifndef WIN32
+# define HEAPMIN() _heapmin()
+#else
+# define HEAPMIN()
+#endif
+
+#elif defined(_MAC)
+# define MEMCMP(PV1, PV2) ERROR -- NYI
+# define MEMCPY(PV1, PV2, CB) ERROR -- NYI
+# define MEMSET(PV, VAL, CB) ERROR -- NYI
+# define MALLOC(CB) ERROR -- NYI
+# define REALLOC(PV, CB) ERROR -- NYI
+# define FREE(PV) ERROR -- NYI
+# define HEAPMIN() ERROR -- NYI
+#else
+# define MEMCMP(PV1, PV2, CB) _fmemcmp((PV1), (PV2), (CB))
+# define MEMCPY(PV1, PV2, CB) _fmemcpy((PV1), (PV2), (CB))
+# define MEMSET(PV, VAL, CB) _fmemset((PV), (VAL), (CB))
+# define MALLOC(CB) _fmalloc(CB)
+# define REALLOC(PV, CB) _frealloc(PV, CB)
+# define FREE(PV) _ffree(PV)
+# define HEAPMIN() _fheapmin()
+#endif
+
+#if defined( __TURBOC__ )
+#define classmodel _huge
+#else
+#define classmodel FAR
+#endif
+
+class classmodel CStdDbOutput : public IDbOutput {
+public:
+ static IDbOutput FAR* Create();
+
+ // IUnknown methods
+
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+
+ // IDbOutput methods
+
+ STDMETHOD_(void, Printf)(TCHAR FAR* szFmt, ...);
+
+ STDMETHOD_(void, Assertion)(
+ BOOL cond,
+ TCHAR FAR* szExpr,
+ TCHAR FAR* szFile,
+ UINT uLine,
+ TCHAR FAR* szMsg);
+
+
+ void FAR* operator new(size_t cb){
+ return MALLOC(cb);
+ }
+ void operator delete(void FAR* pv){
+ FREE(pv);
+ }
+
+ CStdDbOutput(){
+ m_refs = 0;
+ }
+
+private:
+ ULONG m_refs;
+
+ TCHAR m_rgch[128]; // buffer for output formatting
+};
+
+
+//---------------------------------------------------------------------
+// implementation of the debug allocator
+//---------------------------------------------------------------------
+
+class FAR CAddrNode
+{
+public:
+ void FAR* m_pv; // instance
+ ULONG m_cb; // size of allocation in BYTES
+ ULONG m_nAlloc; // the allocation pass count
+ CAddrNode FAR* m_next;
+
+ void FAR* operator new(size_t cb){
+ return MALLOC(cb);
+ }
+ void operator delete(void FAR* pv){
+ FREE(pv);
+ }
+};
+
+
+class classmodel CDbAlloc : public IMalloc
+{
+public:
+ static HRESULT Create(
+ ULONG options, IDbOutput FAR* pdbout, IMalloc FAR* FAR* ppmalloc);
+
+ // IUnknown methods
+
+ STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppv);
+ STDMETHOD_(ULONG, AddRef)(void);
+ STDMETHOD_(ULONG, Release)(void);
+
+ // IMalloc methods
+
+ STDMETHOD_(void FAR*, Alloc)(ULONG cb);
+ STDMETHOD_(void FAR*, Realloc)(void FAR* pv, ULONG cb);
+ STDMETHOD_(void, Free)(void FAR* pv);
+ STDMETHOD_(ULONG, GetSize)(void FAR* pv);
+ STDMETHOD_(int, DidAlloc)(void FAR* pv);
+ STDMETHOD_(void, HeapMinimize)(void);
+
+
+ void FAR* operator new(size_t cb){
+ return MALLOC(cb);
+ }
+ void operator delete(void FAR* pv){
+ FREE(pv);
+ }
+
+ CDbAlloc(){
+ m_refs = 1;
+ m_pdbout = NULL;
+ m_cAllocCalls = 0;
+ m_nBreakAtNthAlloc = 0;
+ m_nBreakAtAllocSize = 0;
+ MEMSET(m_rganode, 0, sizeof(m_rganode));
+#ifdef DBALLOC_POWERDEBUG
+ {
+ SYSTEM_INFO si;
+
+ GetSystemInfo(&si);
+ m_virtPgSz = si.dwPageSize;
+ }
+#endif // DBALLOC_POWERDEBUG
+ }
+
+private:
+
+ ULONG m_refs;
+ ULONG m_cAllocCalls; // total count of allocation calls
+ ULONG m_nBreakAtNthAlloc; // allocation number to break to debugger
+ // this value should be set typically in the
+ // debugger.
+ ULONG m_nBreakAtAllocSize; // allocation size to break to debugger
+ // this value should be set typically in the
+ // debugger.
+ IDbOutput FAR* m_pdbout; // output interface
+ CAddrNode FAR* m_rganode[64]; // address instance table
+
+
+ // instance table methods
+
+ BOOL IsEmpty(void);
+
+ void AddInst(void FAR* pv, ULONG nAlloc, ULONG cb);
+ void DelInst(void FAR* pv);
+ CAddrNode FAR* GetInst(void FAR* pv);
+
+ void DumpInst(CAddrNode FAR* pn);
+ void DumpInstTable(void);
+
+ inline UINT HashInst(void FAR* pv) const {
+ return ((UINT)((ULONG)pv >> 4)) % DIM(m_rganode);
+
+ }
+
+ // output method(s)
+
+ inline void Assertion(
+ BOOL cond,
+ TCHAR FAR* szExpr,
+ TCHAR FAR* szFile,
+ UINT uLine,
+ TCHAR FAR* szMsg)
+ {
+ m_pdbout->Assertion(cond, szExpr, szFile, uLine, szMsg);
+ }
+
+ #define ASSERT(X) Assertion(X, TEXT(#X), TEXT(__FILE__), __LINE__, NULL)
+
+ #define ASSERTSZ(X, SZ) Assertion(X, TEXT(#X), TEXT(__FILE__), __LINE__, SZ)
+
+ static const BYTE m_rgchSig[];
+
+#ifdef DBALLOC_POWERDEBUG
+ size_t m_virtPgSz;
+#endif // DBALLOC_POWERDEBUG
+};
+
+const BYTE CDbAlloc::m_rgchSig[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+
+/***
+*HRESULT OleStdCreateDbAlloc(ULONG reserved, IMalloc** ppmalloc)
+* Purpose:
+* Create an instance of CDbAlloc -- a debug implementation
+* of IMalloc.
+*
+* Parameters:
+* ULONG reserved - reserved for future use. must be 0.
+* IMalloc FAR* FAR* ppmalloc - (OUT) pointer to an IMalloc interface
+* of new debug allocator object
+* Returns:
+* HRESULT
+* NOERROR - if no error.
+* E_OUTOFMEMORY - allocation failed.
+*
+***********************************************************************/
+STDAPI OleStdCreateDbAlloc(ULONG reserved,IMalloc FAR* FAR* ppmalloc)
+{
+ return CDbAlloc::Create(reserved, NULL, ppmalloc);
+}
+
+
+HRESULT
+CDbAlloc::Create(
+ ULONG options,
+ IDbOutput FAR* pdbout,
+ IMalloc FAR* FAR* ppmalloc)
+{
+ HRESULT hresult;
+ CDbAlloc FAR* pmalloc;
+
+
+ // default the instance of IDbOutput if the user didn't supply one
+ if(pdbout == NULL && ((pdbout = CStdDbOutput::Create()) == NULL)){
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto LError0;
+ }
+
+ pdbout->AddRef();
+
+ if((pmalloc = new FAR CDbAlloc()) == NULL){
+ hresult = ResultFromScode(E_OUTOFMEMORY);
+ goto LError1;
+ }
+
+ pmalloc->m_pdbout = pdbout;
+
+ *ppmalloc = pmalloc;
+
+ return NOERROR;
+
+LError1:;
+ pdbout->Release();
+ pmalloc->Release();
+
+LError0:;
+ return hresult;
+}
+
+STDMETHODIMP
+CDbAlloc::QueryInterface(REFIID riid, void FAR* FAR* ppv)
+{
+ if(IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IMalloc)){
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG)
+CDbAlloc::AddRef()
+{
+ return ++m_refs;
+}
+
+STDMETHODIMP_(ULONG)
+CDbAlloc::Release()
+{
+ if(--m_refs == 0){
+
+ // check for memory leakage
+ if(IsEmpty()){
+ m_pdbout->Printf(TEXT("No Memory Leaks.\n"));
+ }else{
+ m_pdbout->Printf(TEXT("Memory Leak Detected,\n"));
+ DumpInstTable();
+ }
+
+ m_pdbout->Release();
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+STDMETHODIMP_(void FAR*)
+CDbAlloc::Alloc(ULONG cb)
+{
+ size_t size;
+ void FAR* pv;
+
+ ++m_cAllocCalls;
+
+ if (m_nBreakAtNthAlloc && m_cAllocCalls == m_nBreakAtNthAlloc) {
+ ASSERTSZ(FALSE, TEXT("DBALLOC: NthAlloc Break target reached\r\n"));
+ } else if (m_nBreakAtAllocSize && cb == m_nBreakAtAllocSize) {
+ ASSERTSZ(FALSE, TEXT("DBALLOC: AllocSize Break target reached\r\n"));
+ }
+
+#ifndef DBALLOC_POWERDEBUG
+ // REVIEW: need to add support for huge allocations (on win16)
+ if((cb + sizeof(m_rgchSig)) > UINT_MAX)
+ return NULL;
+
+ size = (size_t)cb;
+
+ if((pv = MALLOC(size + sizeof(m_rgchSig))) == NULL)
+ return NULL;
+
+ // set allocated block to some non-zero value
+ MEMSET(pv, -1, size);
+
+ // put signature at end of allocated block
+ MEMCPY(((char FAR*)pv) + size, m_rgchSig, sizeof(m_rgchSig));
+
+ AddInst(pv, m_cAllocCalls, size);
+#else
+ // for each allocate, allocate the amount of memory required, and
+ // one more page beyond that. We will change the protection bits of
+ // the trailing page so that we get an access violation if someone
+ // writes beyond the end of their allocated memory
+ {
+ size_t allocpgs; // number of pages to allocate
+ DWORD dwOldProt; // previous protection of the last page
+ void *plastpg; // points to the beginning of the last page
+
+ // allocate at least one page for the allocation, and
+ // one to go after it
+ allocpgs = (cb + 2*m_virtPgSz) / m_virtPgSz;
+ pv = VirtualAlloc(NULL, allocpgs*m_virtPgSz,
+ MEM_COMMIT, PAGE_READWRITE);
+
+ // change the protection of the last page
+ plastpg = (void *)(((BYTE *)pv)+m_virtPgSz*(allocpgs-1));
+ VirtualProtect(plastpg, m_virtPgSz, PAGE_NOACCESS, &dwOldProt);
+
+ // figure out what pointer to return to the user
+ pv = (void *)(((BYTE *)plastpg)-cb);
+
+ // record the allocation
+ AddInst(pv, m_cAllocCalls, cb);
+ }
+#endif // DBALLOC_POWERDEBUG
+
+ return pv;
+}
+
+STDMETHODIMP_(void FAR*)
+CDbAlloc::Realloc(void FAR* pv, ULONG cb)
+{
+ size_t size;
+ CAddrNode *pcan;
+
+#ifndef DBALLOC_POWERDEBUG
+ // REVIEW: need to add support for huge realloc
+ if((cb + sizeof(m_rgchSig)) > UINT_MAX)
+ return NULL;
+#endif // DBALLOC_POWERDEBUG
+
+ if(pv == NULL){
+ return Alloc(cb);
+ }
+
+ ++m_cAllocCalls;
+
+ ASSERT((pcan = GetInst(pv)) != NULL);
+#ifndef DBALLOC_POWERDEBUG
+
+ DelInst(pv);
+
+ if(cb == 0){
+ Free(pv);
+ return NULL;
+ }
+
+ size = (size_t)cb;
+
+ if((pv = REALLOC(pv, size + sizeof(m_rgchSig))) == NULL)
+ return NULL;
+
+ // put signature at end of allocated block
+ MEMCPY(((char FAR*)pv) + size, m_rgchSig, sizeof(m_rgchSig));
+
+ AddInst(pv, m_cAllocCalls, size);
+#else
+ {
+ void *pnew;
+ DWORD dwOldProt;
+
+ // allocate new memory
+ pnew = Alloc(cb);
+
+ // copy in the previous material
+ memcpy(pnew, pcan->m_pv, pcan->m_cb);
+
+ // protect the old memory
+ VirtualProtect(pcan->m_pv, pcan->m_cb, PAGE_NOACCESS,
+ &dwOldProt);
+
+ DelInst(pv);
+ AddInst(pv, m_cAllocCalls, cb);
+ pv = pnew;
+ }
+#endif // DBALLOC_POWERDEBUG
+
+ return pv;
+}
+
+STDMETHODIMP_(void)
+CDbAlloc::Free(void FAR* pv)
+{
+ if (pv == NULL)
+ {
+ // Free of NULL is a NO-OP
+ return;
+ }
+
+ CAddrNode FAR* pn;
+ static TCHAR szSigMsg[] = TEXT("Signature Check Failed");
+
+ pn = GetInst(pv);
+
+ // check for attempt to free an instance we didnt allocate
+ if(pn == NULL){
+ ASSERTSZ(FALSE, TEXT("pointer freed by wrong allocator"));
+ return;
+ }
+
+#ifndef DBALLOC_POWERDEBUG
+ // verify the signature
+ if(MEMCMP(((char FAR*)pv) + pn->m_cb, m_rgchSig, sizeof(m_rgchSig)) != 0){
+ m_pdbout->Printf(szSigMsg); m_pdbout->Printf(TEXT("\n"));
+ DumpInst(GetInst(pv));
+ ASSERTSZ(FALSE, szSigMsg);
+ }
+
+ // stomp on the contents of the block
+ MEMSET(pv, 0xCC, ((size_t)pn->m_cb + sizeof(m_rgchSig)));
+
+ DelInst(pv);
+ FREE(pv);
+#else
+ {
+ DWORD dwOldProt;
+
+ // make the block inaccessible
+ VirtualProtect(pv, pn->m_cb, PAGE_NOACCESS, &dwOldProt);
+ DelInst(pv);
+ }
+#endif // DBALLOC_POWERDEBUG
+}
+
+
+STDMETHODIMP_(ULONG)
+CDbAlloc::GetSize(void FAR* pv)
+{
+ CAddrNode FAR* pn;
+
+ if (pv == NULL)
+ {
+ // GetSize is supposed to return a -1 when NULL is passed in.
+ return (ULONG) -1;
+ }
+
+ pn = GetInst(pv);
+
+ if (pn == NULL) {
+ ASSERT(pn != NULL);
+ return 0;
+ }
+
+ return pn->m_cb;
+}
+
+
+/***
+*PUBLIC HRESULT CDbAlloc::DidAlloc
+*Purpose:
+* Answer if the given address belongs to a block allocated by
+* this allocator.
+*
+*Entry:
+* pv = the instance to lookup
+*
+*Exit:
+* return value = int
+* 1 - did alloc
+* 0 - did *not* alloc
+* -1 - dont know (according to the ole2 spec it is always legal
+* for the allocator to answer "dont know")
+*
+***********************************************************************/
+STDMETHODIMP_(int)
+CDbAlloc::DidAlloc(void FAR* pv)
+{
+ return -1; // answer "I dont know"
+}
+
+
+STDMETHODIMP_(void)
+CDbAlloc::HeapMinimize()
+{
+ HEAPMIN();
+}
+
+
+//---------------------------------------------------------------------
+// instance table methods
+//---------------------------------------------------------------------
+
+/***
+*PRIVATE CDbAlloc::AddInst
+*Purpose:
+* Add the given instance to the address instance table.
+*
+*Entry:
+* pv = the instance to add
+* nAlloc = the allocation passcount of this instance
+*
+*Exit:
+* None
+*
+***********************************************************************/
+void
+CDbAlloc::AddInst(void FAR* pv, ULONG nAlloc, ULONG cb)
+{
+ UINT hash;
+ CAddrNode FAR* pn;
+
+
+ ASSERT(pv != NULL);
+
+ pn = (CAddrNode FAR*)new FAR CAddrNode();
+
+ if (pn == NULL) {
+ ASSERT(pn != NULL);
+ return;
+ }
+
+ pn->m_pv = pv;
+ pn->m_cb = cb;
+ pn->m_nAlloc = nAlloc;
+
+ hash = HashInst(pv);
+ pn->m_next = m_rganode[hash];
+ m_rganode[hash] = pn;
+}
+
+
+/***
+*UNDONE
+*Purpose:
+* Remove the given instance from the address instance table.
+*
+*Entry:
+* pv = the instance to remove
+*
+*Exit:
+* None
+*
+***********************************************************************/
+void
+CDbAlloc::DelInst(void FAR* pv)
+{
+ CAddrNode FAR* FAR* ppn, FAR* pnDead;
+
+ for(ppn = &m_rganode[HashInst(pv)]; *ppn != NULL; ppn = &(*ppn)->m_next){
+ if((*ppn)->m_pv == pv){
+ pnDead = *ppn;
+ *ppn = (*ppn)->m_next;
+ delete pnDead;
+ // make sure it doesnt somehow appear twice
+ ASSERT(GetInst(pv) == NULL);
+ return;
+ }
+ }
+
+ // didnt find the instance
+ ASSERT(UNREACHED);
+}
+
+
+CAddrNode FAR*
+CDbAlloc::GetInst(void FAR* pv)
+{
+ CAddrNode FAR* pn;
+
+ for(pn = m_rganode[HashInst(pv)]; pn != NULL; pn = pn->m_next){
+ if(pn->m_pv == pv)
+ return pn;
+ }
+ return NULL;
+}
+
+
+void
+CDbAlloc::DumpInst(CAddrNode FAR* pn)
+{
+ if (pn == NULL)
+ return;
+
+ m_pdbout->Printf(TEXT("[0x%lx] nAlloc=%ld size=%ld\n"),
+ pn->m_pv, pn->m_nAlloc, GetSize(pn->m_pv));
+}
+
+
+/***
+*PRIVATE BOOL IsEmpty
+*Purpose:
+* Answer if the address instance table is empty.
+*
+*Entry:
+* None
+*
+*Exit:
+* return value = BOOL, TRUE if empty, FALSE otherwise
+*
+***********************************************************************/
+BOOL
+CDbAlloc::IsEmpty()
+{
+ UINT u;
+
+ for(u = 0; u < DIM(m_rganode); ++u){
+ if(m_rganode[u] != NULL)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/***
+*PRIVATE CDbAlloc::Dump
+*Purpose:
+* Print the current contents of the address instance table,
+*
+*Entry:
+* None
+*
+*Exit:
+* None
+*
+***********************************************************************/
+void
+CDbAlloc::DumpInstTable()
+{
+ UINT u;
+ CAddrNode FAR* pn;
+
+ for(u = 0; u < DIM(m_rganode); ++u){
+ for(pn = m_rganode[u]; pn != NULL; pn = pn->m_next){
+ DumpInst(pn);
+ }
+ }
+}
+
+
+//---------------------------------------------------------------------
+// implementation of CStdDbOutput
+//---------------------------------------------------------------------
+
+IDbOutput FAR*
+CStdDbOutput::Create()
+{
+ return (IDbOutput FAR*)new FAR CStdDbOutput();
+}
+
+STDMETHODIMP
+CStdDbOutput::QueryInterface(REFIID riid, void FAR* FAR* ppv)
+{
+ if(IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = this;
+ AddRef();
+ return NOERROR;
+ }
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG)
+CStdDbOutput::AddRef()
+{
+ return ++m_refs;
+}
+
+STDMETHODIMP_(ULONG)
+CStdDbOutput::Release()
+{
+ if(--m_refs == 0){
+ delete this;
+ return 0;
+ }
+ return m_refs;
+}
+
+STDMETHODIMP_(void)
+CStdDbOutput::Printf(TCHAR FAR* lpszFmt, ...)
+{
+ va_list args;
+ TCHAR szBuf[256];
+#if defined( OBSOLETE )
+ TCHAR *pn, FAR* pf;
+static TCHAR rgchFmtBuf[128];
+static TCHAR rgchOutputBuf[128];
+
+ // copy the 'far' format string to a near buffer so we can use
+ // a medium model vsprintf, which only supports near data pointers.
+ //
+ pn = rgchFmtBuf, pf=szFmt;
+ while(*pf != TEXT('\0'))
+ *pn++ = *pf++;
+ *pn = TEXT('\0');
+#endif
+
+ va_start(args, lpszFmt);
+
+// wvsprintf(rgchOutputBuf, rgchFmtBuf, args);
+ wvsprintf(szBuf, lpszFmt, args);
+
+ OutputDebugString(szBuf);
+}
+
+STDMETHODIMP_(void)
+CStdDbOutput::Assertion(
+ BOOL cond,
+ TCHAR FAR* szExpr,
+ TCHAR FAR* szFile,
+ UINT uLine,
+ TCHAR FAR* szMsg)
+{
+ if(cond)
+ return;
+
+#ifdef _DEBUG
+ // following is from compobj.dll (ole2)
+ #ifdef UNICODE
+ #ifndef NOASSERT
+ FnAssert(szExpr, szMsg, szFile, uLine);
+ #endif
+ #else
+ // we need to talk to comobj in UNICODE even though we are not defined
+ // as UNICODE
+ {
+ WCHAR wszExpr[255], wszMsg[255], wszFile[255];
+ mbstowcs(wszExpr, szExpr, 255);
+ mbstowcs(wszMsg, szMsg, 255);
+ mbstowcs(wszFile, szFile, 255);
+ #ifndef NOASSERT
+ FnAssert(wszExpr, wszMsg, wszFile, uLine);
+ #endif
+ }
+ #endif
+#else
+ // REVIEW: should be able to do something better that this...
+ DebugBreak();
+#endif
+}
diff --git a/private/oleutest/letest/ole2ui/dballoc.h b/private/oleutest/letest/ole2ui/dballoc.h
new file mode 100644
index 000000000..42ccbaff2
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dballoc.h
@@ -0,0 +1,36 @@
+/***
+*dballoc.h
+*
+* Copyright (C) 1992-93, Microsoft Corporation. All Rights Reserved.
+*
+*Purpose:
+* This file contains the definition of CDbAlloc - A debug implementation
+* of the IMalloc interface.
+*
+*Implementation Notes:
+*
+*****************************************************************************/
+
+#ifndef DBALLOC_H_INCLUDED /* { */
+#define DBALLOC_H_INCLUDED
+
+
+interface IDbOutput : public IUnknown
+{
+ STDMETHOD(QueryInterface)(THIS_ REFIID riid, void FAR* FAR* ppv) PURE;
+ STDMETHOD_(ULONG, AddRef)(THIS) PURE;
+ STDMETHOD_(ULONG, Release)(THIS) PURE;
+
+ STDMETHOD_(void, Printf)(THIS_
+ TCHAR FAR* szFmt, ...) PURE;
+
+ STDMETHOD_(void, Assertion)(THIS_
+ BOOL cond,
+ TCHAR FAR* szExpr,
+ TCHAR FAR* szFile,
+ UINT uLine,
+ TCHAR FAR* szMsg) PURE;
+};
+
+
+#endif /* } DBALLOC_H_INCLUDED */
diff --git a/private/oleutest/letest/ole2ui/dbgutil.c b/private/oleutest/letest/ole2ui/dbgutil.c
new file mode 100644
index 000000000..15c17a248
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dbgutil.c
@@ -0,0 +1,419 @@
+/*************************************************************************
+**
+** OLE 2.0 Common Utilities
+**
+** dbgutil.h
+**
+** This file contains file contains functions to support debug output.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#define STRICT 1
+#include "ole2ui.h"
+
+static int s_nDbgIndent = 0; // indent level for debug message
+#if defined( _DEBUG )
+static int s_nDbgLevel = 0; // default dbg level printed
+#else
+static int s_nDbgLevel = 0; // default dbg level printed
+#endif
+
+STDAPI_(void) OleDbgPrint(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ int nIndent
+)
+{
+ if (nDbgLvl <= s_nDbgLevel)
+ OleDbgPrintAlways(lpszPrefix, lpszMsg, nIndent);
+}
+
+
+STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent)
+{
+ int i;
+
+ if (nIndent < 0)
+ OleDbgIndent(nIndent);
+
+ if (lpszPrefix && *lpszPrefix != TEXT('\0')) {
+ OutputDebugString(TEXT("| "));
+ for (i = 0; i < s_nDbgIndent; i++)
+ OutputDebugString(TEXT("----"));
+
+ OutputDebugString(lpszPrefix);
+ OutputDebugString(TEXT(": "));
+ }
+
+ OutputDebugString(lpszMsg);
+ if (nIndent > 0)
+ OleDbgIndent(nIndent);
+}
+
+STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl)
+{
+ s_nDbgLevel = nDbgLvl;
+}
+
+STDAPI_(int) OleDbgGetDbgLevel( void )
+{
+ return s_nDbgLevel;
+}
+
+STDAPI_(void) OleDbgIndent(int n)
+{
+ switch (n) {
+ case -1:
+ s_nDbgIndent--;
+ break;
+ case 1:
+ s_nDbgIndent++;
+ break;
+ case -2:
+ s_nDbgIndent = 0;
+ break;
+ }
+}
+
+
+STDAPI_(void) OleDbgPrintRefCnt(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+)
+{
+ if (nDbgLvl <= s_nDbgLevel)
+ OleDbgPrintRefCntAlways(lpszPrefix, lpszMsg, lpObj, refcnt);
+}
+
+
+STDAPI_(void) OleDbgPrintRefCntAlways(
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+)
+{
+#if defined( _DEBUG )
+ TCHAR szBuf[256];
+
+ wsprintf(szBuf, TEXT("[obj=(0x%lx) cnt=%ld] %s"), lpObj, refcnt, lpszMsg);
+ OleDbgPrintAlways(lpszPrefix, szBuf, 0);
+#endif
+}
+
+
+STDAPI_(void) OleDbgPrintRect(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPRECT lpRect
+)
+{
+ if (nDbgLvl <= s_nDbgLevel)
+ OleDbgPrintRectAlways(lpszPrefix, lpszMsg, lpRect);
+}
+
+
+STDAPI_(void) OleDbgPrintRectAlways(
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPRECT lpRect
+)
+{
+#if defined( _DEBUG )
+ TCHAR szBuf[256];
+
+ wsprintf(
+ szBuf,
+ TEXT("%s: (%d,%d)-(%d,%d) %dx%d\r\n"),
+ lpszMsg,
+ lpRect->left,
+ lpRect->top,
+ lpRect->right,
+ lpRect->bottom,
+ (lpRect->right-lpRect->left),
+ (lpRect->bottom-lpRect->top)
+ );
+ OleDbgPrintAlways(lpszPrefix, szBuf, 0);
+#endif
+}
+
+
+#define CASE_SCODE(sc) \
+ case sc: \
+ lstrcpy((LPTSTR)szErrName, (LPTSTR)#sc); \
+ break;
+
+STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc)
+{
+#if defined( _DEBUG )
+ TCHAR szBuf[256];
+ TCHAR szErrName[40];
+
+ switch (sc) {
+
+ /* SCODE's defined in SCODE.H */
+
+ CASE_SCODE(S_OK)
+ CASE_SCODE(S_FALSE)
+ CASE_SCODE(E_UNEXPECTED)
+ CASE_SCODE(E_OUTOFMEMORY)
+ CASE_SCODE(E_INVALIDARG)
+ CASE_SCODE(E_NOINTERFACE)
+ CASE_SCODE(E_POINTER)
+ CASE_SCODE(E_HANDLE)
+ CASE_SCODE(E_ABORT)
+ CASE_SCODE(E_FAIL)
+ CASE_SCODE(E_ACCESSDENIED)
+
+ /* SCODE's defined in OLE2.H */
+
+ CASE_SCODE(OLE_E_OLEVERB)
+ CASE_SCODE(OLE_E_ADVF)
+ CASE_SCODE(OLE_E_ENUM_NOMORE)
+ CASE_SCODE(OLE_E_ADVISENOTSUPPORTED)
+ CASE_SCODE(OLE_E_NOCONNECTION)
+ CASE_SCODE(OLE_E_NOTRUNNING)
+ CASE_SCODE(OLE_E_NOCACHE)
+ CASE_SCODE(OLE_E_BLANK)
+ CASE_SCODE(OLE_E_CLASSDIFF)
+ CASE_SCODE(OLE_E_CANT_GETMONIKER)
+ CASE_SCODE(OLE_E_CANT_BINDTOSOURCE)
+ CASE_SCODE(OLE_E_STATIC)
+ CASE_SCODE(OLE_E_PROMPTSAVECANCELLED)
+ CASE_SCODE(OLE_E_INVALIDRECT)
+ CASE_SCODE(OLE_E_WRONGCOMPOBJ)
+ CASE_SCODE(OLE_E_INVALIDHWND)
+ CASE_SCODE(OLE_E_NOT_INPLACEACTIVE)
+ CASE_SCODE(OLE_E_CANTCONVERT)
+ CASE_SCODE(OLE_E_NOSTORAGE)
+
+ CASE_SCODE(DV_E_FORMATETC)
+ CASE_SCODE(DV_E_DVTARGETDEVICE)
+ CASE_SCODE(DV_E_STGMEDIUM)
+ CASE_SCODE(DV_E_STATDATA)
+ CASE_SCODE(DV_E_LINDEX)
+ CASE_SCODE(DV_E_TYMED)
+ CASE_SCODE(DV_E_CLIPFORMAT)
+ CASE_SCODE(DV_E_DVASPECT)
+ CASE_SCODE(DV_E_DVTARGETDEVICE_SIZE)
+ CASE_SCODE(DV_E_NOIVIEWOBJECT)
+
+ CASE_SCODE(OLE_S_USEREG)
+ CASE_SCODE(OLE_S_STATIC)
+ CASE_SCODE(OLE_S_MAC_CLIPFORMAT)
+
+ CASE_SCODE(CONVERT10_E_OLESTREAM_GET)
+ CASE_SCODE(CONVERT10_E_OLESTREAM_PUT)
+ CASE_SCODE(CONVERT10_E_OLESTREAM_FMT)
+ CASE_SCODE(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB)
+ CASE_SCODE(CONVERT10_E_STG_FMT)
+ CASE_SCODE(CONVERT10_E_STG_NO_STD_STREAM)
+ CASE_SCODE(CONVERT10_E_STG_DIB_TO_BITMAP)
+ CASE_SCODE(CONVERT10_S_NO_PRESENTATION)
+
+ CASE_SCODE(CLIPBRD_E_CANT_OPEN)
+ CASE_SCODE(CLIPBRD_E_CANT_EMPTY)
+ CASE_SCODE(CLIPBRD_E_CANT_SET)
+ CASE_SCODE(CLIPBRD_E_BAD_DATA)
+ CASE_SCODE(CLIPBRD_E_CANT_CLOSE)
+
+ CASE_SCODE(DRAGDROP_E_NOTREGISTERED)
+ CASE_SCODE(DRAGDROP_E_ALREADYREGISTERED)
+ CASE_SCODE(DRAGDROP_E_INVALIDHWND)
+ CASE_SCODE(DRAGDROP_S_DROP)
+ CASE_SCODE(DRAGDROP_S_CANCEL)
+ CASE_SCODE(DRAGDROP_S_USEDEFAULTCURSORS)
+
+ CASE_SCODE(OLEOBJ_E_NOVERBS)
+ CASE_SCODE(OLEOBJ_E_INVALIDVERB)
+ CASE_SCODE(OLEOBJ_S_INVALIDVERB)
+ CASE_SCODE(OLEOBJ_S_CANNOT_DOVERB_NOW)
+ CASE_SCODE(OLEOBJ_S_INVALIDHWND)
+ CASE_SCODE(INPLACE_E_NOTUNDOABLE)
+ CASE_SCODE(INPLACE_E_NOTOOLSPACE)
+ CASE_SCODE(INPLACE_S_TRUNCATED)
+
+ /* SCODE's defined in COMPOBJ.H */
+
+ CASE_SCODE(CO_E_NOTINITIALIZED)
+ CASE_SCODE(CO_E_ALREADYINITIALIZED)
+ CASE_SCODE(CO_E_CANTDETERMINECLASS)
+ CASE_SCODE(CO_E_CLASSSTRING)
+ CASE_SCODE(CO_E_IIDSTRING)
+ CASE_SCODE(CO_E_APPNOTFOUND)
+ CASE_SCODE(CO_E_APPSINGLEUSE)
+ CASE_SCODE(CO_E_ERRORINAPP)
+ CASE_SCODE(CO_E_DLLNOTFOUND)
+ CASE_SCODE(CO_E_ERRORINDLL)
+ CASE_SCODE(CO_E_WRONGOSFORAPP)
+ CASE_SCODE(CO_E_OBJNOTREG)
+ CASE_SCODE(CO_E_OBJISREG)
+ CASE_SCODE(CO_E_OBJNOTCONNECTED)
+ CASE_SCODE(CO_E_APPDIDNTREG)
+ CASE_SCODE(CLASS_E_NOAGGREGATION)
+// CASE_SCODE(CLASS_E_CLASSNOTAVAILABLE)
+ CASE_SCODE(REGDB_E_READREGDB)
+ CASE_SCODE(REGDB_E_WRITEREGDB)
+ CASE_SCODE(REGDB_E_KEYMISSING)
+ CASE_SCODE(REGDB_E_INVALIDVALUE)
+ CASE_SCODE(REGDB_E_CLASSNOTREG)
+ CASE_SCODE(REGDB_E_IIDNOTREG)
+ CASE_SCODE(RPC_E_CALL_REJECTED)
+ CASE_SCODE(RPC_E_CALL_CANCELED)
+ CASE_SCODE(RPC_E_CANTPOST_INSENDCALL)
+ CASE_SCODE(RPC_E_CANTCALLOUT_INASYNCCALL)
+ CASE_SCODE(RPC_E_CANTCALLOUT_INEXTERNALCALL)
+ CASE_SCODE(RPC_E_CONNECTION_TERMINATED)
+ CASE_SCODE(RPC_E_SERVER_DIED)
+ CASE_SCODE(RPC_E_CLIENT_DIED)
+ CASE_SCODE(RPC_E_INVALID_DATAPACKET)
+ CASE_SCODE(RPC_E_CANTTRANSMIT_CALL)
+ CASE_SCODE(RPC_E_CLIENT_CANTMARSHAL_DATA)
+ CASE_SCODE(RPC_E_CLIENT_CANTUNMARSHAL_DATA)
+ CASE_SCODE(RPC_E_SERVER_CANTMARSHAL_DATA)
+ CASE_SCODE(RPC_E_SERVER_CANTUNMARSHAL_DATA)
+ CASE_SCODE(RPC_E_INVALID_DATA)
+ CASE_SCODE(RPC_E_INVALID_PARAMETER)
+// CASE_SCODE(RPC_E_CANTCALLOUT_AGAIN)
+ CASE_SCODE(RPC_E_UNEXPECTED)
+
+ /* SCODE's defined in DVOBJ.H */
+
+ CASE_SCODE(DATA_S_SAMEFORMATETC)
+ CASE_SCODE(VIEW_E_DRAW)
+ CASE_SCODE(VIEW_S_ALREADY_FROZEN)
+ CASE_SCODE(CACHE_E_NOCACHE_UPDATED)
+ CASE_SCODE(CACHE_S_FORMATETC_NOTSUPPORTED)
+ CASE_SCODE(CACHE_S_SAMECACHE)
+ CASE_SCODE(CACHE_S_SOMECACHES_NOTUPDATED)
+
+ /* SCODE's defined in STORAGE.H */
+
+ CASE_SCODE(STG_E_INVALIDFUNCTION)
+ CASE_SCODE(STG_E_FILENOTFOUND)
+ CASE_SCODE(STG_E_PATHNOTFOUND)
+ CASE_SCODE(STG_E_TOOMANYOPENFILES)
+ CASE_SCODE(STG_E_ACCESSDENIED)
+ CASE_SCODE(STG_E_INVALIDHANDLE)
+ CASE_SCODE(STG_E_INSUFFICIENTMEMORY)
+ CASE_SCODE(STG_E_INVALIDPOINTER)
+ CASE_SCODE(STG_E_NOMOREFILES)
+ CASE_SCODE(STG_E_DISKISWRITEPROTECTED)
+ CASE_SCODE(STG_E_SEEKERROR)
+ CASE_SCODE(STG_E_WRITEFAULT)
+ CASE_SCODE(STG_E_READFAULT)
+ CASE_SCODE(STG_E_SHAREVIOLATION)
+ CASE_SCODE(STG_E_LOCKVIOLATION)
+ CASE_SCODE(STG_E_FILEALREADYEXISTS)
+ CASE_SCODE(STG_E_INVALIDPARAMETER)
+ CASE_SCODE(STG_E_MEDIUMFULL)
+ CASE_SCODE(STG_E_ABNORMALAPIEXIT)
+ CASE_SCODE(STG_E_INVALIDHEADER)
+ CASE_SCODE(STG_E_INVALIDNAME)
+ CASE_SCODE(STG_E_UNKNOWN)
+ CASE_SCODE(STG_E_UNIMPLEMENTEDFUNCTION)
+ CASE_SCODE(STG_E_INVALIDFLAG)
+ CASE_SCODE(STG_E_INUSE)
+ CASE_SCODE(STG_E_NOTCURRENT)
+ CASE_SCODE(STG_E_REVERTED)
+ CASE_SCODE(STG_E_CANTSAVE)
+ CASE_SCODE(STG_E_OLDFORMAT)
+ CASE_SCODE(STG_E_OLDDLL)
+ CASE_SCODE(STG_E_SHAREREQUIRED)
+ CASE_SCODE(STG_E_NOTFILEBASEDSTORAGE)
+ CASE_SCODE(STG_E_EXTANTMARSHALLINGS)
+ CASE_SCODE(STG_S_CONVERTED)
+
+ /* SCODE's defined in STORAGE.H */
+
+ CASE_SCODE(MK_E_CONNECTMANUALLY)
+ CASE_SCODE(MK_E_EXCEEDEDDEADLINE)
+ CASE_SCODE(MK_E_NEEDGENERIC)
+ CASE_SCODE(MK_E_UNAVAILABLE)
+ CASE_SCODE(MK_E_SYNTAX)
+ CASE_SCODE(MK_E_NOOBJECT)
+ CASE_SCODE(MK_E_INVALIDEXTENSION)
+ CASE_SCODE(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED)
+ CASE_SCODE(MK_E_NOTBINDABLE)
+ CASE_SCODE(MK_E_NOTBOUND)
+ CASE_SCODE(MK_E_CANTOPENFILE)
+ CASE_SCODE(MK_E_MUSTBOTHERUSER)
+ CASE_SCODE(MK_E_NOINVERSE)
+ CASE_SCODE(MK_E_NOSTORAGE)
+ CASE_SCODE(MK_E_NOPREFIX)
+ CASE_SCODE(MK_S_REDUCED_TO_SELF)
+ CASE_SCODE(MK_S_ME)
+ CASE_SCODE(MK_S_HIM)
+ CASE_SCODE(MK_S_US)
+ CASE_SCODE(MK_S_MONIKERALREADYREGISTERED)
+
+ default:
+ lstrcpy(szErrName, TEXT("UNKNOWN SCODE"));
+ }
+
+ wsprintf(szBuf, TEXT("%s %s (0x%lx)\n"), lpszMsg, (LPTSTR)szErrName, sc);
+ OleDbgPrintAlways(lpszPrefix, szBuf, 0);
+#endif // _DEBUG
+}
+
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine)
+{
+#ifdef _DEBUG
+ char szOutput[1024];
+ char szTitle[256];
+ char szModuleName[128];
+ char *pszModuleName;
+ int id;
+
+ DWORD tid = GetCurrentThreadId();
+ DWORD pid = GetCurrentProcessId();
+
+ wsprintfA(szOutput, "%s %s File: %s Line: %d PID: %d TID: %d\n",
+ lpstrExpr, lpstrMsg ? lpstrMsg : "", lpstrFileName, pid, tid);
+ OutputDebugString(szOutput);
+
+ if (GetModuleFileNameA(NULL, szModuleName, 128))
+ {
+ pszModuleName = strrchr(szModuleName, '\\');
+ if (!pszModuleName)
+ {
+ pszModuleName = szModuleName;
+ }
+ else
+ {
+ pszModuleName++;
+ }
+ }
+ else
+ {
+ pszModuleName = "Unknown";
+ }
+
+ wsprintfA(szTitle, "Process: %s File: %s, line %u",
+ pszModuleName, lpstrFileName, iLine);
+
+ wsprintfA(szOutput, "%s %s PID.TID %d.%d",
+ lpstrExpr, lpstrMsg ? lpstrMsg : "", pid, tid);
+
+ id = MessageBoxA(NULL,
+ szOutput,
+ szTitle,
+ MB_SETFOREGROUND | MB_DEFAULT_DESKTOP_ONLY |
+ MB_TASKMODAL | MB_ICONEXCLAMATION | MB_OKCANCEL);
+
+
+ if (id == IDCANCEL)
+ {
+ DebugBreak();
+ }
+
+#endif // _DEBUG
+ return NOERROR;
+}
diff --git a/private/oleutest/letest/ole2ui/debug.h b/private/oleutest/letest/ole2ui/debug.h
new file mode 100644
index 000000000..fa5bfc7ef
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/debug.h
@@ -0,0 +1,69 @@
+/*
+ * DEBUG.H
+ *
+ * Definitions, structures, types, and function prototypes for debugging
+ * purposes.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved,
+ * as applied to redistribution of this source code in source form
+ * License is granted to use of compiled code in shipped binaries.
+ */
+
+#ifndef _DEBUG_H_
+#define _DEBUG_H_
+
+#ifdef DEBUG
+
+//Basic debug macros
+#define D(x) {x;}
+#define ODS(x) D(OutputDebugString(x);OutputDebugString("\r\n"))
+
+#define ODSsz(f, s) {\
+ char szDebug[128];\
+ wsprintf(szDebug, f, (LPSTR)s);\
+ ODS(szDebug);\
+ }
+
+
+#define ODSu(f, u) {\
+ char szDebug[128];\
+ wsprintf(szDebug, f, (UINT)u);\
+ ODS(szDebug);\
+ }
+
+
+#define ODSlu(f, lu) {\
+ char szDebug[128];\
+ wsprintf(szDebug, f, (DWORD)lu);\
+ ODS(szDebug);\
+ }
+
+#define ODSszu(f, s, u) {\
+ char szDebug[128];\
+ wsprintf(szDebug, f, (LPSTR)s, (UINT)u);\
+ ODS(szDebug);\
+ }
+
+
+#define ODSszlu(f, s, lu) {\
+ char szDebug[128];\
+ wsprintf(szDebug, f, (LPSTR)s, (DWORD)lu);\
+ ODS(szDebug);\
+ }
+
+
+#else //NO DEBUG
+
+#define D(x)
+#define ODS(x)
+
+#define ODSsz(f, s)
+#define ODSu(f, u)
+#define ODSlu(f, lu)
+#define ODSszu(f, s, u)
+#define ODSszlu(f, s, lu)
+
+
+#endif //DEBUG
+
+#endif //_DEBUG_H_
diff --git a/private/oleutest/letest/ole2ui/default.ico b/private/oleutest/letest/ole2ui/default.ico
new file mode 100644
index 000000000..4542c57d3
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/default.ico
Binary files differ
diff --git a/private/oleutest/letest/ole2ui/defuimak.ini b/private/oleutest/letest/ole2ui/defuimak.ini
new file mode 100644
index 000000000..39517d711
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/defuimak.ini
@@ -0,0 +1,20 @@
+# This is the DEBUG UILibrary INI file
+MSG=DEBUG Version ($(LANG))
+DEBUG=1
+LIBNAME=outlui
+REL_DIR=c:\ole2samp\release
+OLEREL_DIR=c:\ole2samp\release
+OBJ=DEBUG
+RESOURCE=RESOURCE
+CFLAGS=-c -Od -Gw2cs -W3 -Zpei -AMw -D_DEBUG -D_WINDLL -Gi
+AFLAGS=-mx -Zi -DDEBUG
+RFLAGS=-D DEBUG
+LFLAGS=/MAP /CO /L /NOD /NOE /SE:300
+UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=USA
+DLLOBJS = $(UI_DLLOBJS:D^\=DEBUG^\)
+LIBOBJS = $(UI_COBJS:D^\=DEBUG^\) $(UI_NOPCOBJS:D^\=DEBUG\NOPC^\)
diff --git a/private/oleutest/letest/ole2ui/depend b/private/oleutest/letest/ole2ui/depend
new file mode 100644
index 000000000..4007c4980
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/depend
@@ -0,0 +1,87 @@
+$(O)busy.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h busy.h
+
+$(O)common.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h
+
+$(O)convert.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h geticon.h regdb.h \
+ convert.h
+
+$(O)dbgutil.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h
+
+$(O)regdb.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h
+
+$(O)drawicon.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h geticon.h
+
+$(O)hatch.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h
+
+$(O)icon.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h icon.h geticon.h
+
+$(O)iconbox.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h iconbox.h
+
+$(O)insobj.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h utility.h icon.h insobj.h \
+ resimage.h iconbox.h geticon.h
+
+$(O)links.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h common.h edlinks.h utility.h
+
+$(O)msgfiltr.obj : $(PRECOMP) \
+ ole2ui.h olestd.h uiclass.h msgfiltr.h
+
+$(O)enumfetc.obj : $(PRECOMP) \
+ ole2ui.h olestd.h
+
+$(O)enumstat.obj : $(PRECOMP) \
+ ole2ui.h olestd.h
+
+$(O)objfdbk.obj : $(PRECOMP) \
+ ole2ui.h olestd.h
+
+$(O)ole2ui.obj : $(PRECOMP) \
+ ole2ui.h olestd.h common.h utility.h resimage.h iconbox.h
+
+$(O)olestd.obj : $(PRECOMP) \
+ ole2ui.h olestd.h regdb.h geticon.h common.h
+
+$(O)targtdev.obj : $(PRECOMP) \
+ ole2ui.h olestd.h
+
+$(O)oleutl.obj : $(PRECOMP) \
+ ole2ui.h olestd.h
+
+$(O)pastespl.obj : $(PRECOMP) \
+ ole2ui.h olestd.h pastespl.h common.h utility.h resimage.h iconbox.h \
+ geticon.h regdb.h
+
+$(O)resimage.obj : $(PRECOMP) \
+ ole2ui.h olestd.h resimage.h
+
+$(O)utility.obj : $(PRECOMP) \
+ ole2ui.h olestd.h common.h utility.h geticon.h
+
+$(O)dllfuncs.obj : $(PRECOMP) \
+ ole2ui.h olestd.h common.h uiclass.h
+
+$(O)NOPC\geticon.obj : \
+ ole2ui.h olestd.h uiclass.h geticon.h
+
+$(O)NOPC\dballoc.obj : \
+ dballoc.h
+
+$(O)NOPC\suminfo.obj : \
+ suminfo.h wn_dos.h
+
+$(O)NOPC\stdpal.obj : \
+ stdpal.h
+
+$(O)precomp.pch : \
+ ole2ui.h olestd.h uiclass.h
+
diff --git a/private/oleutest/letest/ole2ui/depend.mk b/private/oleutest/letest/ole2ui/depend.mk
new file mode 100644
index 000000000..2b6c05155
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/depend.mk
@@ -0,0 +1,569 @@
+#
+# Built automatically
+#
+
+#
+# Source files
+#
+
+$(OBJDIR)\busy.obj $(OBJDIR)\busy.lst: .\busy.c $(CAIROLE)\h\export\coguid.h \
+ $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \
+ $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \
+ $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \
+ $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\busy.h .\common.h .\ole2ui.h \
+ .\olestd.h .\utility.h
+
+$(OBJDIR)\common.obj $(OBJDIR)\common.lst: .\common.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\malloc.h $(CRTINC)\ctype.h \
+ $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\common.h .\ole2ui.h .\olestd.h .\utility.h
+
+$(OBJDIR)\convert.obj $(OBJDIR)\convert.lst: .\convert.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\stdlib.h $(CRTINC)\ctype.h \
+ $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\convert.h .\geticon.h .\regdb.h .\common.h \
+ .\ole2ui.h .\olestd.h .\utility.h
+
+$(OBJDIR)\dballoc.obj $(OBJDIR)\dballoc.lst: .\dballoc.cpp \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\coguid.h \
+ $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \
+ $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \
+ $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \
+ $(CRTINC)\limits.h $(CRTINC)\stdio.h $(CRTINC)\ctype.h \
+ $(CRTINC)\excpt.h $(CRTINC)\malloc.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\dballoc.h
+
+$(OBJDIR)\dbgutil.obj $(OBJDIR)\dbgutil.lst: .\dbgutil.c \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\coguid.h \
+ $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \
+ $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \
+ $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \
+ $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\shellapi.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\dllfuncs.obj $(OBJDIR)\dllfuncs.lst: .\dllfuncs.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\uiclass.h \
+ .\common.h .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\drawicon.obj $(OBJDIR)\drawicon.lst: .\drawicon.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \
+ .\geticon.h .\ole2ui.h .\olestd.h .\utility.h
+
+$(OBJDIR)\enumfetc.obj $(OBJDIR)\enumfetc.lst: .\enumfetc.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\enumfetc.h \
+ .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\enumstat.obj $(OBJDIR)\enumstat.lst: .\enumstat.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\geticon.obj $(OBJDIR)\geticon.lst: .\geticon.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\memory.h $(CRTINC)\ctype.h \
+ $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h .\ole2ui.h \
+ .\olestd.h .\utility.h
+
+$(OBJDIR)\hatch.obj $(OBJDIR)\hatch.lst: .\hatch.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\icon.obj $(OBJDIR)\icon.lst: .\icon.c $(CAIROLE)\h\export\coguid.h \
+ $(CAIROLE)\h\export\compobj.h $(CAIROLE)\h\export\dvobj.h \
+ $(CAIROLE)\h\export\initguid.h $(CAIROLE)\h\export\moniker.h \
+ $(CAIROLE)\h\export\ole2.h $(CAIROLE)\h\export\oleguid.h \
+ $(CAIROLE)\h\export\scode.h $(CAIROLE)\h\export\storage.h \
+ $(CRTINC)\ctype.h $(CRTINC)\dos.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\icon.h .\common.h .\geticon.h \
+ .\ole2ui.h .\olestd.h .\utility.h
+
+$(OBJDIR)\iconbox.obj $(OBJDIR)\iconbox.lst: .\iconbox.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\iconbox.h \
+ .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\insobj.obj $(OBJDIR)\insobj.lst: .\insobj.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\direct.h $(CRTINC)\ctype.h \
+ $(CRTINC)\dos.h $(CRTINC)\excpt.h $(CRTINC)\malloc.h \
+ $(CRTINC)\memory.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\insobj.h .\resimage.h .\common.h .\geticon.h \
+ .\icon.h .\iconbox.h .\ole2ui.h .\olestd.h .\utility.h
+
+$(OBJDIR)\links.obj $(OBJDIR)\links.lst: .\links.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\edlinks.h .\common.h .\ole2ui.h .\olestd.h \
+ .\utility.h
+
+$(OBJDIR)\msgfiltr.obj $(OBJDIR)\msgfiltr.lst: .\msgfiltr.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\msgfiltr.h \
+ .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\objfdbk.obj $(OBJDIR)\objfdbk.lst: .\objfdbk.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\ole2ui.obj $(OBJDIR)\ole2ui.lst: .\ole2ui.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \
+ .\iconbox.h .\ole2ui.h .\olestd.h .\resimage.h .\utility.h
+
+$(OBJDIR)\olestd.obj $(OBJDIR)\olestd.lst: .\olestd.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\common.h .\geticon.h .\ole2ui.h .\olestd.h \
+ .\regdb.h
+
+$(OBJDIR)\oleutl.obj $(OBJDIR)\oleutl.lst: .\oleutl.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\pastespl.obj $(OBJDIR)\pastespl.lst: .\pastespl.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\stdlib.h \
+ $(CRTINC)\string.h $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h \
+ $(OSINC)\ddeml.h $(OSINC)\dlgs.h $(OSINC)\drivinit.h \
+ $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h $(OSINC)\nb30.h \
+ $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h \
+ $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h \
+ $(OSINC)\winbase.h $(OSINC)\wincon.h $(OSINC)\windef.h \
+ $(OSINC)\windows.h $(OSINC)\winerror.h $(OSINC)\wingdi.h \
+ $(OSINC)\winnetwk.h $(OSINC)\winnls.h $(OSINC)\winnt.h \
+ $(OSINC)\winperf.h $(OSINC)\winreg.h $(OSINC)\winsock.h \
+ $(OSINC)\winspool.h $(OSINC)\winsvc.h $(OSINC)\winuser.h \
+ $(OSINC)\winver.h .\pastespl.h .\common.h .\geticon.h .\icon.h \
+ .\iconbox.h .\ole2ui.h .\olestd.h .\regdb.h .\resimage.h \
+ .\utility.h
+
+$(OBJDIR)\precomp.obj $(OBJDIR)\precomp.lst: .\precomp.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\regdb.obj $(OBJDIR)\regdb.lst: .\regdb.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \
+ .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\resimage.obj $(OBJDIR)\resimage.lst: .\resimage.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h .\resimage.h
+
+$(OBJDIR)\stdpal.obj $(OBJDIR)\stdpal.lst: .\stdpal.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\excpt.h \
+ $(CRTINC)\stdarg.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\stdpal.h
+
+$(OBJDIR)\suminfo.obj $(OBJDIR)\suminfo.lst: .\suminfo.cpp \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h \
+ .\..\release\variant.h .\suminfo.h .\wn_dos.h .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\targtdev.obj $(OBJDIR)\targtdev.lst: .\targtdev.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\ole2ui.h \
+ .\olestd.h
+
+$(OBJDIR)\template.obj $(OBJDIR)\template.lst: .\template.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\stdarg.h $(CRTINC)\string.h \
+ $(OSINC)\cderr.h $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h \
+ $(OSINC)\dlgs.h $(OSINC)\drivinit.h $(OSINC)\lzexpand.h \
+ $(OSINC)\mmsystem.h $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h \
+ $(OSINC)\rpcdce.h $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h \
+ $(OSINC)\rpcnterr.h $(OSINC)\shellapi.h $(OSINC)\winbase.h \
+ $(OSINC)\wincon.h $(OSINC)\windef.h $(OSINC)\windows.h \
+ $(OSINC)\winerror.h $(OSINC)\wingdi.h $(OSINC)\winnetwk.h \
+ $(OSINC)\winnls.h $(OSINC)\winnt.h $(OSINC)\winperf.h \
+ $(OSINC)\winreg.h $(OSINC)\winsock.h $(OSINC)\winspool.h \
+ $(OSINC)\winsvc.h $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h \
+ .\ole2ui.h .\olestd.h
+
+$(OBJDIR)\utility.obj $(OBJDIR)\utility.lst: .\utility.c \
+ $(CAIROLE)\h\export\coguid.h $(CAIROLE)\h\export\compobj.h \
+ $(CAIROLE)\h\export\dvobj.h $(CAIROLE)\h\export\initguid.h \
+ $(CAIROLE)\h\export\moniker.h $(CAIROLE)\h\export\ole2.h \
+ $(CAIROLE)\h\export\oleguid.h $(CAIROLE)\h\export\scode.h \
+ $(CAIROLE)\h\export\storage.h $(CRTINC)\ctype.h $(CRTINC)\dos.h \
+ $(CRTINC)\excpt.h $(CRTINC)\memory.h $(CRTINC)\stdarg.h \
+ $(CRTINC)\stdlib.h $(CRTINC)\string.h $(OSINC)\cderr.h \
+ $(OSINC)\commdlg.h $(OSINC)\dde.h $(OSINC)\ddeml.h $(OSINC)\dlgs.h \
+ $(OSINC)\drivinit.h $(OSINC)\lzexpand.h $(OSINC)\mmsystem.h \
+ $(OSINC)\nb30.h $(OSINC)\ole.h $(OSINC)\rpc.h $(OSINC)\rpcdce.h \
+ $(OSINC)\rpcdcep.h $(OSINC)\rpcnsi.h $(OSINC)\rpcnterr.h \
+ $(OSINC)\shellapi.h $(OSINC)\winbase.h $(OSINC)\wincon.h \
+ $(OSINC)\windef.h $(OSINC)\windows.h $(OSINC)\winerror.h \
+ $(OSINC)\wingdi.h $(OSINC)\winnetwk.h $(OSINC)\winnls.h \
+ $(OSINC)\winnt.h $(OSINC)\winperf.h $(OSINC)\winreg.h \
+ $(OSINC)\winsock.h $(OSINC)\winspool.h $(OSINC)\winsvc.h \
+ $(OSINC)\winuser.h $(OSINC)\winver.h .\common.h .\geticon.h \
+ .\ole2ui.h .\olestd.h .\utility.h
+
diff --git a/private/oleutest/letest/ole2ui/dirs b/private/oleutest/letest/ole2ui/dirs
new file mode 100644
index 000000000..90a66698e
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dirs
@@ -0,0 +1,3 @@
+DIRS=
+OPTIONAL_DIRS= daytona \
+
diff --git a/private/oleutest/letest/ole2ui/dllentry.c b/private/oleutest/letest/ole2ui/dllentry.c
new file mode 100644
index 000000000..1cd1159e4
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dllentry.c
@@ -0,0 +1,55 @@
+//+-------------------------------------------------------------------
+//
+// Microsoft Windows
+// Copyright (C) Microsoft Corporation, 1991 - 1992.
+//
+// File: dllentry.c
+//
+// Contents: Dll Entry point code. Calls the appropriate run-time
+// init/term code and then defers to LibMain for further
+// processing.
+//
+// Classes: <none>
+//
+// Functions: DllEntryPoint - Called by loader
+//
+// History: 10-May-92 BryanT Created
+// 22-Jul-92 BryanT Switch to calling _cexit/_mtdeletelocks
+// on cleanup.
+// 06-Oct-92 BryanT Call RegisterWithCommnot on entry
+// and DeRegisterWithCommnot on exit.
+// This should fix the heap dump code.
+// 27-Dec-93 AlexT Post 543 builds don't need special code.
+//
+//--------------------------------------------------------------------
+
+#define USE_CRTDLL
+#include <windows.h>
+
+BOOL WINAPI _CRT_INIT (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+BOOL _CRTAPI1 LibMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved);
+
+BOOL DllEntryPoint (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
+{
+ BOOL fRc = FALSE;
+
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ _CRT_INIT(hDll, dwReason, lpReserved);
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ fRc = LibMain (hDll, dwReason, lpReserved);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ fRc = LibMain (hDll, dwReason, lpReserved);
+ _CRT_INIT(hDll, dwReason, lpReserved);
+ }
+
+ return(fRc);
+}
diff --git a/private/oleutest/letest/ole2ui/dllfuncs.c b/private/oleutest/letest/ole2ui/dllfuncs.c
new file mode 100644
index 000000000..283ca9d67
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/dllfuncs.c
@@ -0,0 +1,110 @@
+/*
+ * DLLFUNCS.C
+ *
+ * Contains entry and exit points for the DLL implementation
+ * of the OLE 2.0 User Interface Support Library.
+ *
+ * This file is not needed if we are linking the static library
+ * version of this library.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "uiclass.h"
+#include "common.h"
+
+OLEDBGDATA_MAIN("ole2u32a")
+
+
+/*
+ * LibMain
+ *
+ * Purpose:
+ * DLL-specific entry point called from LibEntry. Initializes
+ * the DLL's heap and registers the GizmoBar GizmoBar.
+ *
+ * Parameters:
+ * hInst HINSTANCE instance of the DLL.
+ * wDataSeg WORD segment selector of the DLL's data segment.
+ * wHeapSize WORD byte count of the heap.
+ * lpCmdLine LPSTR to command line used to start the module.
+ *
+ * Return Value:
+ * HANDLE Instance handle of the DLL.
+ *
+ */
+
+#ifdef WIN32
+
+BOOL _cdecl LibMain(
+ HINSTANCE hDll,
+ DWORD dwReason,
+ LPVOID lpvReserved)
+{
+ if (dwReason == DLL_PROCESS_ATTACH)
+ {
+ // Initialize OLE UI libraries. If you're linking with the static
+ // LIB version of this library, you need to make the below call in
+ // your application (because this LibMain won't be executed).
+ OleUIInitialize(hDll, (HINSTANCE)0, SZCLASSICONBOX, SZCLASSRESULTIMAGE);
+ }
+ else if (dwReason == DLL_PROCESS_DETACH)
+ {
+ OleUIUnInitialize();
+ }
+
+ return TRUE;
+}
+
+#else
+
+int FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
+ , WORD cbHeapSize, LPTSTR lpCmdLine)
+ {
+ OleDbgOut2(TEXT("LibMain: OLE2UI.DLL loaded\r\n"));
+
+ // Initialize OLE UI libraries. If you're linking with the static LIB version
+ // of this library, you need to make the below call in your application (because
+ // this LibMain won't be executed).
+
+ // The symbols SZCLASSICONBOX and SZCLASSRESULTIMAGE are both defined
+ // in uiclass.h
+
+ OleUIInitialize(hInst, (HINSTANCE)0, TEXT(SZCLASSICONBOX), TEXT(SZCLASSRESULTIMAGE));
+
+ //All done...
+ if (0!=cbHeapSize)
+ UnlockData(0);
+
+ return (int)hInst;
+ }
+
+#endif
+
+/*
+ * WEP
+ *
+ * Purpose:
+ * Required DLL Exit function.
+ *
+ * Parameters:
+ * bSystemExit BOOL indicating if the system is being shut
+ * down or the DLL has just been unloaded.
+ *
+ * Return Value:
+ * void
+ *
+ */
+int CALLBACK EXPORT WEP(int bSystemExit)
+{
+ OleUIUnInitialize();
+ return 0;
+}
+
+
+
+
+
+
diff --git a/private/oleutest/letest/ole2ui/drawicon.c b/private/oleutest/letest/ole2ui/drawicon.c
new file mode 100644
index 000000000..06cdd3ab7
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/drawicon.c
@@ -0,0 +1,729 @@
+/*
+ * DRAWICON.C
+ *
+ * Functions to handle creation of metafiles with icons and labels
+ * as well as functions to draw such metafiles with or without the label.
+ *
+ * The metafile is created with a comment that marks the records containing
+ * the label code. Drawing the metafile enumerates the records, draws
+ * all records up to that point, then decides to either skip the label
+ * or draw it.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+#include "utility.h"
+#include "geticon.h"
+
+/*
+ * Strings for metafile comments. KEEP THESE IN SYNC WITH THE
+ * STRINGS IN GETICON.C.
+ */
+
+static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label.
+
+
+
+
+/*
+ * OleUIMetafilePictIconFree
+ *
+ * Purpose:
+ * Deletes the metafile contained in a METAFILEPICT structure and
+ * frees the memory for the structure itself.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL metafilepict structure created in
+ * OleUIMetafilePictFromIconAndLabel
+ *
+ * Return Value:
+ * None
+ */
+
+STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL hMetaPict)
+ {
+ LPMETAFILEPICT pMF;
+
+ if (NULL==hMetaPict)
+ return;
+
+ pMF=(LPMETAFILEPICT)GlobalLock(hMetaPict);
+
+ if (NULL!=pMF)
+ {
+ if (NULL!=pMF->hMF)
+ DeleteMetaFile(pMF->hMF);
+ }
+
+ GlobalUnlock(hMetaPict);
+ GlobalFree(hMetaPict);
+ return;
+ }
+
+
+
+
+
+
+
+
+/*
+ * OleUIMetafilePictIconDraw
+ *
+ * Purpose:
+ * Draws the metafile from OleUIMetafilePictFromIconAndLabel, either with
+ * the label or without.
+ *
+ * Parameters:
+ * hDC HDC on which to draw.
+ * pRect LPRECT in which to draw the metafile.
+ * hMetaPict HGLOBAL to the METAFILEPICT from
+ * OleUIMetafilePictFromIconAndLabel
+ * fIconOnly BOOL specifying to draw the label or not.
+ *
+ * Return Value:
+ * BOOL TRUE if the function is successful, FALSE if the
+ * given metafilepict is invalid.
+ */
+
+STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC hDC, LPRECT pRect, HGLOBAL hMetaPict
+ , BOOL fIconOnly)
+ {
+ LPMETAFILEPICT pMF;
+ DRAWINFO di;
+ int cx, cy;
+ SIZE size;
+ POINT point;
+
+ if (NULL==hMetaPict)
+ return FALSE;
+
+ pMF=GlobalLock(hMetaPict);
+
+ if (NULL==pMF)
+ return FALSE;
+
+ di.Rect = *pRect;
+ di.fIconOnly = fIconOnly;
+
+ //Transform to back to pixels
+ cx=XformWidthInHimetricToPixels(hDC, pMF->xExt);
+ cy=XformHeightInHimetricToPixels(hDC, pMF->yExt);
+
+ SaveDC(hDC);
+
+ SetMapMode(hDC, pMF->mm);
+ SetViewportOrgEx(hDC, (pRect->right - cx) / 2, 0, &point);
+
+ SetViewportExtEx(hDC, min ((pRect->right - cx) / 2 + cx, cx), cy, &size);
+
+ if (fIconOnly)
+ {
+ // Since we've used the __export keyword on the
+ // EnumMetafileIconDraw proc, we do not need to use
+ // MakeProcInstance
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileIconDraw
+ , (LPARAM)(LPDRAWINFO)&di);
+ }
+ else
+ PlayMetaFile(hDC, pMF->hMF);
+
+ RestoreDC(hDC, -1);
+
+ GlobalUnlock(hMetaPict);
+ return TRUE;
+ }
+
+
+
+
+/*
+ * EnumMetafileIconDraw
+ *
+ * Purpose:
+ * EnumMetaFile callback function that draws either the icon only or
+ * the icon and label depending on given flags.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * lParam LPARAM flags passed in EnumMetaFile.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EXPORT EnumMetafileIconDraw(HDC hDC, HANDLETABLE FAR *phTable
+ , METARECORD FAR *pMFR, int cObj, LPARAM lParam)
+ {
+ LPDRAWINFO lpdi = (LPDRAWINFO)lParam;
+
+ /*
+ * We play everything blindly except for DIBBITBLT (or DIBSTRETCHBLT)
+ * and ESCAPE with MFCOMMENT. For the BitBlts we change the x,y to
+ * draw at (0,0) instead of wherever it was written to draw. The
+ * comment tells us there to stop if we don't want to draw the label.
+ */
+
+ //If we're playing icon only, stop enumeration at the comment.
+ if (lpdi->fIconOnly)
+ {
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2]))
+ return 0;
+ }
+
+ /*
+ * Check for the records in which we want to munge the coordinates.
+ * destX is offset 6 for BitBlt, offset 9 for StretchBlt, either of
+ * which may appear in the metafile.
+ */
+ if (META_DIBBITBLT==pMFR->rdFunction)
+ pMFR->rdParm[6]=0;
+
+ if (META_DIBSTRETCHBLT==pMFR->rdFunction)
+ pMFR->rdParm[9] = 0;
+
+ }
+
+
+ PlayMetaFileRecord(hDC, phTable, pMFR, cObj);
+ return 1;
+ }
+
+
+
+
+
+/*
+ * OleUIMetafilePictExtractLabel
+ *
+ * Purpose:
+ * Retrieves the label string from metafile representation of an icon.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ * lpszLabel LPSTR in which to store the label.
+ * cchLabel UINT length of lpszLabel.
+ * lpWrapIndex DWORD index of first character in last line. Can be NULL
+ * if calling function doesn't care about word wrap.
+ *
+ * Return Value:
+ * UINT Number of characters copied.
+ */
+STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL hMetaPict, LPTSTR lpszLabel
+ , UINT cchLabel, LPDWORD lpWrapIndex)
+ {
+ LPMETAFILEPICT pMF;
+ LABELEXTRACT le;
+ HDC hDC;
+
+ /*
+ * We extract the label by getting a screen DC and walking the metafile
+ * records until we see the ExtTextOut record we put there. That
+ * record will have the string embedded in it which we then copy out.
+ */
+
+ if (NULL==hMetaPict || NULL==lpszLabel || 0==cchLabel)
+ return FALSE;
+
+ pMF=GlobalLock(hMetaPict);
+
+ if (NULL==pMF)
+ return FALSE;
+
+ le.lpsz=lpszLabel;
+ le.u.cch=cchLabel;
+ le.Index=0;
+ le.fFoundIconOnly=FALSE;
+ le.fFoundSource=FALSE; //Unused for this function.
+ le.fFoundIndex=FALSE; //Unused for this function.
+ le.PrevIndex = 0;
+
+ //Use a screen DC so we have something valid to pass in.
+ hDC=GetDC(NULL);
+
+ // Since we've used the EXPORT keyword on the
+ // EnumMetafileExtractLabel proc, we do not need to use
+ // MakeProcInstance
+
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractLabel, (LONG)(LPLABELEXTRACT)&le);
+
+ ReleaseDC(NULL, hDC);
+
+ GlobalUnlock(hMetaPict);
+
+ //Tell where we wrapped (if calling function cares)
+ if (NULL != lpWrapIndex)
+ *lpWrapIndex = le.PrevIndex;
+
+ //Return amount of text copied
+ return le.u.cch;
+ }
+
+
+
+
+
+/*
+ * EnumMetafileExtractLabel
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile looking for
+ * ExtTextOut, then concatenates the text from each one into a buffer
+ * in lParam.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pLE LPLABELEXTRACT providing the destination buffer and length.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EXPORT EnumMetafileExtractLabel(HDC hDC, HANDLETABLE FAR *phTable
+ , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
+ {
+
+ /*
+ * We don't allow anything to happen until we see "IconOnly"
+ * in an MFCOMMENT that is used to enable everything else.
+ */
+ if (!pLE->fFoundIconOnly)
+ {
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2]))
+ pLE->fFoundIconOnly=TRUE;
+ }
+
+ return 1;
+ }
+
+ //Enumerate all records looking for META_EXTTEXTOUT - there can be more
+ //than one.
+ if (META_EXTTEXTOUT==pMFR->rdFunction)
+ {
+ UINT cchMax;
+ LPTSTR lpszTemp;
+
+ /*
+ * If ExtTextOut has NULL fuOptions, then the rectangle is omitted
+ * from the record, and the string starts at rdParm[4]. If
+ * fuOptions is non-NULL, then the string starts at rdParm[8]
+ * (since the rectange takes up four WORDs in the array). In
+ * both cases, the string continues for (rdParm[2]+1) >> 1
+ * words. We just cast a pointer to rdParm[8] to an LPSTR and
+ * lstrcpyn into the buffer we were given.
+ *
+ * Note that we use element 8 in rdParm instead of 4 because we
+ * passed ETO_CLIPPED in for the options on ExtTextOut--docs say
+ * [4] which is rect doesn't exist if we passed zero there.
+ *
+ */
+
+ cchMax=min(pLE->u.cch - pLE->Index, (UINT)pMFR->rdParm[2]);
+ lpszTemp = pLE->lpsz + pLE->Index;
+
+ lstrcpyn(lpszTemp, (LPTSTR)&(pMFR->rdParm[8]), cchMax + 1);
+// lstrcpyn(lpszTemp, (LPTSTR)&(pMFR->rdParm[4]), cchMax + 1);
+
+ pLE->PrevIndex = pLE->Index;
+
+ pLE->Index += cchMax;
+ }
+
+ return 1;
+ }
+
+
+
+
+
+/*
+ * OleUIMetafilePictExtractIcon
+ *
+ * Purpose:
+ * Retrieves the icon from metafile into which DrawIcon was done before.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ *
+ * Return Value:
+ * HICON Icon recreated from the data in the metafile.
+ */
+STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL hMetaPict)
+ {
+ LPMETAFILEPICT pMF;
+ HDC hDC;
+ ICONEXTRACT ie;
+
+ /*
+ * We extract the label by getting a screen DC and walking the metafile
+ * records until we see the ExtTextOut record we put there. That
+ * record will have the string embedded in it which we then copy out.
+ */
+
+ if (NULL==hMetaPict)
+ return NULL;
+
+ pMF=GlobalLock(hMetaPict);
+
+ if (NULL==pMF)
+ return FALSE;
+
+ //Use a screen DC so we have something valid to pass in.
+ hDC=GetDC(NULL);
+ ie.fAND=TRUE;
+
+ // We get information back in the ICONEXTRACT structure.
+ // (Since we've used the EXPORT keyword on the
+ // EnumMetafileExtractLabel proc, we do not need to use
+ // MakeProcInstance)
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIcon, (LONG)(LPICONEXTRACT)&ie);
+
+ ReleaseDC(NULL, hDC);
+ GlobalUnlock(hMetaPict);
+
+ return ie.hIcon;
+ }
+
+
+
+
+
+/*
+ * EnumMetafileExtractIcon
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile looking for
+ * StretchBlt (3.1) and BitBlt (3.0) records. We expect to see two
+ * of them, the first being the AND mask and the second being the XOR
+ * data. We
+ * ExtTextOut, then copies the text into a buffer in lParam.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pIE LPICONEXTRACT providing the destination buffer and length.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EXPORT EnumMetafileExtractIcon(HDC hDC, HANDLETABLE FAR *phTable
+ , METARECORD FAR *pMFR, int cObj, LPICONEXTRACT pIE)
+ {
+ LPBITMAPINFO lpBI;
+ LPBITMAPINFOHEADER lpBH;
+ LPBYTE lpbSrc;
+ LPBYTE lpbDst;
+ UINT uWidth, uHeight;
+ DWORD cb;
+ HGLOBAL hMem;
+ BITMAP bm;
+ HBITMAP hBmp;
+ int cxIcon, cyIcon;
+
+
+ //Continue enumeration if we don't see the records we want.
+ if (META_DIBBITBLT!=pMFR->rdFunction && META_DIBSTRETCHBLT!=pMFR->rdFunction)
+ return 1;
+
+ /*
+ * Windows 3.0 DrawIcon uses META_DIBBITBLT in whereas 3.1 uses
+ * META_DIBSTRETCHBLT so we have to handle each case separately.
+ */
+
+ if (META_DIBBITBLT==pMFR->rdFunction) //Win3.0
+ {
+ //Get dimensions and the BITMAPINFO struct.
+ uHeight=pMFR->rdParm[1];
+ uWidth =pMFR->rdParm[2];
+ lpBI=(LPBITMAPINFO)&(pMFR->rdParm[8]);
+ }
+
+ if (META_DIBSTRETCHBLT==pMFR->rdFunction) //Win3.1
+ {
+ //Get dimensions and the BITMAPINFO struct.
+ uHeight=pMFR->rdParm[2];
+ uWidth =pMFR->rdParm[3];
+ lpBI=(LPBITMAPINFO)&(pMFR->rdParm[10]);
+ }
+
+ lpBH=(LPBITMAPINFOHEADER)&(lpBI->bmiHeader);
+
+ //Pointer to the bits which follows the BITMAPINFO structure.
+ lpbSrc=(LPBYTE)lpBI+sizeof(BITMAPINFOHEADER);
+
+ //Add the length of the color table (if one exists)
+
+ if (0!=lpBH->biClrUsed)
+ {
+ // If we have an explicit count of colors used, we
+ // can find the offset to the data directly
+
+ lpbSrc += (lpBH->biClrUsed*sizeof(RGBQUAD));
+ }
+ else if (lpBH->biCompression == BI_BITFIELDS)
+ {
+ // 16 or 32 bpp, indicated by BI_BITFIELDS in the compression
+ // field, have 3 DWORD masks for adjusting subsequent
+ // direct-color values, and no palette
+
+ lpbSrc += 3 * sizeof(DWORD);
+ }
+ else
+ {
+ // In other cases, there is an array of RGBQUAD entries
+ // equal to 2^(biBitCount) where biBitCount is the number
+ // of bits per pixel. The exception is 24 bpp bitmaps,
+ // which have no color table and just use direct RGB values.
+
+ lpbSrc+=
+ (lpBH->biBitCount == 24) ? 0 :
+ (1 << (lpBH->biBitCount)) * sizeof(RGBQUAD);
+ }
+
+
+ /*
+ * All the bits we have in lpbSrc are device-independent, so we
+ * need to change them over to be device-dependent using SetDIBits.
+ * Once we have a bitmap with the device-dependent bits, we can
+ * GetBitmapBits to have buffers with the real data.
+ *
+ * For each pass we have to allocate memory for the bits. We save
+ * the memory for the mask between passes.
+ */
+
+ //Use CreateBitmap for ANY monochrome bitmaps
+ if (pIE->fAND || 1==lpBH->biBitCount || lpBH->biBitCount > 8)
+ hBmp=CreateBitmap((UINT)lpBH->biWidth, (UINT)lpBH->biHeight, 1, 1, NULL);
+ else if (lpBH->biBitCount <= 8)
+ hBmp=CreateCompatibleBitmap(hDC, (UINT)lpBH->biWidth, (UINT)lpBH->biHeight);
+
+ if (!hBmp || !SetDIBits(hDC, hBmp, 0, (UINT)lpBH->biHeight, (LPVOID)lpbSrc, lpBI, DIB_RGB_COLORS))
+ {
+ if (!pIE->fAND)
+ GlobalFree(pIE->hMemAND);
+
+ DeleteObject(hBmp);
+ return 0;
+ }
+
+ //Allocate memory and get the DDBits into it.
+ GetObject(hBmp, sizeof(bm), &bm);
+
+ cb=bm.bmHeight*bm.bmWidthBytes * bm.bmPlanes;
+
+// if (cb % 4 != 0) // dword align
+// cb += 4 - (cb % 4);
+
+ hMem=GlobalAlloc(GHND, cb);
+
+ if (NULL==hMem)
+ {
+ if (NULL!=pIE->hMemAND)
+ GlobalFree(pIE->hMemAND);
+
+ DeleteObject(hBmp);
+ return 0;
+ }
+
+ lpbDst=(LPBYTE)GlobalLock(hMem);
+ GetBitmapBits(hBmp, cb, (LPVOID)lpbDst);
+
+ DeleteObject(hBmp);
+ GlobalUnlock(hMem);
+
+
+ /*
+ * If this is the first pass (pIE->fAND==TRUE) then save the memory
+ * of the AND bits for the next pass.
+ */
+ if (pIE->fAND)
+ {
+ pIE->fAND=FALSE;
+ pIE->hMemAND=hMem;
+
+ //Continue enumeration looking for the next blt record.
+ return 1;
+ }
+ else
+ {
+ //Get the AND pointer again.
+ lpbSrc=(LPBYTE)GlobalLock(pIE->hMemAND);
+
+ /*
+ * Create the icon now that we have all the data. lpbDst already
+ * points to the XOR bits.
+ */
+ cxIcon = GetSystemMetrics(SM_CXICON);
+ cyIcon = GetSystemMetrics(SM_CYICON);
+
+ pIE->hIcon=CreateIcon(ghInst,
+ uWidth,
+ uHeight,
+ (BYTE)bm.bmPlanes,
+ (BYTE)bm.bmBitsPixel,
+ (LPVOID)lpbSrc,
+ (LPVOID)lpbDst);
+
+ GlobalUnlock(pIE->hMemAND);
+ GlobalFree(pIE->hMemAND);
+ GlobalFree(hMem);
+
+ //We're done so we can stop.
+ return 0;
+ }
+ }
+
+
+
+
+
+/*
+ * OleUIMetafilePictExtractIconSource
+ *
+ * Purpose:
+ * Retrieves the filename and index of the icon source from a metafile
+ * created with OleUIMetafilePictFromIconAndLabel.
+ *
+ * Parameters:
+ * hMetaPict HGLOBAL to the METAFILEPICT containing the metafile.
+ * lpszSource LPTSTR in which to store the source filename. This
+ * buffer should be OLEUI_CCHPATHMAX characters.
+ * piIcon UINT FAR * in which to store the icon's index
+ * within lpszSource
+ *
+ * Return Value:
+ * BOOL TRUE if the records were found, FALSE otherwise.
+ */
+STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL hMetaPict
+ , LPTSTR lpszSource, UINT FAR *piIcon)
+ {
+ LPMETAFILEPICT pMF;
+ LABELEXTRACT le;
+ HDC hDC;
+
+ /*
+ * We will walk the metafile looking for the two comment records
+ * following the IconOnly comment. The flags fFoundIconOnly and
+ * fFoundSource indicate if we have found IconOnly and if we have
+ * found the source comment already.
+ */
+
+ if (NULL==hMetaPict || NULL==lpszSource || NULL==piIcon)
+ return FALSE;
+
+ pMF=GlobalLock(hMetaPict);
+
+ if (NULL==pMF)
+ return FALSE;
+
+ le.lpsz=lpszSource;
+ le.fFoundIconOnly=FALSE;
+ le.fFoundSource=FALSE;
+ le.fFoundIndex=FALSE;
+
+ //Use a screen DC so we have something valid to pass in.
+ hDC=GetDC(NULL);
+
+ EnumMetaFile(hDC, pMF->hMF, (MFENUMPROC)EnumMetafileExtractIconSource, (LONG)(LPLABELEXTRACT)&le);
+
+ ReleaseDC(NULL, hDC);
+ GlobalUnlock(hMetaPict);
+
+ //Copy the icon index to the caller's variable.
+ *piIcon=le.u.iIcon;
+
+ //Check that we found everything.
+ return (le.fFoundIconOnly && le.fFoundSource && le.fFoundIndex);
+ }
+
+
+
+
+
+/*
+ * EnumMetafileExtractIconSource
+ *
+ * Purpose:
+ * EnumMetaFile callback function that walks a metafile skipping the first
+ * comment record, extracting the source filename from the second, and
+ * the index of the icon in the third.
+ *
+ * Parameters:
+ * hDC HDC into which the metafile should be played.
+ * phTable HANDLETABLE FAR * providing handles selected into the DC.
+ * pMFR METARECORD FAR * giving the enumerated record.
+ * pLE LPLABELEXTRACT providing the destination buffer and
+ * area to store the icon index.
+ *
+ * Return Value:
+ * int 0 to stop enumeration, 1 to continue.
+ */
+
+int CALLBACK EXPORT EnumMetafileExtractIconSource(HDC hDC, HANDLETABLE FAR *phTable
+ , METARECORD FAR *pMFR, int cObj, LPLABELEXTRACT pLE)
+ {
+ LPTSTR psz;
+
+ /*
+ * We don't allow anything to happen until we see "IconOnly"
+ * in an MFCOMMENT that is used to enable everything else.
+ */
+ if (!pLE->fFoundIconOnly)
+ {
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ if (0==lstrcmpi(szIconOnly, (LPTSTR)&pMFR->rdParm[2]))
+ pLE->fFoundIconOnly=TRUE;
+ }
+
+ return 1;
+ }
+
+ //Now see if we find the source string.
+ if (!pLE->fFoundSource)
+ {
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ LSTRCPYN(pLE->lpsz, (LPTSTR)&pMFR->rdParm[2], OLEUI_CCHPATHMAX);
+ pLE->lpsz[OLEUI_CCHPATHMAX-1] = TEXT('\0');
+ pLE->fFoundSource=TRUE;
+ }
+
+ return 1;
+ }
+
+ //Next comment will be the icon index.
+ if (META_ESCAPE==pMFR->rdFunction && MFCOMMENT==pMFR->rdParm[0])
+ {
+ /*
+ * This string contains the icon index in string form,
+ * so we need to convert back to a UINT. After we see this
+ * we can stop the enumeration. The comment will have
+ * a null terminator because we made sure to save it.
+ */
+ psz=(LPTSTR)&pMFR->rdParm[2];
+ pLE->u.iIcon=0;
+
+ //Do Ye Olde atoi
+ while (*psz)
+ pLE->u.iIcon=(10*pLE->u.iIcon)+((*psz++)-'0');
+
+ pLE->fFoundIndex=TRUE;
+ return 0;
+ }
+
+ return 1;
+ }
diff --git a/private/oleutest/letest/ole2ui/edlinks.h b/private/oleutest/letest/ole2ui/edlinks.h
new file mode 100644
index 000000000..db721f47f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/edlinks.h
@@ -0,0 +1,135 @@
+/*
+ * EDLINKS.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Edit Links dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _LINKS_H_
+#define _LINKS_H_
+
+//INTERNAL INFORMATION STARTS HERE
+#define OLEUI_SZMAX 255
+#define LINKTYPELEN 9
+#define szNULL TEXT("\0")
+
+typedef UINT (CALLBACK* COMMDLGHOOKPROC)(HWND, UINT, WPARAM, LPARAM);
+
+//Internally used structure
+
+typedef struct tagLINKINFO
+ {
+ DWORD dwLink; // app specific identifier of a link
+ LPTSTR lpszDisplayName; // file based part of name
+ LPTSTR lpszItemName; // object part of name
+ LPTSTR lpszShortFileName; // filename without path
+ LPTSTR lpszShortLinkType; // Short link type - progID
+ LPTSTR lpszFullLinkType; // Full link type - user friendly name
+ LPTSTR lpszAMX; // Is the link auto (A) man (M) or dead (X)
+ ULONG clenFileName; // count of file part of mon.
+ BOOL fSourceAvailable; // bound or not - on boot assume yes??
+ BOOL fIsAuto; // 1 =automatic, 0=manual update
+ BOOL fIsMarked; // 1 = marked, 0 = not
+ BOOL fDontFree; // Don't free this data since it's being reused
+ BOOL fIsSelected; // item selected or to be selected
+ } LINKINFO, FAR* LPLINKINFO;
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+
+typedef struct tagEDITLINKS
+ {
+ //Keep this item first as the Standard* functions depend on it here.
+
+ LPOLEUIEDITLINKS lpOEL; //Original structure passed.
+
+ BOOL fClose; // Does the button read cancel (0) or
+ // close (1)?
+ int *rgIndex; // Array to hold indexes of selected items
+ int cSelItems; // Number of selected items
+ BOOL fItemsExist; // TRUE, items in lbox, FALSE, none
+ UINT nChgSrcHelpID; // ID for Help callback from ChangeSrc dlg
+ TCHAR szClose[50]; // Text for Close button
+ // (when Cancel button gets renamed)
+} EDITLINKS, *PEDITLINKS, FAR *LPEDITLINKS;
+
+// Data to and from the ChangeSource dialog hook
+typedef struct tagOLEUICHANGESOURCEHOOKDATA
+{
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIINSERTOBJECT. All are IN-OUT unless otherwise spec.
+ LPLINKINFO lpLI; // IN: ptr to LinkInfo entry
+ LPEDITLINKS lpEL; // IN: ptr to EditLinks dialog struct
+ BOOL fValidLink; // OUT: was link source validated
+ LPTSTR lpszFrom; // OUT: string containing prefix of
+ // source changed from
+ LPTSTR lpszTo; // OUT: string containing prefix of
+ // source changed to
+} OLEUICHANGESOURCEHOOKDATA, *POLEUICHANGESOURCEHOOKDATA,
+ FAR *LPOLEUICHANGESOURCEHOOKDATA;
+
+
+// Data to and from the ChangeSource dialog hook
+typedef struct tagCHANGESOURCEHOOKDATA
+{
+ LPOLEUICHANGESOURCEHOOKDATA lpOCshData; //Original structure passed.
+ LPOPENFILENAME lpOfn;
+ BOOL fValidLink;
+ int nFileLength;
+ int nEditLength;
+ TCHAR szFileName[OLEUI_CCHPATHMAX];
+ TCHAR szItemName[OLEUI_CCHPATHMAX];
+ BOOL bFileNameStored;
+ BOOL bItemNameStored;
+ TCHAR szEdit[OLEUI_CCHPATHMAX];
+ LPTSTR lpszFrom; // string containing prefix of source
+ // changed from
+ LPTSTR lpszTo; // string containing prefix of source
+ // source changed to
+} CHANGESOURCEHOOKDATA, *PCHANGESOURCEHOOKDATA, FAR *LPCHANGESOURCEHOOKDATA;
+
+
+//Internal function prototypes
+//LINKS.C
+BOOL CALLBACK EXPORT EditLinksDialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL FEditLinksInit(HWND, WPARAM, LPARAM);
+BOOL Container_ChangeSource(HWND, LPEDITLINKS);
+HRESULT Container_AutomaticManual(HWND, BOOL, LPEDITLINKS);
+HRESULT CancelLink(HWND, LPEDITLINKS);
+HRESULT Container_UpdateNow(HWND, LPEDITLINKS);
+HRESULT Container_OpenSource(HWND, LPEDITLINKS);
+int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected);
+VOID BreakString(LPLINKINFO);
+int GetSelectedItems(HWND, int FAR* FAR*);
+BOOL WINAPI ChangeSource(HWND hWndOwner,
+ LPTSTR lpszFile,
+ UINT cchFile,
+ UINT iFilterString,
+ COMMDLGHOOKPROC lpfnBrowseHook,
+ LPOLEUICHANGESOURCEHOOKDATA lpLbhData);
+UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
+VOID InitControls(HWND hDlg, LPEDITLINKS lpEL);
+VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect);
+VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2);
+int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle);
+VOID ChangeAllLinks(HWND hLIstBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo);
+int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
+VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr);
+#endif // __LINKS_H__
diff --git a/private/oleutest/letest/ole2ui/egares.bmp b/private/oleutest/letest/ole2ui/egares.bmp
new file mode 100644
index 000000000..e9dbb065a
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/egares.bmp
Binary files differ
diff --git a/private/oleutest/letest/ole2ui/enumfetc.c b/private/oleutest/letest/ole2ui/enumfetc.c
new file mode 100644
index 000000000..15a6b3a90
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/enumfetc.c
@@ -0,0 +1,308 @@
+/*************************************************************************
+**
+** OLE 2 Utility Code
+**
+** enumfetc.c
+**
+** This file contains a standard implementation of IEnumFormatEtc
+** interface.
+** This file is part of the OLE 2.0 User Interface support library.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "enumfetc.h"
+
+
+typedef struct tagOleStdEnumFmtEtc {
+ IEnumFORMATETCVtbl FAR* lpVtbl;
+ ULONG m_dwRefs; /* referance count */
+ ULONG m_nIndex; /* current index in list */
+ ULONG m_nCount; /* how many items in list */
+ LPFORMATETC m_lpEtc; /* list of formatetc */
+} OLESTDENUMFMTETC, FAR* LPOLESTDENUMFMTETC;
+
+VOID OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC pEtc);
+
+STDMETHODIMP OleStdEnumFmtEtc_QueryInterface(
+ LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj);
+STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis);
+STDMETHODIMP_(ULONG) OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis);
+STDMETHODIMP OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt,
+ LPFORMATETC rgelt, ULONG FAR* pceltFetched);
+STDMETHODIMP OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt);
+STDMETHODIMP OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis);
+STDMETHODIMP OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis,
+ LPENUMFORMATETC FAR* ppenum);
+
+static IEnumFORMATETCVtbl g_EnumFORMATETCVtbl = {
+ OleStdEnumFmtEtc_QueryInterface,
+ OleStdEnumFmtEtc_AddRef,
+ OleStdEnumFmtEtc_Release,
+ OleStdEnumFmtEtc_Next,
+ OleStdEnumFmtEtc_Skip,
+ OleStdEnumFmtEtc_Reset,
+ OleStdEnumFmtEtc_Clone,
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+STDAPI_(LPENUMFORMATETC)
+ OleStdEnumFmtEtc_Create(ULONG nCount, LPFORMATETC lpEtc)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPMALLOC lpMalloc=NULL;
+ LPOLESTDENUMFMTETC lpEF=NULL;
+ DWORD dwSize;
+ WORD i;
+ HRESULT hRes;
+
+ hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
+ if (hRes != NOERROR) {
+ return NULL;
+ }
+
+ lpEF = (LPOLESTDENUMFMTETC)lpMalloc->lpVtbl->Alloc(lpMalloc,
+ sizeof(OLESTDENUMFMTETC));
+ if (lpEF == NULL) {
+ goto errReturn;
+ }
+
+ lpEF->lpVtbl = &g_EnumFORMATETCVtbl;
+ lpEF->m_dwRefs = 1;
+ lpEF->m_nCount = nCount;
+ lpEF->m_nIndex = 0;
+
+ dwSize = sizeof(FORMATETC) * lpEF->m_nCount;
+
+ lpEF->m_lpEtc = (LPFORMATETC)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize);
+ if (lpEF->m_lpEtc == NULL)
+ goto errReturn;
+
+ lpMalloc->lpVtbl->Release(lpMalloc);
+
+ for (i=0; i<nCount; i++) {
+ OleStdCopyFormatEtc(
+ (LPFORMATETC)&(lpEF->m_lpEtc[i]), (LPFORMATETC)&(lpEtc[i]));
+ }
+
+ return (LPENUMFORMATETC)lpEF;
+
+errReturn:
+ if (lpEF != NULL)
+ lpMalloc->lpVtbl->Free(lpMalloc, lpEF);
+
+ if (lpMalloc != NULL)
+ lpMalloc->lpVtbl->Release(lpMalloc);
+
+ return NULL;
+
+} /* OleStdEnumFmtEtc_Create()
+ */
+
+
+VOID
+ OleStdEnumFmtEtc_Destroy(LPOLESTDENUMFMTETC lpEF)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPMALLOC lpMalloc=NULL;
+ WORD i;
+
+ if (lpEF != NULL) {
+
+ if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) {
+
+ /* OLE2NOTE: we MUST free any memory that was allocated for
+ ** TARGETDEVICES contained within the FORMATETC elements.
+ */
+ for (i=0; i<lpEF->m_nCount; i++) {
+ OleStdFree(lpEF->m_lpEtc[i].ptd);
+ }
+
+ if (lpEF->m_lpEtc != NULL) {
+ lpMalloc->lpVtbl->Free(lpMalloc, lpEF->m_lpEtc);
+ }
+
+ lpMalloc->lpVtbl->Free(lpMalloc, lpEF);
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ }
+ }
+} /* OleStdEnumFmtEtc_Destroy()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumFmtEtc_QueryInterface(
+ LPENUMFORMATETC lpThis, REFIID riid, LPVOID FAR* ppobj)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ *ppobj = NULL;
+
+ if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumFORMATETC)){
+ *ppobj = (LPVOID)lpEF;
+ }
+
+ if (*ppobj == NULL) return ResultFromScode(E_NOINTERFACE);
+ else{
+ OleStdEnumFmtEtc_AddRef(lpThis);
+ return NOERROR;
+ }
+
+} /* OleStdEnumFmtEtc_QueryInterface()
+ */
+
+
+STDMETHODIMP_(ULONG)
+ OleStdEnumFmtEtc_AddRef(LPENUMFORMATETC lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ return lpEF->m_dwRefs++;
+
+} /* OleStdEnumFmtEtc_AddRef()
+ */
+
+
+STDMETHODIMP_(ULONG)
+ OleStdEnumFmtEtc_Release(LPENUMFORMATETC lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ DWORD dwRefs = --lpEF->m_dwRefs;
+
+ if (dwRefs == 0)
+ OleStdEnumFmtEtc_Destroy(lpEF);
+
+ return dwRefs;
+
+} /* OleStdEnumFmtEtc_Release()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumFmtEtc_Next(LPENUMFORMATETC lpThis, ULONG celt, LPFORMATETC rgelt,
+ ULONG FAR* pceltFetched)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ ULONG i=0;
+ ULONG nOffset;
+
+ if (rgelt == NULL) {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ while (i < celt) {
+ nOffset = lpEF->m_nIndex + i;
+
+ if (nOffset < lpEF->m_nCount) {
+ OleStdCopyFormatEtc(
+ (LPFORMATETC)&(rgelt[i]), (LPFORMATETC)&(lpEF->m_lpEtc[nOffset]));
+ i++;
+ }else{
+ break;
+ }
+ }
+
+ lpEF->m_nIndex += (WORD)i;
+
+ if (pceltFetched != NULL) {
+ *pceltFetched = i;
+ }
+
+ if (i != celt) {
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+} /* OleStdEnumFmtEtc_Next()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumFmtEtc_Skip(LPENUMFORMATETC lpThis, ULONG celt)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ ULONG i=0;
+ ULONG nOffset;
+
+ while (i < celt) {
+ nOffset = lpEF->m_nIndex + i;
+
+ if (nOffset < lpEF->m_nCount) {
+ i++;
+ }else{
+ break;
+ }
+ }
+
+ lpEF->m_nIndex += (WORD)i;
+
+ if (i != celt) {
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+} /* OleStdEnumFmtEtc_Skip()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumFmtEtc_Reset(LPENUMFORMATETC lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+ lpEF->m_nIndex = 0;
+
+ return NOERROR;
+} /* OleStdEnumFmtEtc_Reset()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumFmtEtc_Clone(LPENUMFORMATETC lpThis, LPENUMFORMATETC FAR* ppenum)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMFMTETC lpEF = (LPOLESTDENUMFMTETC)lpThis;
+
+ if (ppenum == NULL) {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ *ppenum = OleStdEnumFmtEtc_Create(lpEF->m_nCount, lpEF->m_lpEtc);
+
+ // make sure cloned enumerator has same index state as the original
+ if (*ppenum) {
+ LPOLESTDENUMFMTETC lpEFClone = (LPOLESTDENUMFMTETC)*ppenum;
+ lpEFClone->m_nIndex = lpEF->m_nIndex;
+ return NOERROR;
+ } else
+ return ResultFromScode(E_OUTOFMEMORY);
+
+} /* OleStdEnumFmtEtc_Clone()
+ */
+
diff --git a/private/oleutest/letest/ole2ui/enumfetc.h b/private/oleutest/letest/ole2ui/enumfetc.h
new file mode 100644
index 000000000..60b82d151
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/enumfetc.h
@@ -0,0 +1,13 @@
+// This file is now OBSOLETE (include olestd.h instead)
+
+/*************************************************************************
+**
+** OLE 2 Utility Code
+**
+** enumfetc.c
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+// Function prototypes moved to olestd.h
diff --git a/private/oleutest/letest/ole2ui/enumstat.c b/private/oleutest/letest/ole2ui/enumstat.c
new file mode 100644
index 000000000..17a42048f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/enumstat.c
@@ -0,0 +1,336 @@
+/*************************************************************************
+**
+** OLE 2 Utility Code
+**
+** enumstat.c
+**
+** This file contains a standard implementation of IEnumStatData
+** interface.
+** This file is part of the OLE 2.0 User Interface support library.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#define STRICT 1
+#include "ole2ui.h"
+
+
+typedef struct tagOleStdEnumStatData {
+ IEnumSTATDATAVtbl FAR* lpVtbl;
+ ULONG m_dwRefs; /* referance count */
+ ULONG m_nIndex; /* current index in list */
+ ULONG m_nCount; /* how many items in list */
+ LPSTATDATA m_lpStat; /* list of STATDATA */
+} OLESTDENUMSTATDATA, FAR* LPOLESTDENUMSTATDATA;
+
+VOID OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA pStat);
+
+STDMETHODIMP OleStdEnumStatData_QueryInterface(
+ LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj);
+STDMETHODIMP_(ULONG) OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis);
+STDMETHODIMP_(ULONG) OleStdEnumStatData_Release(LPENUMSTATDATA lpThis);
+STDMETHODIMP OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt,
+ LPSTATDATA rgelt, ULONG FAR* pceltFetched);
+STDMETHODIMP OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt);
+STDMETHODIMP OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis);
+STDMETHODIMP OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis,
+ LPENUMSTATDATA FAR* ppenum);
+
+static IEnumSTATDATAVtbl g_EnumSTATDATAVtbl = {
+ OleStdEnumStatData_QueryInterface,
+ OleStdEnumStatData_AddRef,
+ OleStdEnumStatData_Release,
+ OleStdEnumStatData_Next,
+ OleStdEnumStatData_Skip,
+ OleStdEnumStatData_Reset,
+ OleStdEnumStatData_Clone,
+};
+
+/////////////////////////////////////////////////////////////////////////////
+
+STDAPI_(BOOL)
+ OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ if ((pDest == NULL) || (pSrc == NULL)) {
+ return FALSE;
+ }
+
+ if (OleStdCopyFormatEtc(&pDest->formatetc, &pSrc->formatetc) == FALSE) {
+ return FALSE;
+ }
+
+ pDest->advf = pSrc->advf;
+ pDest->pAdvSink = pSrc->pAdvSink;
+ pDest->dwConnection = pSrc->dwConnection;
+
+ if (pDest->pAdvSink != NULL) {
+ pDest->pAdvSink->lpVtbl->AddRef(pDest->pAdvSink);
+ }
+
+ return TRUE;
+
+} /* OleStdCopyStatData()
+ */
+
+STDAPI_(LPENUMSTATDATA)
+ OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStatOrg)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPMALLOC lpMalloc=NULL;
+ LPOLESTDENUMSTATDATA lpSD=NULL;
+ DWORD dwSize;
+ WORD i;
+ HRESULT hRes;
+
+ hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
+ if (hRes != NOERROR) {
+ return NULL;
+ }
+
+ lpSD = (LPOLESTDENUMSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc,
+ sizeof(OLESTDENUMSTATDATA));
+ if (lpSD == NULL) {
+ goto errReturn;
+ }
+
+ lpSD->lpVtbl = &g_EnumSTATDATAVtbl;
+ lpSD->m_dwRefs = 1;
+ lpSD->m_nCount = nCount;
+ lpSD->m_nIndex = 0;
+
+ dwSize = sizeof(STATDATA) * lpSD->m_nCount;
+
+ lpSD->m_lpStat = (LPSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize);
+ if (lpSD->m_lpStat == NULL)
+ goto errReturn;
+
+ lpMalloc->lpVtbl->Release(lpMalloc);
+
+ for (i=0; i<nCount; i++) {
+ OleStdCopyStatData(
+ (LPSTATDATA)&(lpSD->m_lpStat[i]), (LPSTATDATA)&(lpStatOrg[i]));
+ }
+
+ return (LPENUMSTATDATA)lpSD;
+
+errReturn:
+ if (lpSD != NULL)
+ lpMalloc->lpVtbl->Free(lpMalloc, lpSD);
+
+ if (lpMalloc != NULL)
+ lpMalloc->lpVtbl->Release(lpMalloc);
+
+ return NULL;
+
+} /* OleStdEnumStatData_Create()
+ */
+
+
+VOID
+ OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA lpSD)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPMALLOC lpMalloc=NULL;
+ WORD i;
+
+ if (lpSD != NULL) {
+
+ if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) {
+
+ /* OLE2NOTE: we MUST free any memory that was allocated for
+ ** TARGETDEVICES contained within the STATDATA elements.
+ */
+ for (i=0; i<lpSD->m_nCount; i++) {
+ if( lpSD->m_lpStat[i].pAdvSink )
+ lpSD->m_lpStat[i].pAdvSink->lpVtbl->Release(lpSD->m_lpStat[i].pAdvSink);
+
+ OleStdFree(lpSD->m_lpStat[i].formatetc.ptd);
+ }
+
+ if (lpSD->m_lpStat != NULL) {
+ lpMalloc->lpVtbl->Free(lpMalloc, lpSD->m_lpStat);
+ }
+
+ lpMalloc->lpVtbl->Free(lpMalloc, lpSD);
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ }
+ }
+} /* OleStdEnumStatData_Destroy()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumStatData_QueryInterface(
+ LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ *ppobj = NULL;
+
+ if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumSTATDATA)){
+ *ppobj = (LPVOID)lpSD;
+ }
+
+ if (*ppobj == NULL) return ResultFromScode(E_NOINTERFACE);
+ else{
+ OleStdEnumStatData_AddRef(lpThis);
+ return NOERROR;
+ }
+
+} /* OleStdEnumStatData_QueryInterface()
+ */
+
+
+STDMETHODIMP_(ULONG)
+ OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ return lpSD->m_dwRefs++;
+
+} /* OleStdEnumStatData_AddRef()
+ */
+
+
+STDMETHODIMP_(ULONG)
+ OleStdEnumStatData_Release(LPENUMSTATDATA lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ DWORD dwRefs = --lpSD->m_dwRefs;
+
+ if (dwRefs == 0)
+ OleStdEnumStatData_Destroy(lpSD);
+
+ return dwRefs;
+
+} /* OleStdEnumStatData_Release()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt, LPSTATDATA rgelt,
+ ULONG FAR* pceltFetched)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ ULONG i=0;
+ ULONG nOffset;
+
+ if (rgelt == NULL) {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ while (i < celt) {
+ nOffset = lpSD->m_nIndex + i;
+
+ if (nOffset < lpSD->m_nCount) {
+ OleStdCopyStatData(
+ (LPSTATDATA)&(rgelt[i]), (LPSTATDATA)&(lpSD->m_lpStat[nOffset]));
+ i++;
+ }else{
+ break;
+ }
+ }
+
+ lpSD->m_nIndex += (WORD)i;
+
+ if (pceltFetched != NULL) {
+ *pceltFetched = i;
+ }
+
+ if (i != celt) {
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+} /* OleStdEnumStatData_Next()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ ULONG i=0;
+ ULONG nOffset;
+
+ while (i < celt) {
+ nOffset = lpSD->m_nIndex + i;
+
+ if (nOffset < lpSD->m_nCount) {
+ i++;
+ }else{
+ break;
+ }
+ }
+
+ lpSD->m_nIndex += (WORD)i;
+
+ if (i != celt) {
+ return ResultFromScode(S_FALSE);
+ }
+
+ return NOERROR;
+} /* OleStdEnumStatData_Skip()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+ lpSD->m_nIndex = 0;
+
+ return NOERROR;
+} /* OleStdEnumStatData_Reset()
+ */
+
+
+STDMETHODIMP
+ OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis, LPENUMSTATDATA FAR* ppenum)
+//----------------------------------------------------------------------------
+//
+//----------------------------------------------------------------------------
+{
+ LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
+
+ if (ppenum == NULL) {
+ return ResultFromScode(E_INVALIDARG);
+ }
+
+ *ppenum = OleStdEnumStatData_Create(lpSD->m_nCount, lpSD->m_lpStat);
+
+ // make sure cloned enumerator has same index state as the original
+ if (*ppenum) {
+ LPOLESTDENUMSTATDATA lpSDClone = (LPOLESTDENUMSTATDATA)*ppenum;
+ lpSDClone->m_nIndex = lpSD->m_nIndex;
+ return NOERROR;
+ } else
+ return ResultFromScode(E_OUTOFMEMORY);
+
+} /* OleStdEnumStatData_Clone()
+ */
+
diff --git a/private/oleutest/letest/ole2ui/filelist.mk b/private/oleutest/letest/ole2ui/filelist.mk
new file mode 100644
index 000000000..1a15317c7
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/filelist.mk
@@ -0,0 +1,75 @@
+############################################################################
+#
+# Microsoft Windows
+# Copyright (C) Microsoft Corporation, 1992 - 1992.
+# All rights reserved.
+#
+############################################################################
+
+
+#
+# Name of target. Include an extension (.dll, .lib, .exe)
+# If the target is part of the release, set RELEASE to 1.
+#
+
+TARGET = ole2uixd.lib
+RELEASE = 0
+TARGET_DESCRIPTION = "$(PLATFORM) $(BUILDTYPE) OLE 2 UI Library"
+
+
+#
+# Source files. Remember to prefix each name with .\
+#
+
+CFILES = .\busy.c \
+ .\common.c \
+ .\convert.c \
+ .\dbgutil.c \
+ .\dllfuncs.c \
+ .\drawicon.c \
+ .\enumfetc.c \
+ .\enumstat.c \
+ .\geticon.c \
+ .\hatch.c \
+ .\icon.c \
+ .\iconbox.c \
+ .\insobj.c \
+ .\links.c \
+ .\msgfiltr.c \
+ .\objfdbk.c \
+ .\ole2ui.c \
+ .\olestd.c \
+ .\oleutl.c \
+ .\pastespl.c \
+ .\precomp.c \
+ .\regdb.c \
+ .\resimage.c \
+ .\stdpal.c \
+ .\targtdev.c \
+ .\utility.c
+
+CPPFILES = .\suminfo.cpp \
+ .\dballoc.cpp
+
+RCFILES = .\ole2ui.rc
+
+#
+# Libraries and other object files to link.
+#
+OBJFILES =
+LIBS =
+
+DEFFILE =
+
+
+#
+# Precompiled headers.
+#
+
+PXXFILE =
+PFILE =
+CINC = -I$(CAIROLE)\h -I$(CAIROLE)\common \
+ -I.\resource\usa -I.\resource\static
+
+CFLAGS=/DWIN32 /D_DEBUG /DOLE201 /D_INC_OLE
+
diff --git a/private/oleutest/letest/ole2ui/fileopen.dlg b/private/oleutest/letest/ole2ui/fileopen.dlg
new file mode 100644
index 000000000..65f6e91dc
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/fileopen.dlg
@@ -0,0 +1,33 @@
+DLGINCLUDE RCDATA DISCARDABLE
+BEGIN
+ "OLE2UI.H\0"
+END
+
+IDD_FILEOPEN DIALOG 36, 24, 264, 134
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Open"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Source:", stc3, 6, 3, 76, 9
+ EDITTEXT edt1, 7, 13, 195, 12, ES_AUTOHSCROLL | ES_OEMCONVERT
+ LISTBOX lst1, 6, 34, 90, 68, LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "&Directories:", ID_DUMMY, 110, 28, 92, 9
+ LTEXT "", stc1, 110, 36, 92, 9, SS_NOPREFIX
+ LISTBOX lst2, 110, 49, 92, 53, LBS_SORT | LBS_OWNERDRAWFIXED |
+ LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_VSCROLL |
+ WS_TABSTOP
+ LTEXT "List Files of &Type:", stc2, 6, 104, 90, 9
+ COMBOBOX cmb1, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL |
+ WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Dri&ves:", stc4, 110, 104, 92, 9
+ COMBOBOX cmb2, 110, 114, 92, 68, CBS_DROPDOWNLIST |
+ CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT |
+ CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 208, 6, 50, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 208, 24, 50, 14, WS_GROUP
+ PUSHBUTTON "&Help", IDHELP, 208, 46, 50, 14, WS_GROUP
+ CONTROL "&Read Only", chx1, "Button", BS_AUTOCHECKBOX | WS_GROUP |
+ WS_TABSTOP, 208, 68, 50, 12
+END
diff --git a/private/oleutest/letest/ole2ui/geticon.c b/private/oleutest/letest/ole2ui/geticon.c
new file mode 100644
index 000000000..0bf1e13b3
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/geticon.c
@@ -0,0 +1,1177 @@
+/*************************************************************************
+**
+** The following API's are now OBSOLETE because equivalent API's have been
+** added to the OLE2.DLL library
+** GetIconOfFile superceeded by OleGetIconOfFile
+** GetIconOfClass superceeded by OleGetIconOfClass
+** OleUIMetafilePictFromIconAndLabel
+** superceeded by OleMetafilePictFromIconAndLabel
+*************************************************************************/
+
+/*
+ * GETICON.C
+ *
+ * Functions to create DVASPECT_ICON metafile from filename or classname.
+ *
+ * GetIconOfFile
+ * GetIconOfClass
+ * OleUIMetafilePictFromIconAndLabel
+ * HIconAndSourceFromClass Extracts the first icon in a class's server path
+ * and returns the path and icon index to caller.
+ * FIconFileFromClass Retrieves the path to the exe/dll containing the
+ * default icon, and the index of the icon.
+ * OleStdIconLabelTextOut Draw icon label text (line break if necessary)
+ *
+ * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved
+ */
+
+
+/*******
+ *
+ * ICON (DVASPECT_ICON) METAFILE FORMAT:
+ *
+ * The metafile generated with OleUIMetafilePictFromIconAndLabel contains
+ * the following records which are used by the functions in DRAWICON.C
+ * to draw the icon with and without the label and to extract the icon,
+ * label, and icon source/index.
+ *
+ * SetWindowOrg
+ * SetWindowExt
+ * DrawIcon:
+ * Inserts records of DIBBITBLT or DIBSTRETCHBLT, once for the
+ * AND mask, one for the image bits.
+ * Escape with the comment "IconOnly"
+ * This indicates where to stop record enumeration to draw only
+ * the icon.
+ * SetTextColor
+ * SetTextAlign
+ * SetBkColor
+ * CreateFont
+ * SelectObject on the font.
+ * ExtTextOut
+ * One or more ExtTextOuts occur if the label is wrapped. The
+ * text in these records is used to extract the label.
+ * SelectObject on the old font.
+ * DeleteObject on the font.
+ * Escape with a comment that contains the path to the icon source.
+ * Escape with a comment that is the ASCII of the icon index.
+ *
+ *******/
+
+#define STRICT 1
+#include "ole2ui.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <commdlg.h>
+#include <memory.h>
+#include <cderr.h>
+#include "common.h"
+#include "utility.h"
+
+static TCHAR szSeparators[] = TEXT(" \t\\/!:");
+
+#define IS_SEPARATOR(c) ( (c) == TEXT(' ') || (c) == TEXT('\\') \
+ || (c) == TEXT('/') || (c) == TEXT('\t') \
+ || (c) == TEXT('!') || (c) == TEXT(':') )
+#define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') \
+ || (c) == TEXT(':') )
+
+
+#if defined( OBSOLETE )
+static HINSTANCE s_hInst;
+
+static TCHAR szMaxWidth[] =TEXT("WWWWWWWWWW");
+
+//Strings for metafile comments.
+static TCHAR szIconOnly[]=TEXT("IconOnly"); //Where to stop to exclude label.
+
+#ifdef WIN32
+static TCHAR szOLE2DLL[] = TEXT("ole2w32.dll"); // name of OLE 2.0 library
+#else
+static TCHAR szOLE2DLL[] = TEXT("ole2.dll"); // name of OLE 2.0 library
+#endif
+
+#define ICONINDEX 0
+
+#define AUXUSERTYPE_SHORTNAME USERCLASSTYPE_SHORT // short name
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+static TCHAR szVanillaDocIcon[] = TEXT("DefIcon");
+
+static TCHAR szDocument[40] = TEXT("");
+
+
+/*
+ * GetIconOfFile(HINSTANCE hInst, LPSTR lpszPath, BOOL fUseFileAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (filename) for the
+ * specified filename.
+ *
+ * Parameters:
+ * hinst
+ * lpszPath LPTSTR path including filename to use
+ * fUseFileAsLabel BOOL TRUE if the icon's label is the filename, FALSE if
+ * there should be no label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if there's no
+ * class in reg db for the file in lpszPath, then we use
+ * Document. If lpszPath is NULL, then we return NULL.
+ */
+
+STDAPI_(HGLOBAL) GetIconOfFile(HINSTANCE hInst, LPTSTR lpszPath, BOOL fUseFileAsLabel)
+{
+ TCHAR szIconFile[OLEUI_CCHPATHMAX];
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ LPTSTR lpszClsid = NULL;
+ CLSID clsid;
+ HICON hDefIcon = NULL;
+ UINT IconIndex = 0;
+ HGLOBAL hMetaPict;
+ HRESULT hResult;
+
+ if (NULL == lpszPath) // even if fUseFileAsLabel is FALSE, we still
+ return NULL; // need a valid filename to get the class.
+
+ s_hInst = hInst;
+
+ hResult = GetClassFileA(lpszPath, &clsid);
+
+ if (NOERROR == hResult) // use the clsid we got to get to the icon
+ {
+ hDefIcon = HIconAndSourceFromClass(&clsid,
+ (LPTSTR)szIconFile,
+ &IconIndex);
+ }
+
+ if ( (NOERROR != hResult) || (NULL == hDefIcon) )
+ {
+ // Here, either GetClassFile failed or HIconAndSourceFromClass failed.
+
+ LPTSTR lpszTemp;
+
+ lpszTemp = lpszPath;
+
+ while ((*lpszTemp != TEXT('.')) && (*lpszTemp != TEXT('\0')))
+ lpszTemp++;
+
+
+ if (TEXT('.') != *lpszTemp)
+ goto UseVanillaDocument;
+
+
+ if (FALSE == GetAssociatedExecutable(lpszTemp, (LPTSTR)szIconFile))
+ goto UseVanillaDocument;
+
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+ }
+
+ if (hDefIcon <= (HICON)1) // ExtractIcon returns 1 if szExecutable is not exe,
+ { // 0 if there are no icons.
+UseVanillaDocument:
+
+ lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL);
+ IconIndex = ICONINDEX;
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+
+ }
+
+ // Now let's get the label we want to use.
+
+ if (fUseFileAsLabel) // strip off path, so we just have the filename.
+ {
+ int istrlen;
+ LPTSTR lpszBeginFile;
+
+ istrlen = lstrlen(lpszPath);
+
+ // set pointer to END of path, so we can walk backwards through it.
+ lpszBeginFile = lpszPath + istrlen -1;
+
+ while ( (lpszBeginFile >= lpszPath)
+ && (!IS_FILENAME_DELIM(*lpszBeginFile)) )
+ lpszBeginFile--;
+
+
+ lpszBeginFile++; // step back over the delimiter
+
+
+ LSTRCPYN(szLabel, lpszBeginFile, sizeof(szLabel)/sizeof(TCHAR));
+ }
+
+ else // use the short user type (AuxUserType2) for the label
+ {
+
+ if (0 == OleStdGetAuxUserType(&clsid, AUXUSERTYPE_SHORTNAME,
+ (LPTSTR)szLabel, OLEUI_CCHLABELMAX_SIZE, NULL)) {
+
+ if ('\0'==szDocument[0]) {
+ LoadString(
+ s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR));
+ }
+ lstrcpy(szLabel, szDocument);
+ }
+ }
+
+
+ hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon,
+ szLabel,
+ (LPTSTR)szIconFile,
+ IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+
+
+/*
+ * GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPSTR lpszLabel, BOOL fUseTypeAsLabel)
+ *
+ * Purpose:
+ * Returns a hMetaPict containing an icon and label (human-readable form
+ * of class) for the specified clsid.
+ *
+ * Parameters:
+ * hinst
+ * rclsid REFCLSID pointing to clsid to use.
+ * lpszLabel label to use for icon.
+ * fUseTypeAsLabel Use the clsid's user type name as the icon's label.
+ *
+ * Return Value:
+ * HGLOBAL hMetaPict containing the icon and label - if we
+ * don't find the clsid in the reg db then we
+ * return NULL.
+ */
+
+STDAPI_(HGLOBAL) GetIconOfClass(HINSTANCE hInst, REFCLSID rclsid, LPTSTR lpszLabel, BOOL fUseTypeAsLabel)
+{
+
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ TCHAR szIconFile[OLEUI_CCHPATHMAX];
+ HICON hDefIcon;
+ UINT IconIndex;
+ HGLOBAL hMetaPict;
+
+
+ s_hInst = hInst;
+
+ if (!fUseTypeAsLabel) // Use string passed in as label
+ {
+ if (NULL != lpszLabel)
+ LSTRCPYN(szLabel, lpszLabel, OLEUI_CCHLABELMAX_SIZE);
+ else
+ *szLabel = TEXT('\0');
+ }
+ else // Use AuxUserType2 (short name) as label
+ {
+
+ if (0 == OleStdGetAuxUserType(rclsid,
+ AUXUSERTYPE_SHORTNAME,
+ (LPTSTR)szLabel,
+ OLEUI_CCHLABELMAX_SIZE,
+ NULL))
+
+ // If we can't get the AuxUserType2, then try the long name
+ if (0 == OleStdGetUserTypeOfClass(rclsid, szLabel, OLEUI_CCHKEYMAX_SIZE, NULL)) {
+ if (TEXT('\0')==szDocument[0]) {
+ LoadString(
+ s_hInst,IDS_DEFICONLABEL,szDocument,sizeof(szDocument)/sizeof(TCHAR));
+ }
+ lstrcpy(szLabel, szDocument); // last resort
+ }
+ }
+
+ // Get the icon, icon index, and path to icon file
+ hDefIcon = HIconAndSourceFromClass(rclsid,
+ (LPTSTR)szIconFile,
+ &IconIndex);
+
+ if (NULL == hDefIcon) // Use Vanilla Document
+ {
+ lstrcpy((LPTSTR)szIconFile, (LPTSTR)szOLE2DLL);
+ IconIndex = ICONINDEX;
+ hDefIcon = ExtractIcon(s_hInst, szIconFile, IconIndex);
+ }
+
+ // Create the metafile
+ hMetaPict = OleUIMetafilePictFromIconAndLabel(hDefIcon, szLabel,
+ (LPTSTR)szIconFile, IconIndex);
+
+ DestroyIcon(hDefIcon);
+
+ return hMetaPict;
+
+}
+
+
+/*
+ * OleUIMetafilePictFromIconAndLabel
+ *
+ * Purpose:
+ * Creates a METAFILEPICT structure that container a metafile in which
+ * the icon and label are drawn. A comment record is inserted between
+ * the icon and the label code so our special draw function can stop
+ * playing before the label.
+ *
+ * Parameters:
+ * hIcon HICON to draw into the metafile
+ * pszLabel LPTSTR to the label string.
+ * pszSourceFile LPTSTR containing the local pathname of the icon
+ * as we either get from the user or from the reg DB.
+ * iIcon UINT providing the index into pszSourceFile where
+ * the icon came from.
+ *
+ * Return Value:
+ * HGLOBAL Global memory handle containing a METAFILEPICT where
+ * the metafile uses the MM_ANISOTROPIC mapping mode. The
+ * extents reflect both icon and label.
+ */
+
+STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON hIcon, LPTSTR pszLabel
+ , LPTSTR pszSourceFile, UINT iIcon)
+ {
+ HDC hDC, hDCScreen;
+ HMETAFILE hMF;
+ HGLOBAL hMem;
+ LPMETAFILEPICT pMF;
+ UINT cxIcon, cyIcon;
+ UINT cxText, cyText;
+ UINT cx, cy;
+ UINT cchLabel = 0;
+ HFONT hFont, hFontT;
+ int cyFont;
+ TCHAR szIndex[10];
+ RECT TextRect;
+ SIZE size;
+ POINT point;
+ UINT fuAlign;
+
+ if (NULL==hIcon) // null label is valid but NOT a null icon
+ return NULL;
+
+ //Create a memory metafile
+ hDC=(HDC)CreateMetaFile(NULL);
+
+ if (NULL==hDC)
+ return NULL;
+
+ //Allocate the metafilepict
+ hMem=GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(METAFILEPICT));
+
+ if (NULL==hMem)
+ {
+ hMF=CloseMetaFile(hDC);
+ DeleteMetaFile(hMF);
+ return NULL;
+ }
+
+
+ if (NULL!=pszLabel)
+ {
+ cchLabel=lstrlen(pszLabel);
+
+ if (cchLabel >= OLEUI_CCHLABELMAX)
+ pszLabel[cchLabel] = TEXT('\0'); // truncate string
+ }
+
+ //Need to use the screen DC for these operations
+ hDCScreen=GetDC(NULL);
+ cyFont=-(8*GetDeviceCaps(hDCScreen, LOGPIXELSY))/72;
+
+ //cyFont was calculated to give us 8 point.
+ hFont=CreateFont(cyFont, 5, 0, 0, FW_NORMAL, 0, 0, 0, ANSI_CHARSET
+ , OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY
+ , FF_SWISS, TEXT("MS Sans Serif"));
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ GetTextExtentPoint(hDCScreen,szMaxWidth,lstrlen(szMaxWidth),&size);
+ SelectObject(hDCScreen, hFontT);
+
+ cxText = size.cx;
+ cyText = size.cy * 2;
+
+ cxIcon = GetSystemMetrics(SM_CXICON);
+ cyIcon = GetSystemMetrics(SM_CYICON);
+
+
+ // If we have no label, then we want the metafile to be the width of
+ // the icon (plus margin), not the width of the fattest string.
+ if ( (NULL == pszLabel) || (TEXT('\0') == *pszLabel) )
+ cx = cxIcon + cxIcon / 4;
+ else
+ cx = max(cxText, cxIcon);
+
+ cy=cyIcon+cyText+4;
+
+ //Set the metafile size to fit the icon and label
+ SetWindowOrgEx(hDC, 0, 0, &point);
+ SetWindowExtEx(hDC, cx, cy, &size);
+
+ //Set up rectangle to pass to OleStdIconLabelTextOut
+ SetRectEmpty(&TextRect);
+
+ TextRect.right = cx;
+ TextRect.bottom = cy;
+
+ //Draw the icon and the text, centered with respect to each other.
+ DrawIcon(hDC, (cx-cxIcon)/2, 0, hIcon);
+
+ //String that indicates where to stop if we're only doing icons
+ Escape(hDC, MFCOMMENT, lstrlen(szIconOnly)+1, szIconOnly, NULL);
+
+ SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
+ SetBkMode(hDC, TRANSPARENT);
+ fuAlign = SetTextAlign(hDC, TA_LEFT | TA_TOP | TA_NOUPDATECP);
+
+ OleStdIconLabelTextOut(hDC,
+ hFont,
+ 0,
+ cy - cyText,
+ ETO_CLIPPED,
+ &TextRect,
+ pszLabel,
+ cchLabel,
+ NULL);
+
+ //Write comments containing the icon source file and index.
+ if (NULL!=pszSourceFile)
+ {
+ //+1 on string lengths insures the null terminator is embedded.
+ Escape(hDC, MFCOMMENT, lstrlen(pszSourceFile)+1, pszSourceFile, NULL);
+
+ cchLabel=wsprintf(szIndex, TEXT("%u"), iIcon);
+ Escape(hDC, MFCOMMENT, cchLabel+1, szIndex, NULL);
+ }
+
+ SetTextAlign(hDC, fuAlign);
+
+ //All done with the metafile, now stuff it all into a METAFILEPICT.
+ hMF=CloseMetaFile(hDC);
+
+ if (NULL==hMF)
+ {
+ GlobalFree(hMem);
+ ReleaseDC(NULL, hDCScreen);
+ return NULL;
+ }
+
+ //Fill out the structure
+ pMF=(LPMETAFILEPICT)GlobalLock(hMem);
+
+ //Transform to HIMETRICS
+ cx=XformWidthInPixelsToHimetric(hDCScreen, cx);
+ cy=XformHeightInPixelsToHimetric(hDCScreen, cy);
+ ReleaseDC(NULL, hDCScreen);
+
+ pMF->mm=MM_ANISOTROPIC;
+ pMF->xExt=cx;
+ pMF->yExt=cy;
+ pMF->hMF=hMF;
+
+ GlobalUnlock(hMem);
+
+ DeleteObject(hFont);
+
+ return hMem;
+ }
+
+#endif // OBSOLETE
+
+
+/*
+ * GetAssociatedExecutable
+ *
+ * Purpose: Finds the executable associated with the provided extension
+ *
+ * Parameters:
+ * lpszExtension LPSTR points to the extension we're trying to find
+ * an exe for. Does **NO** validation.
+ *
+ * lpszExecutable LPSTR points to where the exe name will be returned.
+ * No validation here either - pass in 128 char buffer.
+ *
+ * Return:
+ * BOOL TRUE if we found an exe, FALSE if we didn't.
+ *
+ */
+
+BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR lpszExtension, LPTSTR lpszExecutable)
+
+{
+ HKEY hKey;
+ LONG dw;
+ LRESULT lRet;
+ TCHAR szValue[OLEUI_CCHKEYMAX];
+ TCHAR szKey[OLEUI_CCHKEYMAX];
+ LPTSTR lpszTemp, lpszExe;
+
+
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ return FALSE;
+
+ dw = OLEUI_CCHPATHMAX_SIZE;
+ lRet = RegQueryValue(hKey, lpszExtension, (LPTSTR)szValue, &dw); //ProgId
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+
+ // szValue now has ProgID
+ lstrcpy(szKey, szValue);
+ lstrcat(szKey, TEXT("\\Shell\\Open\\Command"));
+
+
+ dw = OLEUI_CCHPATHMAX_SIZE;
+ lRet = RegQueryValue(hKey, (LPTSTR)szKey, (LPTSTR)szValue, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ RegCloseKey(hKey);
+ return FALSE;
+ }
+
+ // szValue now has an executable name in it. Let's null-terminate
+ // at the first post-executable space (so we don't have cmd line
+ // args.
+
+ lpszTemp = (LPTSTR)szValue;
+
+ while ((TEXT('\0') != *lpszTemp) && (iswspace(*lpszTemp)))
+ lpszTemp++; // Strip off leading spaces
+
+ lpszExe = lpszTemp;
+
+ while ((TEXT('\0') != *lpszTemp) && (!iswspace(*lpszTemp)))
+ lpszTemp++; // Step through exe name
+
+ *lpszTemp = TEXT('\0'); // null terminate at first space (or at end).
+
+
+ lstrcpy(lpszExecutable, lpszExe);
+
+ return TRUE;
+
+}
+
+
+/*
+ * HIconAndSourceFromClass
+ *
+ * Purpose:
+ * Given an object class name, finds an associated executable in the
+ * registration database and extracts the first icon from that
+ * executable. If none is available or the class has no associated
+ * executable, this function returns NULL.
+ *
+ * Parameters:
+ * rclsid pointer to clsid to look up.
+ * pszSource LPSTR in which to place the source of the icon.
+ * This is assumed to be OLEUI_CCHPATHMAX
+ * puIcon UINT FAR * in which to store the index of the
+ * icon in pszSource.
+ *
+ * Return Value:
+ * HICON Handle to the extracted icon if there is a module
+ * associated to pszClass. NULL on failure to either
+ * find the executable or extract and icon.
+ */
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID rclsid, LPTSTR pszSource, UINT FAR *puIcon)
+ {
+ HICON hIcon;
+ UINT IconIndex;
+
+ if (NULL==rclsid || NULL==pszSource || IsEqualCLSID(rclsid,&CLSID_NULL))
+ return NULL;
+
+ if (!FIconFileFromClass(rclsid, pszSource, OLEUI_CCHPATHMAX_SIZE, &IconIndex))
+ return NULL;
+
+ hIcon=ExtractIcon(ghInst, pszSource, IconIndex);
+
+ if ((HICON)32 > hIcon)
+ hIcon=NULL;
+ else
+ *puIcon= IconIndex;
+
+ return hIcon;
+ }
+
+
+/*
+ * PointerToNthField
+ *
+ * Purpose:
+ * Returns a pointer to the beginning of the nth field.
+ * Assumes null-terminated string.
+ *
+ * Parameters:
+ * lpszString string to parse
+ * nField field to return starting index of.
+ * chDelimiter char that delimits fields
+ *
+ * Return Value:
+ * LPSTR pointer to beginning of nField field.
+ * NOTE: If the null terminator is found
+ * Before we find the Nth field, then
+ * we return a pointer to the null terminator -
+ * calling app should be sure to check for
+ * this case.
+ *
+ */
+LPTSTR FAR PASCAL PointerToNthField(LPTSTR lpszString, int nField, TCHAR chDelimiter)
+{
+ LPTSTR lpField = lpszString;
+ int cFieldFound = 1;
+
+ if (1 ==nField)
+ return lpszString;
+
+ while (*lpField != TEXT('\0'))
+ {
+
+ if (*lpField++ == chDelimiter)
+ {
+
+ cFieldFound++;
+
+ if (nField == cFieldFound)
+ return lpField;
+ }
+ }
+
+ return lpField;
+
+}
+
+
+/*
+ * FIconFileFromClass
+ *
+ * Purpose:
+ * Looks up the path to executable that contains the class default icon.
+ *
+ * Parameters:
+ * rclsid pointer to CLSID to look up.
+ * pszEXE LPSTR at which to store the server name
+ * cch UINT size of pszEXE
+ * lpIndex LPUINT to index of icon within executable
+ *
+ * Return Value:
+ * BOOL TRUE if one or more characters were loaded into pszEXE.
+ * FALSE otherwise.
+ */
+
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID rclsid, LPTSTR pszEXE, UINT cchBytes, UINT FAR *lpIndex)
+{
+
+ LONG dw;
+ LONG lRet;
+ HKEY hKey;
+ LPMALLOC lpIMalloc;
+ HRESULT hrErr;
+ LPTSTR lpBuffer;
+ LPTSTR lpIndexString;
+ UINT cBufferSize = 136;// room for 128 char path and icon's index
+ TCHAR szKey[64];
+ LPSTR pszClass;
+ UINT cch=cchBytes / sizeof(TCHAR); // number of characters
+
+
+ if (NULL==rclsid || NULL==pszEXE || 0==cch || IsEqualCLSID(rclsid,&CLSID_NULL))
+ return FALSE;
+
+ //Here, we use CoGetMalloc and alloc a buffer (maxpathlen + 8) to
+ //pass to RegQueryValue. Then, we copy the exe to pszEXE and the
+ //index to *lpIndex.
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &lpIMalloc);
+
+ if (NOERROR != hrErr)
+ return FALSE;
+
+ lpBuffer = (LPTSTR)lpIMalloc->lpVtbl->Alloc(lpIMalloc, cBufferSize);
+
+ if (NULL == lpBuffer)
+ {
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ if (CoIsOle1Class(rclsid))
+ {
+
+ LPOLESTR lpszProgID;
+
+ // we've got an ole 1.0 class on our hands, so we look at
+ // progID\protocol\stdfileedting\server to get the
+ // name of the executable.
+
+ ProgIDFromCLSID(rclsid, &lpszProgID);
+
+ //Open up the class key
+#ifdef UNICODE
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, lpszProgID, &hKey);
+#else
+ {
+ char szTemp[255];
+
+ wcstombs(szTemp, lpszProgID, 255);
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szTemp, &hKey);
+ }
+#endif
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ dw=(LONG)cBufferSize;
+ lRet = RegQueryValue(hKey, TEXT("Protocol\\StdFileEditing\\Server"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ // Use server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpszProgID);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+
+ }
+
+
+
+ /*
+ * We have to go walking in the registration database under the
+ * classname, so we first open the classname key and then check
+ * under "\\DefaultIcon" to get the file that contains the icon.
+ */
+
+ StringFromCLSIDA(rclsid, &pszClass);
+
+ lstrcpy(szKey, TEXT("CLSID\\"));
+
+ lstrcat(szKey, pszClass);
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hKey);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ //Get the executable path and icon index.
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, TEXT("DefaultIcon"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no DefaultIcon key...try LocalServer
+
+ dw=(LONG)cBufferSize;
+ lRet=RegQueryValue(hKey, TEXT("LocalServer"), lpBuffer, &dw);
+
+ if (ERROR_SUCCESS != lRet)
+ {
+ // no LocalServer entry either...they're outta luck.
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+
+ // Use server from LocalServer or Server and 0 as the icon index
+ LSTRCPYN(pszEXE, lpBuffer, cch);
+
+ *lpIndex = 0;
+
+ RegCloseKey(hKey);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+ }
+
+ RegCloseKey(hKey);
+
+ // lpBuffer contains a string that looks like "<pathtoexe>,<iconindex>",
+ // so we need to separate the path and the icon index.
+
+ lpIndexString = PointerToNthField(lpBuffer, 2, TEXT(','));
+
+ if (TEXT('\0') == *lpIndexString) // no icon index specified - use 0 as default.
+ {
+ *lpIndex = 0;
+
+ }
+ else
+ {
+ LPTSTR lpTemp;
+ static TCHAR szTemp[16];
+
+ lstrcpy((LPTSTR)szTemp, lpIndexString);
+
+ // Put the icon index part into *pIconIndex
+#ifdef UNICODE
+ {
+ char szTEMP1[16];
+
+ wcstombs(szTEMP1, szTemp, 16);
+ *lpIndex = atoi((const char *)szTEMP1);
+ }
+#else
+ *lpIndex = atoi((const char *)szTemp);
+#endif
+
+ // Null-terminate the exe part.
+#ifdef WIN32
+ lpTemp = CharPrev(lpBuffer, lpIndexString);
+#else
+ lpTemp = AnsiPrev(lpBuffer, lpIndexString);
+#endif
+ *lpTemp = TEXT('\0');
+ }
+
+ if (!LSTRCPYN(pszEXE, lpBuffer, cch))
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return FALSE;
+ }
+
+ // Free the memory we alloc'd and leave.
+ lpIMalloc->lpVtbl->Free(lpIMalloc, lpBuffer);
+ lpIMalloc->lpVtbl->Free(lpIMalloc, pszClass);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ return TRUE;
+}
+
+
+
+/*
+ * OleStdIconLabelTextOut
+ *
+ * Purpose:
+ * Replacement for DrawText to be used in the "Display as Icon" metafile.
+ * Uses ExtTextOut to output a string center on (at most) two lines.
+ * Uses a very simple word wrap algorithm to split the lines.
+ *
+ * Parameters: (same as for ExtTextOut, except for hFont)
+ * hDC device context to draw into; if this is NULL, then we don't
+ * ETO the text, we just return the index of the beginning
+ * of the second line
+ * hFont font to use
+ * nXStart x-coordinate of starting position
+ * nYStart y-coordinate of starting position
+ * fuOptions rectangle type
+ * lpRect rect far * containing rectangle to draw text in.
+ * lpszString string to draw
+ * cchString length of string (truncated if over OLEUI_CCHLABELMAX)
+ * lpDX spacing between character cells
+ *
+ * Return Value:
+ * UINT Index of beginning of last line (0 if there's only one
+ * line of text).
+ *
+ */
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPTSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX)
+{
+
+ HDC hDCScreen;
+ static TCHAR szTempBuff[OLEUI_CCHLABELMAX];
+ int cxString, cyString, cxMaxString;
+ int cxFirstLine, cyFirstLine, cxSecondLine;
+ int index;
+ int cch = cchString;
+ TCHAR chKeep;
+ LPTSTR lpszSecondLine;
+ HFONT hFontT;
+ BOOL fPrintText = TRUE;
+ UINT iLastLineStart = 0;
+ SIZE size;
+
+ // Initialization stuff...
+
+ if (NULL == hDC) // If we got NULL as the hDC, then we don't actually call ETO
+ fPrintText = FALSE;
+
+
+ // Make a copy of the string (NULL or non-NULL) that we're using
+ if (NULL == lpszString)
+ *szTempBuff = TEXT('\0');
+
+ else
+ LSTRCPYN(szTempBuff, lpszString, sizeof(szTempBuff)/sizeof(TCHAR));
+
+ // set maximum width
+ cxMaxString = lpRect->right - lpRect->left;
+
+ // get screen DC to do text size calculations
+ hDCScreen = GetDC(NULL);
+
+ hFontT=SelectObject(hDCScreen, hFont);
+
+ // get the extent of our label
+#ifdef WIN32
+ // GetTextExtentPoint32 has fixed the off-by-one bug.
+ GetTextExtentPoint32(hDCScreen, szTempBuff, cch, &size);
+#else
+ GetTextExtentPoint(hDCScreen, szTempBuff, cch, &size);
+#endif
+
+ cxString = size.cx;
+ cyString = size.cy;
+
+ // Select in the font we want to use
+ if (fPrintText)
+ SelectObject(hDC, hFont);
+
+ // String is smaller than max string - just center, ETO, and return.
+ if (cxString <= cxMaxString)
+ {
+
+ if (fPrintText)
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxString) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ szTempBuff,
+ cch,
+ NULL);
+
+ iLastLineStart = 0; // only 1 line of text
+ goto CleanupAndLeave;
+ }
+
+ // String is too long...we've got to word-wrap it.
+
+
+ // Are there any spaces, slashes, tabs, or bangs in string?
+
+ if (lstrlen(szTempBuff) != (int)
+#ifdef UNICODE
+ wcscspn(szTempBuff, szSeparators)
+#else
+ strcspn(szTempBuff, szSeparators)
+#endif
+ )
+ {
+ // Yep, we've got spaces, so we'll try to find the largest
+ // space-terminated string that will fit on the first line.
+
+ index = cch;
+
+
+ while (index >= 0)
+ {
+
+ TCHAR cchKeep;
+
+ // scan the string backwards for spaces, slashes, tabs, or bangs
+
+ while (!IS_SEPARATOR(szTempBuff[index]) )
+ index--;
+
+
+ if (index <= 0)
+ break;
+
+ cchKeep = szTempBuff[index]; // remember what char was there
+
+ szTempBuff[index] = TEXT('\0'); // just for now
+
+#ifdef WIN32
+ GetTextExtentPoint32(
+ hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size);
+#else
+ GetTextExtentPoint(
+ hDCScreen, (LPTSTR)szTempBuff,lstrlen((LPTSTR)szTempBuff),&size);
+#endif
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ szTempBuff[index] = cchKeep; // put the right char back
+
+ if (cxFirstLine <= cxMaxString)
+ {
+
+ iLastLineStart = index + 1;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPTSTR)szTempBuff,
+ index + 1,
+ lpDX);
+
+ lpszSecondLine = (LPTSTR)szTempBuff;
+
+ lpszSecondLine += (index + 1) ;
+
+ GetTextExtentPoint(hDCScreen,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+ goto CleanupAndLeave;
+
+ } // end if
+
+ index--;
+
+ } // end while
+
+ } // end if
+
+ // Here, there are either no spaces in the string (strchr(szTempBuff, ' ')
+ // returned NULL), or there spaces in the string, but they are
+ // positioned so that the first space terminated string is still
+ // longer than one line. So, we walk backwards from the end of the
+ // string until we find the largest string that will fit on the first
+ // line , and then we just clip the second line.
+
+ cch = lstrlen((LPTSTR)szTempBuff);
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = TEXT('\0');
+
+ GetTextExtentPoint(hDCScreen, szTempBuff, lstrlen(szTempBuff),&size);
+
+ cxFirstLine = size.cx;
+ cyFirstLine = size.cy;
+
+ while (cxFirstLine > cxMaxString)
+ {
+ // We allow 40 characters in the label, but the metafile is
+ // only as wide as 10 W's (for aesthetics - 20 W's wide looked
+ // dumb. This means that if we split a long string in half (in
+ // terms of characters), then we could still be wider than the
+ // metafile. So, if this is the case, we just step backwards
+ // from the halfway point until we get something that will fit.
+ // Since we just let ETO clip the second line
+
+ szTempBuff[cch--] = chKeep;
+ if (0 == cch)
+ goto CleanupAndLeave;
+
+ chKeep = szTempBuff[cch];
+ szTempBuff[cch] = TEXT('\0');
+
+ GetTextExtentPoint(
+ hDCScreen, szTempBuff, lstrlen(szTempBuff), &size);
+ cxFirstLine = size.cx;
+ }
+
+ iLastLineStart = cch;
+
+ if (!fPrintText)
+ goto CleanupAndLeave;
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxFirstLine) / 2,
+ nYStart,
+ fuOptions,
+ lpRect,
+ (LPTSTR)szTempBuff,
+ lstrlen((LPTSTR)szTempBuff),
+ lpDX);
+
+ szTempBuff[cch] = chKeep;
+ lpszSecondLine = szTempBuff;
+ lpszSecondLine += cch ;
+
+ GetTextExtentPoint(
+ hDCScreen, (LPTSTR)lpszSecondLine, lstrlen(lpszSecondLine), &size);
+
+ // If the second line is wider than the rectangle, we
+ // just want to clip the text.
+ cxSecondLine = min(size.cx, cxMaxString);
+
+ ExtTextOut(hDC,
+ nXStart + (lpRect->right - cxSecondLine) / 2,
+ nYStart + cyFirstLine,
+ fuOptions,
+ lpRect,
+ lpszSecondLine,
+ lstrlen(lpszSecondLine),
+ lpDX);
+
+CleanupAndLeave:
+ SelectObject(hDCScreen, hFontT);
+ ReleaseDC(NULL, hDCScreen);
+ return iLastLineStart;
+
+}
+
diff --git a/private/oleutest/letest/ole2ui/geticon.h b/private/oleutest/letest/ole2ui/geticon.h
new file mode 100644
index 000000000..223411385
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/geticon.h
@@ -0,0 +1,18 @@
+// This file is now OBSOLETE (include olestd.h instead)
+/*
+ * GETICON.H
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+/*************************************************************************
+**
+** The following API's are now OBSOLETE because equivalent API's have been
+** added to the OLE2.DLL library
+** GetIconOfFile superceeded by OleGetIconOfFile
+** GetIconOfClass superceeded by OleGetIconOfClass
+** OleUIMetafilePictFromIconAndLabel
+** superceeded by OleMetafilePictFromIconAndLabel
+*************************************************************************/
+
+// Other function prototypes moved to olestd.h
diff --git a/private/oleutest/letest/ole2ui/hatch.c b/private/oleutest/letest/ole2ui/hatch.c
new file mode 100644
index 000000000..1e156a1e0
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/hatch.c
@@ -0,0 +1,325 @@
+/*
+ * HATCH.C
+ *
+ * Miscellaneous API's to generate hatch window for in-place active
+ * objects. This is part of the OLE 2.0 User Interface Support Library.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+
+// offsets in the extra bytes stored with the hatch window
+#define EB_HATCHWIDTH 0
+#define EB_HATCHRECT_LEFT 2
+#define EB_HATCHRECT_TOP 4
+#define EB_HATCHRECT_RIGHT 6
+#define EB_HATCHRECT_BOTTOM 8
+
+// class name of hatch window
+#define CLASS_HATCH TEXT("Hatch Window")
+
+// local function prototypes
+LRESULT FAR PASCAL EXPORT HatchWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam);
+
+
+/*
+ * HatchRegisterClass
+ *
+ * Purpose:
+ * Register the hatch window
+ *
+ * Parameters:
+ * hInst Process instance
+ *
+ * Return Value:
+ * TRUE if successful
+ * FALSE if failed
+ *
+ */
+STDAPI_(BOOL) RegisterHatchWindowClass(HINSTANCE hInst)
+{
+ WNDCLASS wc;
+
+ // Register Hatch Window Class
+ wc.style = CS_BYTEALIGNWINDOW;
+ wc.lpfnWndProc = HatchWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 5 * sizeof(int); // extra bytes stores
+ // uHatchWidth
+ // rcHatchRect
+ wc.hInstance = hInst;
+ wc.hIcon = NULL;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = CLASS_HATCH;
+
+ if (!RegisterClass(&wc))
+ return FALSE;
+ else
+ return TRUE;
+}
+
+
+/*
+ * CreateHatchWindow
+ *
+ * Purpose:
+ * Create the hatch window
+ *
+ * Parameters:
+ * hWndParent parent of hatch window
+ * hInst instance handle
+ *
+ * Return Value:
+ * pointer to hatch window if successful
+ * NULL if failed
+ *
+ */
+STDAPI_(HWND) CreateHatchWindow(HWND hWndParent, HINSTANCE hInst)
+{
+ HWND hWnd;
+
+ if (!hWndParent || !hInst)
+ return NULL;
+
+ hWnd = CreateWindow(
+ CLASS_HATCH,
+ TEXT("Hatch Window"),
+ WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+ 0, 0, 0, 0,
+ hWndParent,
+ (HMENU)NULL,
+ hInst,
+ 0L
+ );
+
+ if (!hWnd)
+ return NULL;
+
+ return hWnd;
+}
+
+/*
+ * GetHatchWidth
+ *
+ * Purpose:
+ * Get width of hatch border
+ *
+ * Parameters:
+ * hWndHatch hatch window handle
+ *
+ * Return Value:
+ * width of the hatch border
+ */
+STDAPI_(UINT) GetHatchWidth(HWND hWndHatch)
+{
+ if (!IsWindow(hWndHatch))
+ return 0;
+
+ return (UINT)GetWindowWord(hWndHatch, EB_HATCHWIDTH);
+}
+
+/*
+ * GetHatchRect
+ *
+ * Purpose:
+ * Get hatch rect. this is the size of the hatch window if it were
+ * not clipped by the ClipRect.
+ *
+ * Parameters:
+ * hWndHatch hatch window handle
+ * lprcHatchRect hatch rect
+ *
+ * Return Value:
+ * none
+ */
+STDAPI_(void) GetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect)
+{
+ if (!IsWindow(hWndHatch)) {
+ SetRect(lprcHatchRect, 0, 0, 0, 0);
+ return;
+ }
+
+ lprcHatchRect->left = GetWindowWord(hWndHatch, EB_HATCHRECT_LEFT);
+ lprcHatchRect->top = GetWindowWord(hWndHatch, EB_HATCHRECT_TOP);
+ lprcHatchRect->right = GetWindowWord(hWndHatch, EB_HATCHRECT_RIGHT);
+ lprcHatchRect->bottom = GetWindowWord(hWndHatch, EB_HATCHRECT_BOTTOM);
+}
+
+
+/* SetHatchRect
+ *
+ *
+ * Purpose:
+ * Store hatch rect with HatchRect window.
+ * this rect is the size of the hatch window if it were
+ * not clipped by the ClipRect.
+ *
+ * Parameters:
+ * hWndHatch hatch window handle
+ * lprcHatchRect hatch rect
+ *
+ * Return Value:
+ * none
+ */
+STDAPI_(void) SetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect)
+{
+ if (!IsWindow(hWndHatch))
+ return;
+
+ SetWindowWord(hWndHatch, EB_HATCHRECT_LEFT, (WORD)lprcHatchRect->left);
+ SetWindowWord(hWndHatch, EB_HATCHRECT_TOP, (WORD)lprcHatchRect->top);
+ SetWindowWord(hWndHatch, EB_HATCHRECT_RIGHT, (WORD)lprcHatchRect->right);
+ SetWindowWord(hWndHatch, EB_HATCHRECT_BOTTOM,(WORD)lprcHatchRect->bottom);
+}
+
+
+/* SetHatchWindowSize
+ *
+ *
+ * Purpose:
+ * Move/size the HatchWindow correctly given the rect required by the
+ * in-place server object window and the lprcClipRect imposed by the
+ * in-place container. both rect's are expressed in the client coord.
+ * of the in-place container's window (which is the parent of the
+ * HatchWindow).
+ *
+ * OLE2NOTE: the in-place server must honor the lprcClipRect specified
+ * by its in-place container. it must NOT draw outside of the ClipRect.
+ * in order to achieve this, the hatch window is sized to be
+ * exactly the size that should be visible (rcVisRect). the
+ * rcVisRect is defined as the intersection of the full size of
+ * the HatchRect window and the lprcClipRect.
+ * the ClipRect could infact clip the HatchRect on the
+ * right/bottom and/or on the top/left. if it is clipped on the
+ * right/bottom then it is sufficient to simply resize the hatch
+ * window. but if the HatchRect is clipped on the top/left then
+ * in-place server document window (child of HatchWindow) must be moved
+ * by the delta that was clipped. the window origin of the
+ * in-place server window will then have negative coordinates relative
+ * to its parent HatchWindow.
+ *
+ * Parameters:
+ * hWndHatch hatch window handle
+ * lprcIPObjRect full size of in-place server object window
+ * lprcClipRect clipping rect imposed by in-place container
+ * lpptOffset offset required to position in-place server object
+ * window properly. caller should call:
+ * OffsetRect(&rcObjRect,lpptOffset->x,lpptOffset->y)
+ *
+ * Return Value:
+ * none
+ */
+STDAPI_(void) SetHatchWindowSize(
+ HWND hWndHatch,
+ LPRECT lprcIPObjRect,
+ LPRECT lprcClipRect,
+ LPPOINT lpptOffset
+)
+{
+ RECT rcHatchRect;
+ RECT rcVisRect;
+ UINT uHatchWidth;
+ POINT ptOffset;
+
+ if (!IsWindow(hWndHatch))
+ return;
+
+ rcHatchRect = *lprcIPObjRect;
+ uHatchWidth = GetHatchWidth(hWndHatch);
+ InflateRect((LPRECT)&rcHatchRect, uHatchWidth + 1, uHatchWidth + 1);
+
+ IntersectRect((LPRECT)&rcVisRect, (LPRECT)&rcHatchRect, lprcClipRect);
+ MoveWindow(
+ hWndHatch,
+ rcVisRect.left,
+ rcVisRect.top,
+ rcVisRect.right-rcVisRect.left,
+ rcVisRect.bottom-rcVisRect.top,
+ TRUE /* fRepaint */
+ );
+ InvalidateRect(hWndHatch, NULL, TRUE);
+
+ ptOffset.x = -rcHatchRect.left + (rcHatchRect.left - rcVisRect.left);
+ ptOffset.y = -rcHatchRect.top + (rcHatchRect.top - rcVisRect.top);
+
+ /* convert the rcHatchRect into the client coordinate system of the
+ ** HatchWindow itself
+ */
+ OffsetRect((LPRECT)&rcHatchRect, ptOffset.x, ptOffset.y);
+
+ SetHatchRect(hWndHatch, (LPRECT)&rcHatchRect);
+
+ // calculate offset required to position in-place server doc window
+ lpptOffset->x = ptOffset.x;
+ lpptOffset->y = ptOffset.y;
+}
+
+
+/*
+ * HatchWndProc
+ *
+ * Purpose:
+ * WndProc for hatch window
+ *
+ * Parameters:
+ * hWnd
+ * Message
+ * wParam
+ * lParam
+ *
+ * Return Value:
+ * message dependent
+ */
+LRESULT FAR PASCAL EXPORT HatchWndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam)
+{
+ int nBorderWidth;
+
+ switch (Message) {
+
+ case WM_CREATE:
+ nBorderWidth = GetProfileInt(
+ TEXT("windows"),
+ TEXT("oleinplaceborderwidth"),
+ DEFAULT_HATCHBORDER_WIDTH
+ );
+ SetWindowWord(hWnd, EB_HATCHWIDTH, (WORD)nBorderWidth);
+ break;
+
+ case WM_PAINT:
+ {
+ HDC hDC;
+ PAINTSTRUCT ps;
+ RECT rcHatchRect;
+
+ nBorderWidth = GetHatchWidth(hWnd);
+ hDC = BeginPaint(hWnd, &ps);
+ GetHatchRect(hWnd, (LPRECT)&rcHatchRect);
+ OleUIDrawShading(&rcHatchRect, hDC, OLEUI_SHADE_BORDERIN,
+ nBorderWidth);
+ InflateRect((LPRECT)&rcHatchRect, -nBorderWidth, -nBorderWidth);
+ OleUIDrawHandles(&rcHatchRect, hDC, OLEUI_HANDLES_OUTSIDE,
+ nBorderWidth+1, TRUE);
+ EndPaint(hWnd, &ps);
+ break;
+ }
+
+ /* OLE2NOTE: Any window that is used during in-place activation
+ ** must handle the WM_SETCURSOR message or else the cursor
+ ** of the in-place parent will be used. if WM_SETCURSOR is
+ ** not handled, then DefWindowProc sends the message to the
+ ** window's parent.
+ */
+ case WM_SETCURSOR:
+ SetCursor(LoadCursor( NULL, MAKEINTRESOURCE(IDC_ARROW) ) );
+ return (LRESULT)TRUE;
+
+ default:
+ return DefWindowProc(hWnd, Message, wParam, lParam);
+ }
+
+ return 0L;
+}
diff --git a/private/oleutest/letest/ole2ui/hivgares.bmp b/private/oleutest/letest/ole2ui/hivgares.bmp
new file mode 100644
index 000000000..0011166da
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/hivgares.bmp
Binary files differ
diff --git a/private/oleutest/letest/ole2ui/icon.c b/private/oleutest/letest/ole2ui/icon.c
new file mode 100644
index 000000000..048a991fe
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/icon.c
@@ -0,0 +1,857 @@
+/*
+ * ICON.C
+ *
+ * Implements the OleUIChangeIcon function which invokes the complete
+ * Change Icon dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+#include "utility.h"
+#include "icon.h"
+#include "geticon.h"
+
+/*
+ * OleUIChangeIcon
+ *
+ * Purpose:
+ * Invokes the standard OLE Change Icon dialog box allowing the user
+ * to select an icon from an icon file, executable, or DLL.
+ *
+ * Parameters:
+ * lpCI LPOLEUIChangeIcon pointing to the in-out structure
+ * for this dialog.
+ *
+ * Return Value:
+ * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
+ * an error value.
+ */
+
+STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON lpCI)
+ {
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpCI, sizeof(OLEUICHANGEICON)
+ , &hMemDlg);
+
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+#if defined( OBSOLETE )
+ if (NULL==lpCI->hMetaPict)
+ uRet=OLEUI_CIERR_MUSTHAVECURRENTMETAFILE;
+#endif
+
+ if (lpCI->dwFlags & CIF_USEICONEXE)
+ {
+ if ( (NULL == lpCI->szIconExe)
+ || (IsBadReadPtr(lpCI->szIconExe, lpCI->cchIconExe))
+ || (IsBadWritePtr(lpCI->szIconExe, lpCI->cchIconExe)) )
+ uRet = OLEUI_CIERR_SZICONEXEINVALID;
+
+ }
+
+ // REVIEW: how do we validate the CLSID?
+/*
+ if ('\0'==*((LPSTR)&lpCI->clsid))
+ uRet=OLEUI_CIERR_MUSTHAVECLSID;
+*/
+ if (OLEUI_ERR_STANDARDMIN <= uRet)
+ {
+ if (NULL!=hMemDlg)
+ FreeResource(hMemDlg);
+
+ return uRet;
+ }
+
+ //Now that we've validated everything, we can invoke the dialog.
+ return UStandardInvocation(ChangeIconDialogProc, (LPOLEUISTANDARD)lpCI
+ , hMemDlg, MAKEINTRESOURCE(IDD_CHANGEICON));
+ }
+
+
+
+
+
+/*
+ * ChangeIconDialogProc
+ *
+ * Purpose:
+ * Implements the OLE Change Icon dialog as invoked through the
+ * OleUIChangeIcon function.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ */
+
+BOOL CALLBACK EXPORT ChangeIconDialogProc(HWND hDlg, UINT iMsg
+ , WPARAM wParam, LPARAM lParam)
+ {
+ LPCHANGEICON lpCI;
+ HICON hIcon;
+ HGLOBAL hMetaPict;
+ BOOL fOK=FALSE;
+ UINT uRet=0;
+ LPTSTR psz;
+ TCHAR szTemp[OLEUI_CCHPATHMAX];
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ lpCI=(LPCHANGEICON)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
+
+ //If the hook processed the message, we're done.
+ if (0!=uRet)
+ return uRet;
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ //Insure that icons are properly destroyed.
+ SendDlgItemMessage(hDlg, ID_ICONLIST, LB_RESETCONTENT, 0, 0L);
+
+ StandardCleanup(lpCI, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ FChangeIconInit(hDlg, wParam, lParam);
+ return TRUE;
+
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpMI=(LPMEASUREITEMSTRUCT)lParam;
+
+ //All icons are system metric+padding in width and height
+ lpMI->itemWidth =GetSystemMetrics(SM_CXICON)+CXICONPAD;
+ lpMI->itemHeight=GetSystemMetrics(SM_CYICON)+CYICONPAD;
+ }
+ break;
+
+
+ case WM_DRAWITEM:
+ return FDrawListIcon((LPDRAWITEMSTRUCT)lParam);
+
+
+ case WM_DELETEITEM:
+ //Free the GDI object for the item
+ DestroyIcon((HICON)LOWORD(((LPDELETEITEMSTRUCT)lParam)->itemData));
+ break;
+
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case ID_CURRENT:
+ case ID_DEFAULT:
+ case ID_FROMFILE:
+ UpdateResultIcon(lpCI, hDlg, wID);
+ break;
+
+ case ID_LABELEDIT:
+ //When the edit loses focus, update the result display
+ if (EN_KILLFOCUS==wCode)
+ {
+ GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
+ SetDlgItemText(hDlg, ID_RESULTLABEL, szTemp);
+ }
+ break;
+
+ case ID_FROMFILEEDIT:
+ //If the text changed, remove any selection in the list.
+ GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
+
+ if (lpCI && lstrcmpi(szTemp, lpCI->szFile))
+ {
+ SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL
+ , (WPARAM)-1, 0);
+
+ //Also force selection of ID_FROMFILE
+ CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE);
+ }
+ break;
+
+
+ case ID_ICONLIST:
+ switch (wCode)
+ {
+ case LBN_SETFOCUS:
+ //If we got the focus, see about updating.
+ GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp
+ , sizeof(szTemp)/sizeof(TCHAR));
+
+ //Check if file changed and update the list if so
+ if (lpCI && 0!=lstrcmpi(szTemp, lpCI->szFile))
+ {
+ lstrcpy(lpCI->szFile, szTemp);
+ UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
+ UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
+ }
+ break;
+
+ case LBN_SELCHANGE:
+ UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
+ break;
+
+ case LBN_DBLCLK:
+ //Same as pressing OK.
+ SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
+ break;
+ }
+ break;
+
+
+ case ID_BROWSE:
+ {
+ DWORD dwOfnFlags;
+
+ /*
+ * To allow the hook to customize the browse dialog, we
+ * send OLEUI_MSG_BROWSE. If the hook returns FALSE
+ * we use the default, otherwise we trust that it retrieved
+ * a filename for us. This mechanism prevents hooks from
+ * trapping ID_BROWSE to customize the dialog and from
+ * trying to figure out what we do after we have the name.
+ */
+
+ //Copy for reference
+ LSTRCPYN(szTemp, lpCI->szFile, sizeof(szTemp)/sizeof(TCHAR));
+
+ uRet=UStandardHook(lpCI, hDlg, uMsgBrowse, OLEUI_CCHPATHMAX_SIZE
+ , (LONG)(LPSTR)lpCI->szFile);
+
+ dwOfnFlags = OFN_FILEMUSTEXIST;
+ if (lpCI->lpOCI->dwFlags & CIF_SHOWHELP)
+ dwOfnFlags |= OFN_SHOWHELP;
+
+ if (0==uRet)
+ uRet=(BOOL)Browse(hDlg, lpCI->szFile, NULL, OLEUI_CCHPATHMAX_SIZE, IDS_ICONFILTERS, dwOfnFlags);
+
+ /*
+ * Only reinitialize if the file changed, so if we got
+ * TRUE from the hook but the user hit Cancel, we don't
+ * spend time unecessarily refilling the list.
+ */
+ if (0!=uRet && 0!=lstrcmpi(szTemp, lpCI->szFile))
+ {
+ CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_FROMFILE);
+ SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile);
+ UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
+ UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
+ }
+ }
+ break;
+
+
+ case IDOK:
+ /*
+ * If the user pressed enter, compare the current file
+ * and the one we have stored. If they match, then
+ * refill the listbox instead of closing down. This is
+ * so the user can press Enter in the edit control as
+ * they would expect to be able to do.
+ */
+ GetDlgItemText(hDlg, ID_FROMFILEEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
+
+ //Check if the file changed at all.
+ if (0!=lstrcmpi(szTemp, lpCI->szFile))
+ {
+ lstrcpy(lpCI->szFile, szTemp);
+ UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile);
+ UpdateResultIcon(lpCI, hDlg, ID_FROMFILE);
+
+ //Eat this message to prevent focus change.
+ return TRUE;
+ }
+
+ // Check if the file name is valid
+ // (if FromFile is enabled)
+ if (ID_FROMFILE & lpCI->dwFlags)
+ {
+ OFSTRUCT of;
+ HWND hWnd;
+ if (HFILE_ERROR==DoesFileExist(lpCI->szFile, &of))
+ {
+ OpenFileError(hDlg, of.nErrCode, lpCI->szFile);
+ hWnd = GetDlgItem(hDlg, ID_FROMFILEEDIT);
+ SetFocus(hWnd);
+ SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ return TRUE; // eat this message
+ }
+ }
+
+ if ((HWND)LOWORD(lParam) != GetFocus())
+ SetFocus((HWND)LOWORD(lParam));
+
+ /*
+ * On closing, create a new metafilepict with the
+ * current icon and label, destroying the old structure.
+ *
+ * Since we make a copy of the icon by placing it into
+ * the metafile, we have to make sure we delete the
+ * icon in the current field. When the listbox is
+ * destroyed WM_DELETEITEMs will clean it up appropriately.
+ */
+
+ hIcon=(HICON)SendDlgItemMessage(hDlg, ID_RESULTICON
+ , STM_GETICON, 0, 0L);
+
+ /*
+ * If default is selected then we get the source
+ * information from registrion database for the
+ * current class to put in the metafile. If current
+ * is selected the we just retrieve the original file
+ * again and recreate the metafile. If from file is
+ * selected we use the current filename from the
+ * control and the current listbox selection.
+ */
+
+ psz=lpCI->szFile;
+
+ if (lpCI->dwFlags & CIF_SELECTDEFAULT)
+ {
+ psz=lpCI->szDefIconFile;
+ lpCI->iIcon=lpCI->iDefIcon;
+ hIcon=lpCI->hDefIcon;
+ }
+
+ if (lpCI->dwFlags & CIF_SELECTCURRENT)
+ {
+ //Go get the current icon source back.
+ OleUIMetafilePictExtractIconSource(lpCI->lpOCI->hMetaPict
+ , psz, &lpCI->iIcon);
+ }
+
+ if (lpCI->dwFlags & CIF_SELECTFROMFILE)
+ {
+ GetDlgItemText(hDlg, ID_FROMFILEEDIT, psz, OLEUI_CCHPATHMAX);
+
+ lpCI->iIcon=(UINT)SendDlgItemMessage(hDlg
+ , ID_ICONLIST, LB_GETCURSEL, 0, 0L);
+ }
+
+
+ //Get the label and go create the metafile
+ GetDlgItemText(hDlg, ID_LABELEDIT, szTemp, sizeof(szTemp)/sizeof(TCHAR));
+
+ //If psz is NULL (default) we get no source comments.
+
+#ifdef OLE201
+ hMetaPict=OleUIMetafilePictFromIconAndLabel(hIcon,
+ szTemp, psz, lpCI->iIcon);
+#endif
+
+ //Clean up the current icon that we extracted.
+ hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON
+ , STM_GETICON, 0, 0L);
+ DestroyIcon(hIcon);
+
+ //Clean up the default icon
+ DestroyIcon(lpCI->hDefIcon);
+
+ // Remove the prop set on our parent
+ RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG);
+
+ if (NULL==hMetaPict)
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_FALSE, 0L);
+
+ OleUIMetafilePictIconFree(lpCI->lpOCI->hMetaPict);
+ lpCI->lpOCI->hMetaPict=hMetaPict;
+
+ lpCI->lpOCI->dwFlags = lpCI->dwFlags;
+
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ break;
+
+
+ case IDCANCEL:
+ //Clean up the current icon that we extracted.
+ hIcon=(HICON)SendDlgItemMessage(hDlg, ID_CURRENTICON
+ , STM_GETICON, 0, 0L);
+ DestroyIcon(hIcon);
+
+ //Clean up the default icon
+ DestroyIcon(lpCI->hDefIcon);
+
+ // Remove the prop set on our parent
+ RemoveProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG);
+
+ //We leave hMetaPict intact on Cancel; caller's responsibility
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+
+
+ case ID_OLEUIHELP:
+ PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICON, 0));
+ break;
+ }
+ break;
+
+ default:
+ {
+ if (lpCI && iMsg == lpCI->nBrowseHelpID) {
+ PostMessage(lpCI->lpOCI->hWndOwner, uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_CHANGEICONBROWSE, 0));
+ }
+ }
+ break;
+ }
+ return FALSE;
+ }
+
+
+
+
+/*
+ * FChangeIconInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Change Icon dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FChangeIconInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+ {
+ LPCHANGEICON lpCI;
+ LPOLEUICHANGEICON lpOCI;
+ HFONT hFont;
+ HWND hList;
+ UINT cyList;
+ RECT rc, rcG;
+ UINT uID;
+
+ //1. Copy the structure at lParam into our instance memory.
+ lpCI=(LPCHANGEICON)LpvStandardInit(hDlg, sizeof(CHANGEICON), TRUE, &hFont);
+
+ //PvStandardInit send a termination to us already.
+ if (NULL==lpCI)
+ return FALSE;
+
+ //Save the original pointer and copy necessary information.
+ lpOCI=(LPOLEUICHANGEICON)lParam;
+
+ lpCI->lpOCI =lpOCI;
+ lpCI->dwFlags=lpOCI->dwFlags;
+
+ //Go extract the icon source from the metafile.
+ OleUIMetafilePictExtractIconSource(lpOCI->hMetaPict, lpCI->szFile, &lpCI->iIcon);
+
+ //Go extract the icon and the label from the metafile
+ OleUIMetafilePictExtractLabel(lpOCI->hMetaPict, lpCI->szLabel, OLEUI_CCHLABELMAX_SIZE, NULL);
+ lpCI->hCurIcon=OleUIMetafilePictExtractIcon(lpOCI->hMetaPict);
+
+ //2. If we got a font, send it to the necessary controls.
+ if (NULL!=hFont)
+ {
+ SendDlgItemMessage(hDlg, ID_RESULTLABEL, WM_SETFONT
+ , (WPARAM)hFont, 0L);
+ }
+
+
+ //3. Show or hide the help button
+ if (!(lpCI->dwFlags & CIF_SHOWHELP))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+
+ /*
+ * 4. Set text limits and initial control values. If we're given
+ * an intial label we set it in the edit and static controls.
+ * If we don't, then we copy the default contents of the static
+ * control into the edit control, meaning that only the default
+ * static control string need be localized.
+ */
+
+ SendDlgItemMessage(hDlg, ID_LABELEDIT, EM_LIMITTEXT, OLEUI_CCHLABELMAX, 0L);
+ SendDlgItemMessage(hDlg, ID_FROMFILEEDIT, EM_LIMITTEXT, OLEUI_CCHPATHMAX, 0L);
+ SetDlgItemText(hDlg, ID_FROMFILEEDIT, lpCI->szFile);
+
+ //Copy the label text into the edit and static controls.
+ SetDlgItemText(hDlg, ID_LABELEDIT, lpCI->szLabel);
+ SetDlgItemText(hDlg, ID_RESULTLABEL, lpCI->szLabel);
+
+
+ lpCI->hDefIcon = NULL;
+
+ if (lpCI->dwFlags & CIF_USEICONEXE)
+ {
+ lpCI->hDefIcon = ExtractIcon(ghInst, lpCI->lpOCI->szIconExe, 0);
+
+ if (NULL != lpCI->hDefIcon)
+ {
+ lstrcpy(lpCI->szDefIconFile, lpCI->lpOCI->szIconExe);
+ lpCI->iDefIcon = 0;
+ }
+ }
+
+
+ if (NULL == lpCI->hDefIcon)
+ {
+ HGLOBAL hMetaPict;
+
+#ifdef OLE201
+ hMetaPict = GetIconOfClass(ghInst,
+ &lpCI->lpOCI->clsid,
+ NULL,
+ TRUE);
+#endif
+
+ lpCI->hDefIcon = OleUIMetafilePictExtractIcon(hMetaPict);
+
+ OleUIMetafilePictExtractIconSource(hMetaPict,
+ lpCI->szDefIconFile,
+ &lpCI->iDefIcon);
+
+ OleUIMetafilePictIconFree(hMetaPict);
+ }
+
+
+ //Initialize all the icon displays.
+ SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_SETICON
+ , (WPARAM)lpCI->hCurIcon, 0L);
+ SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_SETICON
+ , (WPARAM)lpCI->hDefIcon, 0L);
+ SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON
+ , (WPARAM)lpCI->hCurIcon, 0L);
+
+
+ /*
+ * 5. Since we cannot predict the size of icons on any display,
+ * we have to resize the icon listbox to the size of an icon
+ * (plus padding), a scrollbar, and two borders (top & bottom).
+ */
+ cyList=GetSystemMetrics(SM_CYICON)+GetSystemMetrics(SM_CYHSCROLL)
+ +GetSystemMetrics(SM_CYBORDER)*2+CYICONPAD;
+
+ hList=GetDlgItem(hDlg, ID_ICONLIST);
+ GetClientRect(hList, &rc);
+ SetWindowPos(hList, NULL, 0, 0, rc.right, cyList
+ , SWP_NOMOVE | SWP_NOZORDER);
+
+ //Set the columns in this multi-column listbox to hold one icon
+ SendMessage(hList, LB_SETCOLUMNWIDTH
+ , GetSystemMetrics(SM_CXICON)+CXICONPAD,0L);
+
+ /*
+ * 5a. If the listbox expanded below the group box, then size
+ * the groupbox down, move the label static and exit controls
+ * down, and expand the entire dialog appropriately.
+ */
+
+ GetWindowRect(hList, &rc);
+ GetWindowRect(GetDlgItem(hDlg, ID_GROUP), &rcG);
+
+ if (rc.bottom > rcG.bottom)
+ {
+ //Calculate amount to move things down.
+ cyList=(rcG.bottom-rcG.top)-(rc.bottom-rc.top-cyList);
+
+ //Expand the group box.
+ rcG.right -=rcG.left;
+ rcG.bottom-=rcG.top;
+ SetWindowPos(GetDlgItem(hDlg, ID_GROUP), NULL, 0, 0
+ , rcG.right, rcG.bottom+cyList
+ , SWP_NOMOVE | SWP_NOZORDER);
+
+ //Expand the dialog box.
+ GetClientRect(hDlg, &rc);
+ SetWindowPos(hDlg, NULL, 0, 0, rc.right, rc.bottom+cyList
+ , SWP_NOMOVE | SWP_NOZORDER);
+
+ //Move the label and edit controls down.
+ GetClientRect(GetDlgItem(hDlg, ID_LABEL), &rc);
+ SetWindowPos(GetDlgItem(hDlg, ID_LABEL), NULL, 0, cyList
+ , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER);
+
+ GetClientRect(GetDlgItem(hDlg, ID_LABELEDIT), &rc);
+ SetWindowPos(GetDlgItem(hDlg, ID_LABELEDIT), NULL, 0, cyList
+ , rc.right, rc.bottom, SWP_NOSIZE | SWP_NOZORDER);
+ }
+
+
+ /*
+ * 6. Select Current, Default, or From File radiobuttons appropriately.
+ * The CheckRadioButton call sends WM_COMMANDs which handle
+ * other actions. Note that if we check From File, which
+ * takes an icon from the list, we better fill the list.
+ * This will also fill the list even if default is selected.
+ */
+
+ if (0!=UFillIconList(hDlg, ID_ICONLIST, lpCI->szFile))
+ {
+ //If szFile worked, then select the source icon in the listbox.
+ SendDlgItemMessage(hDlg, ID_ICONLIST, LB_SETCURSEL, lpCI->iIcon, 0L);
+ }
+
+
+ if (lpCI->dwFlags & CIF_SELECTCURRENT)
+ CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, ID_CURRENT);
+ else
+ {
+ uID=(lpCI->dwFlags & CIF_SELECTFROMFILE) ? ID_FROMFILE : ID_DEFAULT;
+ CheckRadioButton(hDlg, ID_CURRENT, ID_FROMFILE, uID);
+ }
+
+ //7. Give our parent window access to our hDlg (via a special SetProp).
+ // The PasteSpecial dialog may need to force our dialog down if the
+ // clipboard contents change underneath it. if so it will send
+ // us a IDCANCEL command.
+ SetProp(lpCI->lpOCI->hWndOwner, PROP_HWND_CHGICONDLG, hDlg);
+
+ lpCI->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
+
+ //8. Call the hook with lCustData in lParam
+ UStandardHook(lpCI, hDlg, WM_INITDIALOG, wParam, lpOCI->lCustData);
+ return TRUE;
+ }
+
+
+
+
+
+/*
+ * UFillIconList
+ *
+ * Purpose:
+ * Given a listbox and a filename, attempts to open that file and
+ * read all the icons that exist therein, adding them to the listbox
+ * hList as owner-draw items. If the file does not exist or has no
+ * icons, then you get no icons and an appropriate warning message.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog containing the listbox.
+ * idList UINT identifier of the listbox to fill.
+ * pszFile LPSTR of the file from which to extract icons.
+ *
+ * Return Value:
+ * UINT Number of items added to the listbox. 0 on failure.
+ */
+
+UINT UFillIconList(HWND hDlg, UINT idList, LPTSTR pszFile)
+ {
+ HWND hList;
+ UINT i;
+ UINT cIcons=0;
+ HCURSOR hCur;
+ HICON hIcon;
+ OFSTRUCT of;
+
+ if (NULL==hDlg || !IsWindow(hDlg) || NULL==pszFile)
+ return 0;
+
+ hList=GetDlgItem(hDlg, idList);
+
+ if (NULL==hList)
+ return 0;
+
+ //Clean out the listbox.
+ SendMessage(hList, LB_RESETCONTENT, 0, 0L);
+
+ //If we have an empty string, just exit leaving the listbox empty as well
+ if (0==lstrlen(pszFile))
+ return 0;
+
+ //Turn on the hourglass
+ hCur=HourGlassOn();
+
+ //Check if the file is valid.
+ if (HFILE_ERROR!=DoesFileExist(pszFile, &of))
+ {
+ #ifdef EXTRACTICONWORKS
+ //Get the icon count for this file.
+ cIcons=(UINT)ExtractIcon(ghInst, pszFile, (UINT)-1);
+ #else
+ /*
+ * ExtractIcon in Windows 3.1 with -1 eats a selector, leaving an
+ * extra global memory object around for this applciation. Since
+ * changing icons may happen very often with all OLE apps in
+ * the system, we have to work around it. So we'll say we
+ * have lots of icons and just call ExtractIcon until it
+ * fails. We check if there's any around by trying to get
+ * the first one.
+ */
+ cIcons=0xFFFF;
+
+ hIcon=ExtractIcon(ghInst, pszFile, 0);
+
+ //Fake a failure with cIcons=0, or cleanup hIcon from this test.
+ if (32 > (UINT)hIcon)
+ cIcons=0;
+ else
+ DestroyIcon(hIcon);
+ #endif
+
+ if (0!=cIcons)
+ {
+ SendMessage(hList, WM_SETREDRAW, FALSE, 0L);
+
+ for (i=0; i<cIcons; i++)
+ {
+ hIcon=ExtractIcon(ghInst, pszFile, i);
+
+ if (32 < (UINT)hIcon)
+ SendMessage(hList, LB_ADDSTRING, 0, (LONG)(UINT)hIcon);
+ #ifndef EXTRACTICONWORKS
+ else
+ {
+ //ExtractIcon failed, so let's leave now.
+ break;
+ }
+ #endif
+ }
+
+ //Force complete repaint
+ SendMessage(hList, WM_SETREDRAW, TRUE, 0L);
+ InvalidateRect(hList, NULL, TRUE);
+
+ //Select an icon
+ SendMessage(hList, LB_SETCURSEL, 0, 0L);
+ }
+ else
+ ErrorWithFile(hDlg, ghInst, IDS_CINOICONSINFILE, pszFile, MB_OK);
+ }
+ else
+ OpenFileError(hDlg, of.nErrCode, pszFile);
+
+ HourGlassOff(hCur);
+ return cIcons;
+ }
+
+
+
+
+/*
+ * FDrawListIcon
+ *
+ * Purpose:
+ * Handles WM_DRAWITEM for the icon listbox.
+ *
+ * Parameters:
+ * lpDI LPDRAWITEMSTRUCT from WM_DRAWITEM
+ *
+ * Return Value:
+ * BOOL TRUE if we did anything, FALSE if there are no items
+ * in the list.
+ */
+
+BOOL FDrawListIcon(LPDRAWITEMSTRUCT lpDI)
+ {
+ COLORREF cr;
+
+ /*
+ * If there are no items in the list, then itemID is negative according
+ * to the Win3.1 SDK. Unfortunately DRAWITEMSTRUCT has an unsigned int
+ * for this field, so we need the typecast to do a signed comparison.
+ */
+ if ((int)lpDI->itemID < 0)
+ return FALSE;
+
+ /*
+ * For selection or draw entire case we just draw the entire item all
+ * over again. For focus cases, we only call DrawFocusRect.
+ */
+
+ if (lpDI->itemAction & (ODA_SELECT | ODA_DRAWENTIRE))
+ {
+ //Clear background and draw the icon.
+ if (lpDI->itemState & ODS_SELECTED)
+ cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_HIGHLIGHT));
+ else
+ cr=SetBkColor(lpDI->hDC, GetSysColor(COLOR_WINDOW));
+
+ //Draw a cheap rectangle.
+ ExtTextOut(lpDI->hDC, 0, 0, ETO_OPAQUE, &lpDI->rcItem
+ , NULL, 0, NULL);
+
+ DrawIcon(lpDI->hDC, lpDI->rcItem.left+(CXICONPAD/2)
+ , lpDI->rcItem.top+(CYICONPAD/2)
+ , (HICON)LOWORD(lpDI->itemData));
+
+ //Restore original background for DrawFocusRect
+ SetBkColor(lpDI->hDC, cr);
+ }
+
+ //Always change focus on the focus action.
+ if (lpDI->itemAction & ODA_FOCUS || lpDI->itemState & ODS_FOCUS)
+ DrawFocusRect(lpDI->hDC, &lpDI->rcItem);
+
+ return TRUE;
+ }
+
+
+
+
+
+/*
+ * UpdateResultIcon
+ *
+ * Purpose:
+ * Updates the result icon using the current icon in the default display
+ * or the icon listbox depending on fFromDefault.
+ *
+ * Parameters:
+ * lpCI LPCHANGEICON containing dialog flags.
+ * hDlg HWND of the dialog
+ * uID UINT identifying the radiobutton selected.
+ *
+ * Return Value:
+ * None
+ */
+
+void UpdateResultIcon(LPCHANGEICON lpCI, HWND hDlg, UINT uID)
+ {
+ UINT iSel;
+ LONG lTemp=LB_ERR;
+
+ lpCI->dwFlags &= ~(CIF_SELECTCURRENT | CIF_SELECTDEFAULT | CIF_SELECTFROMFILE);
+
+ switch (uID)
+ {
+ case ID_CURRENT:
+ lTemp=SendDlgItemMessage(hDlg, ID_CURRENTICON, STM_GETICON, 0, 0L);
+ lpCI->dwFlags |= CIF_SELECTCURRENT;
+ break;
+
+ case ID_DEFAULT:
+ lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L);
+ lpCI->dwFlags |= CIF_SELECTDEFAULT;
+ break;
+
+ case ID_FROMFILE:
+ //Get the selected icon from the list and place it in the result
+ lpCI->dwFlags |= CIF_SELECTFROMFILE;
+
+ iSel=(UINT)SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETCURSEL, 0, 0L);
+ if ((UINT)LB_ERR==iSel)
+ lTemp=SendDlgItemMessage(hDlg, ID_DEFAULTICON, STM_GETICON, 0, 0L);
+ else
+ SendDlgItemMessage(hDlg, ID_ICONLIST, LB_GETTEXT, iSel
+ , (LPARAM)(LPLONG)&lTemp);
+
+ break;
+ }
+
+ if ((LONG)LB_ERR!=lTemp)
+ SendDlgItemMessage(hDlg, ID_RESULTICON, STM_SETICON, LOWORD(lTemp), 0L);
+ return;
+ }
+
+
diff --git a/private/oleutest/letest/ole2ui/icon.dlg b/private/oleutest/letest/ole2ui/icon.dlg
new file mode 100644
index 000000000..43a2f274c
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/icon.dlg
@@ -0,0 +1,48 @@
+// DLGINCLUDE RCDATA DISCARDABLE
+// BEGIN
+// "OLE2UI.H\0"
+// END
+
+
+IDD_CHANGEICON DIALOG 18, 18, 261, 152
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Change Icon"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX "Icon", ID_GROUP, 4, 6, 180, 124
+ CONTROL "&Current", ID_CURRENT, "Button", BS_AUTORADIOBUTTON |
+ WS_GROUP , 10, 19, 46, 10
+
+ CONTROL "&Default", ID_DEFAULT, "Button", BS_AUTORADIOBUTTON,
+ 10, 44, 46, 10
+
+ CONTROL "&From File:", ID_FROMFILE, "Button", BS_AUTORADIOBUTTON,
+ 10, 68, 46, 10
+
+ ICON "", ID_CURRENTICON, 58, 15, 18, 20
+
+ ICON "", ID_DEFAULTICON, 58, 40, 18, 20
+
+ EDITTEXT ID_FROMFILEEDIT, 58, 68, 119, 12, ES_LOWERCASE |
+ ES_AUTOHSCROLL | WS_GROUP | ES_OEMCONVERT
+
+ LISTBOX ID_ICONLIST, 58, 84, 119, 40, LBS_OWNERDRAWFIXED |
+ LBS_NOINTEGRALHEIGHT | LBS_MULTICOLUMN | WS_HSCROLL |
+ WS_TABSTOP
+
+ LTEXT "&Label:", ID_LABEL, 6, 138, 32, 8
+
+ EDITTEXT ID_LABELEDIT, 38, 136, 146, 12, ES_AUTOHSCROLL
+
+ DEFPUSHBUTTON "OK", IDOK, 189, 6, 66, 14
+
+ PUSHBUTTON "Cancel", IDCANCEL, 189, 23, 66, 14
+
+ PUSHBUTTON "&Browse...", ID_BROWSE, 189, 41, 66, 14
+
+ PUSHBUTTON "&Help", ID_OLEUIHELP, 189, 59, 66, 14
+
+ CTEXT "", ID_RESULTLABEL, 193, 114, 63, 24
+ ICON "", ID_RESULTICON, 214, 90, 18, 20
+END
+
diff --git a/private/oleutest/letest/ole2ui/icon.h b/private/oleutest/letest/ole2ui/icon.h
new file mode 100644
index 000000000..512155949
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/icon.h
@@ -0,0 +1,59 @@
+/*
+ * ICON.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Change Icon dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _ICON_H_
+#define _ICON_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING ICON.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+#define CXICONPAD 12
+#define CYICONPAD 4
+
+// Property used by ChangeIcon dialog to give its parent window access to
+// its hDlg. The PasteSpecial dialog may need to force the ChgIcon dialog
+// down if the clipboard contents change underneath it. if so it will send
+// a IDCANCEL command to the ChangeIcon dialog.
+#define PROP_HWND_CHGICONDLG TEXT("HWND_CIDLG")
+
+//Internally used structure
+typedef struct tagCHANGEICON
+ {
+ LPOLEUICHANGEICON lpOCI; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+ DWORD dwFlags;
+ HICON hCurIcon;
+ TCHAR szLabel[OLEUI_CCHLABELMAX+1];
+ TCHAR szFile[OLEUI_CCHPATHMAX];
+ UINT iIcon;
+ HICON hDefIcon;
+ TCHAR szDefIconFile[OLEUI_CCHPATHMAX];
+ UINT iDefIcon;
+ UINT nBrowseHelpID; // Help ID callback for Browse dlg
+ } CHANGEICON, *PCHANGEICON, FAR *LPCHANGEICON;
+
+
+//Internal function prototypes
+//ICON.C
+BOOL CALLBACK EXPORT ChangeIconDialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL FChangeIconInit(HWND, WPARAM, LPARAM);
+UINT UFillIconList(HWND, UINT, LPTSTR);
+BOOL FDrawListIcon(LPDRAWITEMSTRUCT);
+void UpdateResultIcon(LPCHANGEICON, HWND, UINT);
+
+
+#endif //_ICON_H_
diff --git a/private/oleutest/letest/ole2ui/iconbox.c b/private/oleutest/letest/ole2ui/iconbox.c
new file mode 100644
index 000000000..8422f5dcc
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/iconbox.c
@@ -0,0 +1,253 @@
+/*
+ * ICONBOX.C
+ *
+ * Implemenatation of an IconBox control for OLE 2.0 UI dialogs that we'll
+ * use wherever a dialog needs an icon/label display. Through the control's
+ * interface we can change the image or control label visibility.
+ *
+ * The IconBox discusses images in CF_METAFILEPICT format. When drawing
+ * such a metafile, the entire aspect is centered in the IconBox, so long
+ * labels are chopped at either end.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "iconbox.h"
+
+
+//Flag indicating if we've registered the class
+static BOOL fRegistered=FALSE;
+
+
+/*
+ * FIconBoxInitialize
+ *
+ * Purpose:
+ * Registers the IconBox control class.
+ *
+ * Parameters:
+ * hInst HINSTANCE instance of the DLL.
+ *
+ * hPrevInst HINSTANCE of the previous instance. Used to
+ * determine whether to register window classes or not.
+ *
+ * lpszClassName LPSTR containing the class name to register the
+ * IconBox control class with.
+ *
+ * Return Value:
+ * BOOL TRUE if all initialization succeeded, FALSE otherwise.
+ */
+
+BOOL FIconBoxInitialize(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszClassName)
+ {
+ WNDCLASS wc;
+
+ // Only register class if we're the first instance
+ if (hPrevInst)
+ fRegistered = TRUE;
+ else
+ {
+
+ // Static flag fRegistered guards against calling this function more
+ // than once
+ if (!fRegistered)
+ {
+ wc.lpfnWndProc =IconBoxWndProc;
+ wc.cbClsExtra =0;
+ wc.cbWndExtra =CBICONBOXWNDEXTRA;
+ wc.hInstance =hInst;
+ wc.hIcon =NULL;
+ wc.hCursor =LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground =(HBRUSH)NULL;
+ wc.lpszMenuName =NULL;
+ wc.lpszClassName =lpszClassName;
+ wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
+
+ fRegistered=RegisterClass(&wc);
+ }
+ }
+
+ return fRegistered;
+}
+
+
+/*
+ * IconBoxUninitialize
+ *
+ * Purpose:
+ * Cleans up anything done in FIconBoxInitialize. Currently there is
+ * nothing, but we do this for symmetry.
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * None
+ */
+
+void IconBoxUninitialize(void)
+ {
+ //Nothing to do.
+ return;
+ }
+
+
+
+
+
+
+/*
+ * IconBoxWndProc
+ *
+ * Purpose:
+ * Window Procedure for the IconBox custom control. Only handles
+ * WM_CREATE, WM_PAINT, and private messages to manipulate the image.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ */
+
+LONG CALLBACK EXPORT IconBoxWndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
+ {
+ HGLOBAL hMF=NULL;
+ PAINTSTRUCT ps;
+ HDC hDC;
+ RECT rc;
+
+
+ //Handle standard Windows messages.
+ switch (iMsg)
+ {
+ case WM_CREATE:
+ SetWindowLong(hWnd, IBWW_HIMAGE, 0);
+ SetWindowWord(hWnd, IBWW_FLABEL, TRUE);
+ return 0L;
+
+
+ case WM_ERASEBKGND:
+ {
+
+ HBRUSH hBrush;
+ RECT Rect;
+#if defined( WIN32 )
+ POINT point;
+#endif
+
+ GetClientRect(hWnd, &Rect);
+#if defined( WIN32 )
+ hBrush = (HBRUSH)SendMessage(GetParent(hWnd),
+ WM_CTLCOLORDLG,
+ wParam,
+ (LPARAM)GetParent(hWnd));
+#else
+ hBrush = (HBRUSH)SendMessage(GetParent(hWnd),
+ WM_CTLCOLOR,
+ wParam,
+ MAKELPARAM(GetParent(hWnd), CTLCOLOR_DLG));
+#endif
+
+
+ if (!hBrush)
+ return FALSE;
+
+ UnrealizeObject(hBrush);
+
+#if defined( WIN32 )
+ SetBrushOrgEx((HDC)wParam, 0, 0, &point);
+#else
+ SetBrushOrg((HDC)wParam, 0, 0);
+#endif
+
+ FillRect((HDC)wParam, &Rect, hBrush);
+
+ return TRUE;
+ }
+
+
+ case WM_PAINT:
+ hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE);
+
+ //BeginPaint and EndPaint clear us even if hMF is NULL.
+ hDC=BeginPaint(hWnd, &ps);
+
+ if (NULL!=hMF)
+ {
+ BOOL fLabel;
+
+ //Now we get to paint the metafile, centered in our rect.
+ GetClientRect(hWnd, &rc);
+
+ /*
+ * If we're doing icon only, then place the metafile
+ * at the center of our box minus half the icon width.
+ * Top is top.
+ */
+
+ fLabel=GetWindowWord(hWnd, IBWW_FLABEL);
+
+
+ //Go draw where we decided to place it.
+ OleUIMetafilePictIconDraw(hDC, &rc, hMF, !fLabel);
+ }
+
+ EndPaint(hWnd, &ps);
+ break;
+
+
+ case IBXM_IMAGESET:
+ /*
+ * wParam contains the new handle.
+ * lParam is a flag to delete the old or not.
+ */
+ hMF=(HGLOBAL)SetWindowLong(hWnd, IBWW_HIMAGE, wParam);
+ InvalidateRect(hWnd, NULL, TRUE);
+ UpdateWindow(hWnd);
+
+ //Delete the old handle if requested
+ if (0L!=lParam)
+ {
+ OleUIMetafilePictIconFree(hMF);
+ hMF=NULL;
+ }
+
+ return (LONG)(UINT)hMF;
+
+
+ case IBXM_IMAGEGET:
+ //Return the current index.
+ hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE);
+ return (LONG)(UINT)hMF;
+
+
+ case IBXM_IMAGEFREE:
+ //Free up whatever we're holding.
+ hMF=(HGLOBAL)GetWindowLong(hWnd, IBWW_HIMAGE);
+ OleUIMetafilePictIconFree(hMF);
+ return 1L;
+
+
+ case IBXM_LABELENABLE:
+ //wParam has the new flag, returns the previous flag.
+ return (LONG)SetWindowWord(hWnd, IBWW_FLABEL, (WORD)wParam);
+
+
+ default:
+ return DefWindowProc(hWnd, iMsg, wParam, lParam);
+ }
+
+ return 0L;
+ }
+
+
+
+
+
+
+
+
diff --git a/private/oleutest/letest/ole2ui/iconbox.h b/private/oleutest/letest/ole2ui/iconbox.h
new file mode 100644
index 000000000..057b59e75
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/iconbox.h
@@ -0,0 +1,31 @@
+/*
+ * ICONBOX.H
+ *
+ * Structures and definitions for the IconBox control.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _ICONBOX_H_
+#define _ICONBOX_H_
+
+//Function prototypes
+BOOL FIconBoxInitialize(HINSTANCE, HINSTANCE, LPTSTR);
+void IconBoxUninitialize(void);
+LONG CALLBACK EXPORT IconBoxWndProc(HWND, UINT, WPARAM, LPARAM);
+
+
+//Window extra bytes contain the bitmap index we deal with currently.
+#define CBICONBOXWNDEXTRA (sizeof(HGLOBAL)+sizeof(BOOL))
+#define IBWW_HIMAGE 0
+#define IBWW_FLABEL (sizeof(HGLOBAL))
+
+//Control messages
+#define IBXM_IMAGESET (WM_USER+0)
+#define IBXM_IMAGEGET (WM_USER+1)
+#define IBXM_IMAGEFREE (WM_USER+2)
+#define IBXM_LABELENABLE (WM_USER+3)
+
+
+#endif //_ICONBOX_H_
diff --git a/private/oleutest/letest/ole2ui/insobj.c b/private/oleutest/letest/ole2ui/insobj.c
new file mode 100644
index 000000000..53fa094c9
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/insobj.c
@@ -0,0 +1,1724 @@
+/*
+ * INSOBJ.C
+ *
+ * Implements the OleUIInsertObject function which invokes the complete
+ * Insert Object dialog. Makes use of the OleChangeIcon function in
+ * ICON.C.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include <commdlg.h>
+#include <memory.h>
+#include <direct.h>
+#include <malloc.h>
+#include <dos.h>
+#include <stdlib.h>
+#include "common.h"
+#include "utility.h"
+#include "icon.h"
+#include "insobj.h"
+#include "resimage.h"
+#include "iconbox.h"
+#include "geticon.h"
+
+#define IS_FILENAME_DELIM(c) ( (c) == TEXT('\\') || (c) == TEXT('/') || (c) == TEXT(':') )
+
+/*
+ * OleUIInsertObject
+ *
+ * Purpose:
+ * Invokes the standard OLE Insert Object dialog box allowing the
+ * user to select an object source and classname as well as the option
+ * to display the object as itself or as an icon.
+ *
+ * Parameters:
+ * lpIO LPOLEUIINSERTOBJECT pointing to the in-out structure
+ * for this dialog.
+ *
+ * Return Value:
+ * UINT OLEUI_SUCCESS or OLEUI_OK if all is well, otherwise
+ * an error value.
+ */
+
+STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT lpIO)
+ {
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+ HRESULT hrErr;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpIO, sizeof(OLEUIINSERTOBJECT)
+ , &hMemDlg);
+
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+ //Now we can do Insert Object specific validation.
+
+
+ // NULL is NOT valid for lpszFile
+ if ( (NULL == lpIO->lpszFile)
+ || (IsBadReadPtr(lpIO->lpszFile, lpIO->cchFile))
+ || (IsBadWritePtr(lpIO->lpszFile, lpIO->cchFile)) )
+ uRet=OLEUI_IOERR_LPSZFILEINVALID;
+
+ if (NULL != lpIO->lpszFile
+ && (lpIO->cchFile <= 0 || lpIO->cchFile > OLEUI_CCHPATHMAX_SIZE))
+ uRet=OLEUI_IOERR_CCHFILEINVALID;
+
+ if (0!=lpIO->cClsidExclude)
+ {
+ if (NULL!=lpIO->lpClsidExclude && IsBadReadPtr(lpIO->lpClsidExclude
+ , lpIO->cClsidExclude*sizeof(CLSID)))
+ uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
+ }
+
+ //If we have flags to create any object, validate necessary data.
+ if (lpIO->dwFlags & (IOF_CREATENEWOBJECT | IOF_CREATEFILEOBJECT | IOF_CREATELINKOBJECT))
+ {
+ if (NULL!=lpIO->lpFormatEtc
+ && IsBadReadPtr(lpIO->lpFormatEtc, sizeof(FORMATETC)))
+ uRet=OLEUI_IOERR_LPFORMATETCINVALID;
+
+ if (NULL!=lpIO->ppvObj && IsBadWritePtr(lpIO->ppvObj, sizeof(LPVOID)))
+ uRet=OLEUI_IOERR_PPVOBJINVALID;
+
+ if (NULL!=lpIO->lpIOleClientSite
+ && IsBadReadPtr(lpIO->lpIOleClientSite->lpVtbl, sizeof(IOleClientSiteVtbl)))
+ uRet=OLEUI_IOERR_LPIOLECLIENTSITEINVALID;
+
+ if (NULL!=lpIO->lpIStorage
+ && IsBadReadPtr(lpIO->lpIStorage->lpVtbl, sizeof(IStorageVtbl)))
+ uRet=OLEUI_IOERR_LPISTORAGEINVALID;
+ }
+
+ if (OLEUI_ERR_STANDARDMIN <= uRet)
+ {
+ if (NULL!=hMemDlg)
+ FreeResource(hMemDlg);
+
+ return uRet;
+ }
+
+ //Now that we've validated everything, we can invoke the dialog.
+ uRet=UStandardInvocation(InsertObjectDialogProc, (LPOLEUISTANDARD)lpIO
+ , hMemDlg, MAKEINTRESOURCE(IDD_INSERTOBJECT));
+
+
+ //Stop here if we cancelled or had an error.
+ if (OLEUI_SUCCESS !=uRet && OLEUI_OK!=uRet)
+ return uRet;
+
+
+ /*
+ * If any of the flags specify that we're to create objects on return
+ * from this dialog, then do so. If we encounter an error in this
+ * processing, we return OLEUI_IOERR_SCODEHASERROR. Since the
+ * three select flags are mutually exclusive, we don't have to
+ * if...else here, just if each case (keeps things cleaner that way).
+ */
+
+ lpIO->sc=S_OK;
+
+ //Check if Create New was selected and we have IOF_CREATENEWOBJECT
+ if ((lpIO->dwFlags & IOF_SELECTCREATENEW) && (lpIO->dwFlags & IOF_CREATENEWOBJECT))
+ {
+ hrErr=OleCreate(&lpIO->clsid, &lpIO->iid, lpIO->oleRender
+ , lpIO->lpFormatEtc, lpIO->lpIOleClientSite, lpIO->lpIStorage
+ , lpIO->ppvObj);
+ lpIO->sc = GetScode(hrErr);
+ }
+
+ //Try Create From File
+ if ((lpIO->dwFlags & IOF_SELECTCREATEFROMFILE))
+ {
+ if (!(lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATEFILEOBJECT))
+ {
+ hrErr=OleCreateFromFileA(&CLSID_NULL, lpIO->lpszFile, &lpIO->iid
+ , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite
+ , lpIO->lpIStorage, lpIO->ppvObj);
+ lpIO->sc = GetScode(hrErr);
+ }
+
+ if ((lpIO->dwFlags & IOF_CHECKLINK) && (lpIO->dwFlags & IOF_CREATELINKOBJECT))
+ {
+ hrErr=OleCreateLinkToFileA(lpIO->lpszFile, &lpIO->iid
+ , lpIO->oleRender, lpIO->lpFormatEtc, lpIO->lpIOleClientSite
+ , lpIO->lpIStorage, lpIO->ppvObj);
+ lpIO->sc = GetScode(hrErr);
+ }
+ }
+
+ //If we tried but failed a create option, then return the appropriate error
+ if (S_OK!=lpIO->sc)
+ uRet=OLEUI_IOERR_SCODEHASERROR;
+
+ return uRet;
+ }
+
+
+
+
+
+/*
+ * InsertObjectDialogProc
+ *
+ * Purpose:
+ * Implements the OLE Insert Object dialog as invoked through the
+ * OleUIInsertObject function.
+ */
+
+BOOL CALLBACK EXPORT InsertObjectDialogProc(HWND hDlg, UINT iMsg
+ , WPARAM wParam, LPARAM lParam)
+ {
+ LPOLEUIINSERTOBJECT lpOIO;
+ LPINSERTOBJECT lpIO;
+ OLEUICHANGEICON ci;
+ UINT i;
+ BOOL fCheck=FALSE;
+ UINT uRet=0;
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ lpIO=(LPINSERTOBJECT)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
+
+ //If the hook processed the message, we're done.
+ if (0!=uRet)
+ return (BOOL)uRet;
+
+ //Process help message from Change Icon
+ if (iMsg==uMsgHelp)
+ {
+ PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp, wParam, lParam);
+ return FALSE;
+ }
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ InsertObjectCleanup(hDlg);
+ StandardCleanup(lpIO, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ return FInsertObjectInit(hDlg, wParam, lParam);
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case ID_IO_CREATENEW:
+ FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATENEW);
+ break;
+
+ case ID_IO_CREATEFROMFILE:
+ FToggleObjectSource(hDlg, lpIO, IOF_SELECTCREATEFROMFILE);
+ break;
+
+ case ID_IO_LINKFILE:
+ fCheck=IsDlgButtonChecked(hDlg, wID);
+
+ if (fCheck)
+ lpIO->dwFlags |=IOF_CHECKLINK;
+ else
+ lpIO->dwFlags &=~IOF_CHECKLINK;
+
+ //Results change here, so be sure to update it.
+ SetInsertObjectResults(hDlg, lpIO);
+ UpdateClassIcon(hDlg, lpIO, NULL);
+ break;
+
+ case ID_IO_OBJECTTYPELIST:
+ switch (wCode)
+ {
+ case LBN_SELCHANGE:
+ UpdateClassIcon(hDlg, lpIO, hWndMsg);
+ SetInsertObjectResults(hDlg, lpIO);
+ break;
+
+ case LBN_DBLCLK:
+ //Same as pressing OK.
+ SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
+ break;
+ }
+ break;
+
+
+ case ID_IO_FILEDISPLAY:
+ //If there are characters, enable OK and Display As Icon
+ if (EN_CHANGE==wCode)
+ {
+ lpIO->fFileDirty = TRUE;
+ lpIO->fFileValid = FALSE;
+
+ lpIO->fFileSelected=
+ (0L!=SendMessage(hWndMsg, EM_LINELENGTH, 0, 0L));
+ EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), lpIO->fFileSelected);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), lpIO->fFileSelected);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), lpIO->fFileSelected);
+ EnableWindow(GetDlgItem(hDlg, IDOK), lpIO->fFileSelected);
+ }
+
+ if (EN_KILLFOCUS==wCode && NULL!=lpIO)
+ {
+ if (FValidateInsertFile(hDlg,FALSE,&lpIO->nErrCode)) {
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = TRUE;
+ UpdateClassIcon(hDlg, lpIO, NULL);
+ UpdateClassType(hDlg, lpIO, TRUE);
+ } else {
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = FALSE;
+ UpdateClassType(hDlg, lpIO, FALSE);
+ }
+ }
+ break;
+
+
+ case ID_IO_DISPLAYASICON:
+ fCheck=IsDlgButtonChecked(hDlg, wID);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fCheck);
+
+ if (fCheck)
+ lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
+ else
+ lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
+
+ //Update the internal flag based on this checking
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ lpIO->fAsIconNew=fCheck;
+ else
+ lpIO->fAsIconFile=fCheck;
+
+ //Re-read the class icon on Display checked
+ if (fCheck)
+ {
+ if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
+ {
+ if (FValidateInsertFile(hDlg, TRUE,&lpIO->nErrCode))
+ {
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = TRUE;
+ UpdateClassIcon(hDlg, lpIO,
+ GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
+
+ UpdateClassType(hDlg, lpIO, TRUE);
+ }
+
+ else
+ {
+ HWND hWndEC;
+
+ lpIO->fAsIconFile= FALSE;
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = FALSE;
+ SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, 0, 0L);
+ UpdateClassType(hDlg, lpIO, FALSE);
+
+ lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, 0);
+
+ hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
+ SetFocus(hWndEC);
+ SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ return TRUE;
+ }
+ }
+ else
+ UpdateClassIcon(hDlg, lpIO,
+ GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
+ }
+
+
+ //Results change here, so be sure to update it.
+ SetInsertObjectResults(hDlg, lpIO);
+
+
+ /*
+ * Show or hide controls as appropriate. Do the icon
+ * display last because it will take some time to repaint.
+ * If we do it first then the dialog looks too sluggish.
+ */
+ i=(fCheck) ? SW_SHOWNORMAL : SW_HIDE;
+ StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i);
+ StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i);
+
+ break;
+
+
+ case ID_IO_CHANGEICON:
+ {
+
+ LPMALLOC pIMalloc;
+ HWND hList;
+ LPTSTR pszString, pszCLSID;
+
+ int iCurSel;
+
+ // if we're in SELECTCREATEFROMFILE mode, then we need to Validate
+ // the contents of the edit control first.
+
+ if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
+ {
+ if ( lpIO->fFileDirty
+ && !FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode) )
+ {
+ HWND hWndEC;
+
+ lpIO->fFileDirty = TRUE;
+ hWndEC = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
+ SetFocus(hWndEC);
+ SendMessage(hWndEC, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ return TRUE;
+ }
+ else
+ lpIO->fFileDirty = FALSE;
+ }
+
+
+
+ //Initialize the structure for the hook.
+ _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
+
+ ci.hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg
+ , ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
+
+ ci.cbStruct =sizeof(ci);
+ ci.hWndOwner=hDlg;
+ ci.dwFlags =CIF_SELECTCURRENT;
+
+ if (lpIO->dwFlags & IOF_SHOWHELP)
+ ci.dwFlags |= CIF_SHOWHELP;
+
+
+
+
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ // Initialize clsid...
+ if (NOERROR != CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ return FALSE;
+
+ pszString = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc,
+ OLEUI_CCHKEYMAX_SIZE +
+ OLEUI_CCHCLSIDSTRING_SIZE);
+
+
+ hList = GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
+ iCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+ SendMessage(hList, LB_GETTEXT, iCurSel, (LONG)pszString);
+
+ pszCLSID = PointerToNthField(pszString, 2, TEXT('\t'));
+
+ CLSIDFromStringA((LPTSTR)pszCLSID, (LPCLSID)&(ci.clsid));
+
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszString);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ }
+ else // IOF_SELECTCREATEFROMFILE
+ {
+
+ TCHAR szFileName[OLEUI_CCHPATHMAX];
+
+ GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX);
+
+ if (NOERROR != GetClassFileA(szFileName, (LPCLSID)&(ci.clsid)))
+ {
+ LPTSTR lpszExtension;
+ int istrlen;
+
+ istrlen = lstrlen(szFileName);
+
+ lpszExtension = (LPTSTR)szFileName + istrlen -1;
+
+ while ( (lpszExtension > szFileName) &&
+ (*lpszExtension != TEXT('.')) )
+ lpszExtension--;
+
+ GetAssociatedExecutable(lpszExtension, (LPTSTR)ci.szIconExe);
+ ci.cchIconExe = lstrlen(ci.szIconExe);
+ ci.dwFlags |= CIF_USEICONEXE;
+
+ }
+ }
+
+
+ //Let the hook in to customize Change Icon if desired.
+ uRet=UStandardHook(lpIO, hDlg, uMsgChangeIcon
+ , 0, (LONG)(LPTSTR)&ci);
+
+ if (0==uRet)
+ uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
+
+ //Update the display and itemdata if necessary.
+ if (0!=uRet)
+ {
+
+ /*
+ * OleUIChangeIcon will have already freed our
+ * current hMetaPict that we passed in when OK is
+ * pressed in that dialog. So we use 0L as lParam
+ * here so the IconBox doesn't try to free the
+ * metafilepict again.
+ */
+ SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET
+ , (WPARAM)ci.hMetaPict, 0L);
+
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ SendMessage(hList, LB_SETITEMDATA, iCurSel, ci.hMetaPict);
+ }
+ }
+ break;
+
+
+ case ID_IO_FILE:
+ {
+ /*
+ * To allow the hook to customize the browse dialog, we
+ * send OLEUI_MSG_BROWSE. If the hook returns FALSE
+ * we use the default, otherwise we trust that it retrieved
+ * a filename for us. This mechanism prevents hooks from
+ * trapping ID_IO_BROWSE to customize the dialog and from
+ * trying to figure out what we do after we have the name.
+ */
+
+ TCHAR szTemp[OLEUI_CCHPATHMAX];
+ TCHAR szInitialDir[OLEUI_CCHPATHMAX];
+ DWORD dwOfnFlags;
+ int nChars;
+ BOOL fUseInitialDir = FALSE;
+
+
+ nChars = GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szTemp, OLEUI_CCHPATHMAX);
+
+ if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
+ {
+
+ int istrlen;
+
+ GetFileTitle((LPTSTR)szTemp, lpIO->szFile, OLEUI_CCHPATHMAX);
+
+ istrlen = lstrlen(lpIO->szFile);
+
+ LSTRCPYN((LPTSTR)szInitialDir, szTemp, nChars - istrlen);
+ fUseInitialDir = TRUE;
+
+ }
+ else // file name isn't valid...lop off end of szTemp to get a
+ // valid directory
+ {
+#if defined( WIN32 )
+ TCHAR szBuffer[OLEUI_CCHPATHMAX];
+ DWORD Attribs;
+
+ LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1);
+ szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0');
+
+ if (TEXT('\\') == szBuffer[nChars-1])
+ szBuffer[nChars-1] = TEXT('\0');
+
+ Attribs = GetFileAttributes(szBuffer);
+ if (Attribs != 0xffffffff &&
+ (Attribs & FILE_ATTRIBUTE_DIRECTORY) )
+ {
+ lstrcpy(szInitialDir, (LPTSTR)szBuffer);
+ fUseInitialDir = TRUE;
+ }
+#else
+ static TCHAR szBuffer[OLEUI_CCHPATHMAX];
+ static int attrib ;
+
+ LSTRCPYN(szBuffer, szTemp, OLEUI_CCHPATHMAX-1);
+ szBuffer[OLEUI_CCHPATHMAX-1] = TEXT('\0');
+
+ AnsiToOem(szBuffer, szBuffer);
+#if defined( OBSOLETE ) // fix bug# 3575
+ if (TEXT('\\') == szBuffer[nChars-1])
+ szBuffer[nChars-1] = TEXT('\0');
+
+ if(0 == _dos_getfileattr(szBuffer, &attrib))
+#endif // OBSOLETE
+ {
+ lstrcpy(szInitialDir, (LPTSTR)szBuffer);
+ fUseInitialDir = TRUE;
+ }
+#endif
+ *lpIO->szFile = TEXT('\0');
+ }
+
+ uRet=UStandardHook(lpIO, hDlg, uMsgBrowse
+ , OLEUI_CCHPATHMAX_SIZE, (LPARAM)(LPSTR)lpIO->szFile);
+
+ dwOfnFlags = OFN_FILEMUSTEXIST;
+
+ if (lpIO->lpOIO->dwFlags & IOF_SHOWHELP)
+ dwOfnFlags |= OFN_SHOWHELP;
+
+ if (0==uRet)
+ uRet=(UINT)Browse(hDlg,
+ lpIO->szFile,
+ fUseInitialDir ? (LPTSTR)szInitialDir : NULL,
+ OLEUI_CCHPATHMAX_SIZE,
+ IDS_FILTERS,
+ dwOfnFlags);
+
+ //Only update if the file changed.
+ if (0!=uRet && 0!=lstrcmpi(szTemp, lpIO->szFile))
+ {
+ SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile);
+ lpIO->fFileSelected=TRUE;
+
+ if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
+ {
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = TRUE;
+ UpdateClassIcon(hDlg, lpIO, NULL);
+ UpdateClassType(hDlg, lpIO, TRUE);
+ // auto set OK to be default button if valid file
+ SendMessage(hDlg, DM_SETDEFID,
+ (WPARAM)GetDlgItem(hDlg, IDOK), 0L);
+ SetFocus(GetDlgItem(hDlg, IDOK));
+ }
+ else // filename is invalid - set focus back to ec
+ {
+ HWND hWnd;
+
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = FALSE;
+ hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
+ SetFocus(hWnd);
+ SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ }
+
+ //Once we have a file, Display As Icon is always enabled
+ EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), TRUE);
+
+ //As well as OK
+ EnableWindow(GetDlgItem(hDlg, IDOK), TRUE);
+
+ }
+ }
+ break;
+
+
+ case IDOK:
+ {
+ HWND hListBox;
+ WORD iCurSel;
+ TCHAR szBuffer[OLEUI_CCHKEYMAX + OLEUI_CCHCLSIDSTRING];
+ LPTSTR lpszCLSID;
+
+ if ((HWND)(LOWORD(lParam)) != GetFocus())
+ SetFocus((HWND)(LOWORD(lParam)));
+
+
+
+ // If the file name is clean (already validated), or
+ // if Create New is selected, then we can skip this part.
+
+ if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
+ && (TRUE == lpIO->fFileDirty) )
+ {
+
+ if (FValidateInsertFile(hDlg, TRUE, &lpIO->nErrCode))
+ {
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = TRUE;
+ UpdateClassIcon(hDlg, lpIO, NULL);
+ UpdateClassType(hDlg, lpIO, TRUE);
+ }
+ else // filename is invalid - set focus back to ec
+ {
+ HWND hWnd;
+
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = FALSE;
+ hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
+ SetFocus(hWnd);
+ SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ UpdateClassType(hDlg, lpIO, FALSE);
+ }
+
+ return TRUE; // eat this message
+ }
+ else if ( (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
+ && (FALSE == lpIO->fFileValid) )
+ {
+ // filename is invalid - set focus back to ec
+ HWND hWnd;
+ TCHAR szFile[OLEUI_CCHPATHMAX];
+
+ if (0!=GetDlgItemText(hDlg, ID_IO_FILEDISPLAY,
+ szFile, OLEUI_CCHPATHMAX))
+ {
+ OpenFileError(hDlg, lpIO->nErrCode, szFile);
+ }
+ lpIO->fFileDirty = FALSE;
+ lpIO->fFileValid = FALSE;
+ hWnd = GetDlgItem(hDlg, ID_IO_FILEDISPLAY);
+ SetFocus(hWnd);
+ SendMessage(hWnd, EM_SETSEL, 0, MAKELPARAM(0, (WORD)-1));
+ UpdateClassType(hDlg, lpIO, FALSE);
+ return TRUE; // eat this message
+ }
+
+ //Copy the necessary information back to the original struct
+ lpOIO=lpIO->lpOIO;
+ lpOIO->dwFlags=lpIO->dwFlags;
+
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ hListBox=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
+ iCurSel=(WORD)SendMessage(hListBox, LB_GETCURSEL, 0, 0);
+
+ if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
+ {
+ lpOIO->hMetaPict=(HGLOBAL)SendMessage(hListBox,
+ LB_GETITEMDATA, iCurSel, 0L);
+
+ /*
+ * Set the item data to 0 here so that the cleanup
+ * code doesn't delete the metafile.
+ */
+ SendMessage(hListBox, LB_SETITEMDATA, iCurSel, 0L);
+ }
+ else
+ lpOIO->hMetaPict = (HGLOBAL)NULL;
+
+ SendMessage(hListBox, LB_GETTEXT, iCurSel
+ , (LPARAM)(LPTSTR)szBuffer);
+
+ lpszCLSID=PointerToNthField((LPTSTR)szBuffer, 2, TEXT('\t'));
+ CLSIDFromStringA(lpszCLSID, &lpOIO->clsid);
+
+ }
+ else // IOF_SELECTCREATEFROMFILE
+ {
+ if (lpIO->dwFlags & IOF_CHECKDISPLAYASICON)
+ {
+ // get metafile here
+ lpOIO->hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg,
+ ID_IO_ICONDISPLAY,
+ IBXM_IMAGEGET,
+ 0, 0L);
+
+
+ }
+ else
+ lpOIO->hMetaPict = (HGLOBAL)NULL;
+
+ }
+
+ GetDlgItemText(hDlg, ID_IO_FILEDISPLAY,
+ lpIO->szFile, lpOIO->cchFile);
+
+ LSTRCPYN(lpOIO->lpszFile, lpIO->szFile, lpOIO->cchFile);
+
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ }
+ break;
+
+ case IDCANCEL:
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+
+ case ID_OLEUIHELP:
+ PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp
+ , (WPARAM)hDlg, MAKELPARAM(IDD_INSERTOBJECT, 0));
+ break;
+ }
+ break;
+
+ default:
+ {
+ if (lpIO && iMsg == lpIO->nBrowseHelpID) {
+ PostMessage(lpIO->lpOIO->hWndOwner, uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_INSERTFILEBROWSE, 0));
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+ }
+
+
+
+
+/*
+ * FInsertObjectInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Insert Object dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FInsertObjectInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+ {
+ LPOLEUIINSERTOBJECT lpOIO;
+ LPINSERTOBJECT lpIO;
+ RECT rc;
+ DWORD dw;
+ HFONT hFont;
+ HWND hList;
+ UINT u;
+ BOOL fCheck;
+ CHAR *pch; // pointer to current working directory
+ // ANSI string (to use with _getcwd)
+
+ //1. Copy the structure at lParam into our instance memory.
+ lpIO=(LPINSERTOBJECT)LpvStandardInit(hDlg, sizeof(INSERTOBJECT), TRUE, &hFont);
+
+ //PvStandardInit send a termination to us already.
+ if (NULL==lpIO)
+ return FALSE;
+
+ lpOIO=(LPOLEUIINSERTOBJECT)lParam;
+
+ //2. Save the original pointer and copy necessary information.
+ lpIO->lpOIO =lpOIO;
+ lpIO->dwFlags=lpOIO->dwFlags;
+ lpIO->clsid =lpOIO->clsid;
+
+ if ( (lpOIO->lpszFile) && (TEXT('\0') != *lpOIO->lpszFile) )
+ LSTRCPYN((LPTSTR)lpIO->szFile, lpOIO->lpszFile, OLEUI_CCHPATHMAX);
+ else
+ *(lpIO->szFile) = TEXT('\0');
+
+ lpIO->hMetaPictFile = (HGLOBAL)NULL;
+
+ //3. If we got a font, send it to the necessary controls.
+ if (NULL!=hFont)
+ {
+ SendDlgItemMessage(hDlg, ID_IO_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, ID_IO_FILETYPE, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+
+ //4. Fill the Object Type listbox with entries from the reg DB.
+ hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
+ UFillClassList(hList, lpOIO->cClsidExclude, lpOIO->lpClsidExclude
+ , (BOOL)(lpOIO->dwFlags & IOF_VERIFYSERVERSEXIST));
+
+ //Set the tab width in the list to push all the tabs off the side.
+ GetClientRect(hList, &rc);
+ dw=GetDialogBaseUnits();
+ rc.right =(8*rc.right)/LOWORD(dw); //Convert pixels to 2x dlg units.
+ SendMessage(hList, LB_SETTABSTOPS, 1, (LPARAM)(LPINT)&rc.right);
+
+
+ //5. Initilize the file name display to cwd if we don't have any name.
+ if (TEXT('\0') == *(lpIO->szFile))
+ {
+ TCHAR tch[OLEUI_CCHPATHMAX];
+
+ pch=_getcwd(NULL, OLEUI_CCHPATHMAX);
+ if (*(pch+strlen(pch)-1) != '\\')
+ strcat(pch, "\\"); // put slash on end of cwd
+#ifdef UNICODE
+ mbstowcs(tch, pch, OLEUI_CCHPATHMAX);
+#else
+ strcpy(tch, pch);
+#endif
+ SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, tch);
+ lpIO->fFileDirty = TRUE; // cwd is not a valid filename
+ #ifndef __TURBOC__
+ free(pch);
+ #endif
+ }
+ else
+ {
+ SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, lpIO->szFile);
+
+ if (FValidateInsertFile(hDlg, FALSE, &lpIO->nErrCode))
+ lpIO->fFileDirty = FALSE;
+ else
+ lpIO->fFileDirty = TRUE;
+ }
+
+
+ //6. Initialize the selected type radiobutton.
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ StandardShowDlgItem(hDlg, ID_IO_FILETEXT, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_FILETYPE, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_FILE, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE);
+
+ CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATENEW);
+
+ lpIO->fAsIconNew=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
+ SetFocus(hList);
+ }
+ else
+ {
+ /*
+ * Use pszType as the initial File. If there's no initial
+ * file then we have to remove any check from Display As
+ * Icon. We also check Link if so indicated for this option.
+ */
+ StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, SW_HIDE);
+
+ // Don't preselect display as icon if the filename isn't valid
+ if (TRUE == lpIO->fFileDirty)
+ lpIO->dwFlags &= ~(IOF_CHECKDISPLAYASICON);
+
+ if (IOF_DISABLELINK & lpIO->dwFlags)
+ StandardShowDlgItem(hDlg, ID_IO_LINKFILE, SW_HIDE);
+ else
+ {
+ CheckDlgButton(hDlg, ID_IO_LINKFILE
+ , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKLINK)));
+ }
+
+ CheckRadioButton(hDlg, ID_IO_CREATENEW, ID_IO_CREATEFROMFILE, ID_IO_CREATEFROMFILE);
+
+ lpIO->fAsIconFile=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
+ SetFocus(GetDlgItem(hDlg, ID_IO_FILEDISPLAY));
+ }
+
+
+ //7. Initialize the Display as Icon state
+ fCheck=(BOOL)(lpIO->dwFlags & IOF_CHECKDISPLAYASICON);
+ u=fCheck ? SW_SHOWNORMAL : SW_HIDE;
+
+ StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, u);
+ StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, u);
+
+ CheckDlgButton(hDlg, ID_IO_DISPLAYASICON, fCheck);
+
+
+ //8. Show or hide the help button
+ if (!(lpIO->dwFlags & IOF_SHOWHELP))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+
+ //9. Initialize the result display
+ UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
+ SetInsertObjectResults(hDlg, lpIO);
+
+ //10. Change the caption
+ if (NULL!=lpOIO->lpszCaption)
+ SetWindowText(hDlg, lpOIO->lpszCaption);
+
+ //11. Hide all DisplayAsIcon related controls if it should be disabled
+ if ( lpIO->dwFlags & IOF_DISABLEDISPLAYASICON ) {
+ StandardShowDlgItem(hDlg, ID_IO_DISPLAYASICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, SW_HIDE);
+ }
+
+ lpIO->nBrowseHelpID = RegisterWindowMessage(HELPMSGSTRING);
+
+ //All Done: call the hook with lCustData
+ UStandardHook(lpIO, hDlg, WM_INITDIALOG, wParam, lpOIO->lCustData);
+
+ /*
+ * We either set focus to the listbox or the edit control. In either
+ * case we don't want Windows to do any SetFocus, so we return FALSE.
+ */
+ return FALSE;
+ }
+
+
+
+
+
+
+/*
+ * UFillClassList
+ *
+ * Purpose:
+ * Enumerates available OLE object classes from the registration
+ * database and fills a listbox with those names.
+ *
+ * Note that this function removes any prior contents of the listbox.
+ *
+ * Parameters:
+ * hList HWND to the listbox to fill.
+ * cIDEx UINT number of CLSIDs to exclude in lpIDEx
+ * lpIDEx LPCLSID to CLSIDs to leave out of the listbox.
+ * fVerify BOOL indicating if we are to validate existence of
+ * servers before putting them in the list.
+ *
+ * Return Value:
+ * UINT Number of strings added to the listbox, -1 on failure.
+ */
+
+UINT UFillClassList(HWND hList, UINT cIDEx, LPCLSID lpIDEx, BOOL fVerify)
+ {
+ DWORD dw;
+ UINT cStrings=0;
+ UINT i;
+ UINT cch;
+ HKEY hKey;
+ LONG lRet;
+ HFILE hFile;
+ OFSTRUCT of;
+ BOOL fExclude;
+ LPMALLOC pIMalloc;
+ LPTSTR pszExec;
+ LPTSTR pszClass;
+ LPTSTR pszKey;
+ LPTSTR pszID;
+ CLSID clsid;
+
+ //Get some work buffers
+ if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ return (UINT)-1;
+
+ pszExec=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE*4);
+
+ if (NULL==pszExec)
+ {
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return (UINT)-1;
+ }
+
+ pszClass=pszExec+OLEUI_CCHKEYMAX;
+ pszKey=pszClass+OLEUI_CCHKEYMAX;
+ pszID=pszKey+OLEUI_CCHKEYMAX;
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ {
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return (UINT)-1;
+ }
+
+ //Clean out the existing strings.
+ SendMessage(hList, LB_RESETCONTENT, 0, 0L);
+
+ cStrings=0;
+
+ while (TRUE)
+ {
+ lRet=RegEnumKey(hKey, cStrings++, pszClass, OLEUI_CCHKEYMAX_SIZE);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ break;
+
+ //Cheat on lstrcat by using lstrcpy after this string, saving time
+ cch=lstrlen(pszClass);
+
+ // Check for \NotInsertable. if this is found then this overrides
+ // all other keys; this class will NOT be added to the InsertObject
+ // list.
+
+ lstrcpy(pszClass+cch, TEXT("\\NotInsertable"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ continue; // NotInsertable IS found--skip this class
+
+ //Check for a \protocol\StdFileEditing\server entry.
+ lstrcpy(pszClass+cch, TEXT("\\protocol\\StdFileEditing\\server"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+ /*
+ * Check if the EXE actually exists. By default we don't do this
+ * to bring up the dialog faster. If an application wants to be
+ * stringent, they can provide IOF_VERIFYSERVERSEXIST.
+ */
+
+ hFile = !HFILE_ERROR;
+
+ if (fVerify)
+ hFile=DoesFileExist(pszKey, &of);
+
+ if (HFILE_ERROR!=hFile)
+ {
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ *(pszClass+cch)=0; // set back to rootkey
+ // Get full user type name
+ lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ continue; // error getting type name--skip this class
+
+ //Tell the code below to get the string for us.
+ pszID=NULL;
+ }
+ }
+ else
+ {
+ /*
+ * No \protocol\StdFileEditing\server entry. Look to see if
+ * there's an Insertable entry. If there is, then use the
+ * Clsid to look at CLSID\clsid\LocalServer and \InprocServer
+ */
+
+ lstrcpy(pszClass+cch, TEXT("\\Insertable"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszClass, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ continue; // Insertable NOT found--skip this class
+
+ //Get memory for pszID
+ pszID=pIMalloc->lpVtbl->Alloc(pIMalloc, OLEUI_CCHKEYMAX_SIZE);
+
+ if (NULL==pszID)
+ continue;
+
+ *(pszClass+cch)=0; // set back to rootkey
+ lstrcat(pszClass+cch, TEXT("\\CLSID"));
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszClass, pszID, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ continue; // CLSID subkey not found
+
+ lstrcpy(pszExec, TEXT("CLSID\\"));
+ lstrcat(pszExec, pszID);
+
+ //CLSID\ is 6, dw contains pszID length.
+ cch=6+(UINT)dw;
+
+ lstrcpy(pszExec+cch, TEXT("\\LocalServer"));
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ {
+ //Try InprocServer
+ lstrcpy(pszExec+cch, TEXT("\\InProcServer"));
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ continue;
+ }
+
+ if (fVerify)
+ {
+ if (HFILE_ERROR==DoesFileExist(pszKey, &of))
+ continue;
+ }
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet=RegQueryValue(hKey, pszExec, pszKey, &dw);
+ *(pszExec+cch)=0; //Remove \\*Server
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ continue;
+ }
+
+ //Get CLSID to add to listbox.
+ if (NULL==pszID)
+ {
+ CLSIDFromProgIDA(pszClass, &clsid);
+ StringFromCLSIDA(&clsid, &pszID);
+ }
+ else
+ CLSIDFromStringA(pszID, &clsid);
+
+ //Check if this CLSID is in the exclusion list.
+ fExclude=FALSE;
+
+ for (i=0; i < cIDEx; i++)
+ {
+ if (IsEqualCLSID(&clsid, (LPCLSID)(lpIDEx+i)))
+ {
+ fExclude=TRUE;
+ break;
+ }
+ }
+
+ if (fExclude)
+ continue;
+
+ //We go through all the conditions, add the string.
+ lstrcat(pszKey, TEXT("\t"));
+
+ // only add to listbox if not a duplicate
+ if (LB_ERR==SendMessage(hList,LB_FINDSTRING,0,(LPARAM)pszKey)) {
+ lstrcat(pszKey, pszID);
+ SendMessage(hList, LB_ADDSTRING, 0, (LPARAM)pszKey);
+ }
+
+ //We always allocated this regardless of the path
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszID);
+ }
+
+
+ //Select the first item by default
+ SendMessage(hList, LB_SETCURSEL, 0, 0L);
+ RegCloseKey(hKey);
+
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszExec);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+
+ return cStrings;
+ }
+
+
+
+
+
+/*
+ * FToggleObjectSource
+ *
+ * Purpose:
+ * Handles enabling, disabling, showing, and flag manipulation when the
+ * user changes between Create New, Insert File, and Link File in the
+ * Insert Object dialog.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpIO LPINSERTOBJECT pointing to the dialog structure
+ * dwOption DWORD flag indicating the option just selected:
+ * IOF_SELECTCREATENEW or IOF_SELECTCREATEFROMFILE
+ *
+ * Return Value:
+ * BOOL TRUE if the option was already selected, FALSE otherwise.
+ */
+
+BOOL FToggleObjectSource(HWND hDlg, LPINSERTOBJECT lpIO, DWORD dwOption)
+ {
+ BOOL fTemp;
+ UINT uTemp;
+ DWORD dwTemp;
+ int i;
+
+ //Skip all of this if we're already selected.
+ if (lpIO->dwFlags & dwOption)
+ return TRUE;
+
+
+ // if we're switching from "from file" to "create new" and we've got
+ // an icon for "from file", then we need to save it so that we can
+ // show it if the user reselects "from file".
+
+ if ( (IOF_SELECTCREATENEW == dwOption) &&
+ (lpIO->dwFlags & IOF_CHECKDISPLAYASICON) )
+ lpIO->hMetaPictFile = (HGLOBAL)SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
+
+ /*
+ * 1. Change the Display As Icon checked state to reflect the
+ * selection for this option, stored in the fAsIcon* flags.
+ */
+ fTemp=(IOF_SELECTCREATENEW==dwOption) ? lpIO->fAsIconNew : lpIO->fAsIconFile;
+
+ if (fTemp)
+ lpIO->dwFlags |=IOF_CHECKDISPLAYASICON;
+ else
+ lpIO->dwFlags &=~IOF_CHECKDISPLAYASICON;
+
+ CheckDlgButton(hDlg, ID_IO_DISPLAYASICON
+ , (BOOL)(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON)));
+
+ EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), fTemp);
+
+ /*
+ * 2. Display Icon: Enabled on Create New or on Create from File if
+ * there is a selected file.
+ */
+ fTemp=(IOF_SELECTCREATENEW==dwOption) ? TRUE : lpIO->fFileSelected;
+ EnableWindow(GetDlgItem(hDlg, ID_IO_DISPLAYASICON), fTemp);
+
+ //OK and Link follow the same enabling as Display As Icon.
+ EnableWindow(GetDlgItem(hDlg, IDOK), fTemp);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_LINKFILE), fTemp);
+
+ //3. Enable Browse... when Create from File is selected.
+ fTemp=(IOF_SELECTCREATENEW==dwOption);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_FILE), !fTemp);
+ EnableWindow(GetDlgItem(hDlg, ID_IO_FILEDISPLAY), !fTemp);
+
+ /*
+ * 4. Switch between Object Type listbox on Create New and
+ * file buttons on others.
+ */
+ uTemp=(fTemp) ? SW_SHOWNORMAL : SW_HIDE;
+ StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPELIST, uTemp);
+ StandardShowDlgItem(hDlg, ID_IO_OBJECTTYPETEXT, uTemp);
+
+ uTemp=(fTemp) ? SW_HIDE : SW_SHOWNORMAL;
+ StandardShowDlgItem(hDlg, ID_IO_FILETEXT, uTemp);
+ StandardShowDlgItem(hDlg, ID_IO_FILETYPE, uTemp);
+ StandardShowDlgItem(hDlg, ID_IO_FILEDISPLAY, uTemp);
+ StandardShowDlgItem(hDlg, ID_IO_FILE, uTemp);
+
+ //Link is always hidden if IOF_DISABLELINK is set.
+ if (IOF_DISABLELINK & lpIO->dwFlags)
+ uTemp=SW_HIDE;
+
+ StandardShowDlgItem(hDlg, ID_IO_LINKFILE, uTemp); //last use of uTemp
+
+
+ //5. Clear out existing any flags selection and set the new one
+ dwTemp=IOF_SELECTCREATENEW | IOF_SELECTCREATEFROMFILE;
+ lpIO->dwFlags=(lpIO->dwFlags & ~dwTemp) | dwOption;
+
+
+ /*
+ * Show or hide controls as appropriate. Do the icon
+ * display last because it will take some time to repaint.
+ * If we do it first then the dialog looks too sluggish.
+ */
+
+ i=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON) ? SW_SHOWNORMAL : SW_HIDE;
+ StandardShowDlgItem(hDlg, ID_IO_CHANGEICON, i);
+ StandardShowDlgItem(hDlg, ID_IO_ICONDISPLAY, i);
+
+
+ //6.Change result display
+ SetInsertObjectResults(hDlg, lpIO);
+
+ /*
+ * 7. For Create New, twiddle the listbox to think we selected it
+ * so it updates the icon from the object type. set the focus
+ * to the list box.
+ *
+ * For Insert or Link file, set the focus to the filename button
+ * and update the icon if necessary.
+ */
+ if (fTemp) {
+ UpdateClassIcon(hDlg, lpIO, GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
+ SetFocus(GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST));
+ }
+ else
+ {
+ if (lpIO->fAsIconFile && (NULL != lpIO->hMetaPictFile) )
+ {
+ SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)lpIO->hMetaPictFile, 0L);
+ lpIO->hMetaPictFile = 0;
+ }
+ else
+ UpdateClassIcon(hDlg, lpIO, NULL);
+
+ SetFocus(GetDlgItem(hDlg, ID_IO_FILE));
+ }
+
+ return FALSE;
+ }
+
+
+/*
+ * UpdateClassType
+ *
+ * Purpose:
+ * Updates static text control to reflect current file type. Assumes
+ * a valid filename.
+ *
+ * Parameters
+ * hDlg HWND of the dialog box.
+ * lpIO LPINSERTOBJECT pointing to the dialog structure
+ * fSet TRUE to set the text, FALSE to explicitly clear it
+ *
+ * Return Value:
+ * None
+ */
+
+void UpdateClassType(HWND hDlg, LPINSERTOBJECT lpIO, BOOL fSet)
+{
+
+ CLSID clsid;
+ TCHAR szFileName[OLEUI_CCHPATHMAX];
+ TCHAR szFileType[OLEUI_CCHLABELMAX];
+
+ *szFileType = TEXT('\0');
+
+ if (fSet)
+ {
+ GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, (LPTSTR)szFileName, OLEUI_CCHPATHMAX);
+
+ if (NOERROR == GetClassFileA(szFileName, &clsid) )
+ OleStdGetUserTypeOfClass(&clsid, szFileType, OLEUI_CCHLABELMAX_SIZE, NULL);
+
+ }
+
+ SetDlgItemText(hDlg, ID_IO_FILETYPE, (LPTSTR)szFileType);
+
+ return;
+}
+
+
+/*
+ * UpdateClassIcon
+ *
+ * Purpose:
+ * Handles LBN_SELCHANGE for the Object Type listbox. On a selection
+ * change, we extract an icon from the server handling the currently
+ * selected object type using the utility function HIconFromClass.
+ * Note that we depend on the behavior of FillClassList to stuff the
+ * object class after a tab in the listbox string that we hide from
+ * view (see WM_INITDIALOG).
+ *
+ * Parameters
+ * hDlg HWND of the dialog box.
+ * lpIO LPINSERTOBJECT pointing to the dialog structure
+ * hList HWND of the Object Type listbox.
+ *
+ * Return Value:
+ * None
+ */
+
+void UpdateClassIcon(HWND hDlg, LPINSERTOBJECT lpIO, HWND hList)
+ {
+ UINT iSel;
+ DWORD cb;
+ LPMALLOC pIMalloc;
+ LPTSTR pszName, pszCLSID, pszTemp;
+ HGLOBAL hMetaPict;
+
+ LRESULT dwRet;
+
+
+ //If Display as Icon is not selected, exit
+ if (!(lpIO->dwFlags & IOF_CHECKDISPLAYASICON))
+ return;
+
+ /*
+ * When we change object type selection, get the new icon for that
+ * type into our structure and update it in the display. We use the
+ * class in the listbox when Create New is selected or the association
+ * with the extension in Create From File.
+ */
+
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+
+ if (LB_ERR==(int)iSel)
+ return;
+
+ //Check to see if we've already got the hMetaPict for this item
+ dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)iSel, 0L);
+
+ hMetaPict=(HGLOBAL)(UINT)dwRet;
+
+ if (hMetaPict)
+ {
+ //Yep, we've already got it, so just display it and return.
+ SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L);
+ return;
+ }
+
+ iSel=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+
+ if (LB_ERR==(int)iSel)
+ return;
+
+ //Allocate a string to hold the entire listbox string
+ cb=SendMessage(hList, LB_GETTEXTLEN, iSel, 0L);
+ }
+ else
+ cb=OLEUI_CCHPATHMAX_SIZE;
+
+ if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ return;
+
+ pszName=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, cb+1*sizeof(TCHAR) );
+
+ if (NULL==pszName)
+ {
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return;
+ }
+
+ *pszName=0;
+
+ //Get the clsid we want.
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ //Grab the classname string from the list
+ SendMessage(hList, LB_GETTEXT, iSel, (LONG)pszName);
+
+ //Set pointer to CLSID (string)
+ pszCLSID=PointerToNthField(pszName, 2, TEXT('\t'));
+
+ //Null terminate pszName string
+#ifdef WIN32
+ // AnsiPrev is obsolete in Win32
+ pszTemp=CharPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID);
+#else
+ pszTemp=AnsiPrev((LPCTSTR) pszName,(LPCTSTR) pszCLSID);
+#endif
+ *pszTemp=TEXT('\0');
+ CLSIDFromStringA(pszCLSID, &lpIO->clsid);
+
+#ifdef OLE201
+ hMetaPict = GetIconOfClass(ghInst, &lpIO->clsid, NULL, TRUE);
+#endif
+ }
+
+ else
+ {
+ //Get the class from the filename
+ GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, pszName, OLEUI_CCHPATHMAX);
+
+#ifdef OLE201
+
+ hMetaPict = OleGetIconOfFileA(pszName,
+ lpIO->dwFlags & IOF_CHECKLINK ? TRUE : FALSE);
+
+#endif
+
+ }
+
+ //Replace the current display with this new one.
+ SendDlgItemMessage(hDlg, ID_IO_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)hMetaPict, 0L);
+
+ //Enable or disable "Change Icon" button depending on whether
+ //we've got a valid filename or not.
+ EnableWindow(GetDlgItem(hDlg, ID_IO_CHANGEICON), hMetaPict ? TRUE : FALSE);
+
+ //Save the hMetaPict so that we won't have to re-create
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ SendMessage(hList, LB_SETITEMDATA, (WPARAM)iSel, hMetaPict);
+
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszName);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return;
+ }
+
+
+
+
+/*
+ * SetInsertObjectResults
+ *
+ * Purpose:
+ * Centralizes setting of the Result and icon displays in the Insert Object
+ * dialog. Handles loading the appropriate string from the module's
+ * resources and setting the text, displaying the proper result picture,
+ * and showing the proper icon.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box so we can access controls.
+ * lpIO LPINSERTOBJECT in which we assume that the
+ * current radiobutton and Display as Icon selections
+ * are set. We use the state of those variables to
+ * determine which string we use.
+ *
+ * Return Value:
+ * None
+ */
+
+void SetInsertObjectResults(HWND hDlg, LPINSERTOBJECT lpIO)
+ {
+ LPTSTR pszT, psz1, psz2, psz3, psz4, pszTemp;
+ UINT i, iString1, iString2, iImage, cch;
+ LPMALLOC pIMalloc;
+ BOOL fAsIcon;
+
+ /*
+ * We need scratch memory for loading the stringtable string, loading
+ * the object type from the listbox, and constructing the final string.
+ * We therefore allocate three buffers as large as the maximum message
+ * length (512) plus the object type, guaranteeing that we have enough
+ * in all cases.
+ */
+ i=(UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETCURSEL, 0, 0L);
+ cch=512+
+ (UINT)SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXTLEN, i, 0L);
+
+ if (NOERROR!=CoGetMalloc(MEMCTX_TASK, &pIMalloc))
+ return;
+
+ pszTemp=(LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)(4*cch*sizeof(TCHAR)));
+
+ if (NULL==pszTemp)
+ {
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return;
+ }
+
+ psz1=pszTemp;
+ psz2=psz1+cch;
+ psz3=psz2+cch;
+ psz4=psz3+cch;
+
+ fAsIcon=(0L!=(lpIO->dwFlags & IOF_CHECKDISPLAYASICON));
+
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ iString1 = fAsIcon ? IDS_IORESULTNEWICON : IDS_IORESULTNEW;
+ iString2 = 0;
+ iImage = fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
+ }
+
+ if (lpIO->dwFlags & IOF_SELECTCREATEFROMFILE)
+ {
+ //Pay attention to Link checkbox
+ if (lpIO->dwFlags & IOF_CHECKLINK)
+ {
+ iString1 = fAsIcon ? IDS_IORESULTLINKFILEICON1 : IDS_IORESULTLINKFILE1;
+ iString2 = fAsIcon ? IDS_IORESULTLINKFILEICON2 : IDS_IORESULTLINKFILE2;
+ iImage =fAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
+ }
+ else
+ {
+ iString1 = IDS_IORESULTFROMFILE1;
+ iString2 = fAsIcon ? IDS_IORESULTFROMFILEICON2 : IDS_IORESULTFROMFILE2;
+ iImage =fAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
+ }
+ }
+
+ //Default is an empty string.
+ *psz1=0;
+
+ if (0!=LoadString(ghInst, iString1, psz1, cch))
+ {
+
+ // Load second string, if necessary
+ if ( (0 != iString2)
+ && (0 != LoadString(ghInst, iString2, psz4, cch)) )
+ {
+ lstrcat(psz1, psz4); // concatenate strings together.
+ }
+
+
+
+ //In Create New, do the extra step of inserting the object type string
+ if (lpIO->dwFlags & IOF_SELECTCREATENEW)
+ {
+ SendDlgItemMessage(hDlg, ID_IO_OBJECTTYPELIST, LB_GETTEXT
+ , i, (LONG)psz2);
+
+ //Null terminate at any tab (before the classname)
+ pszT=psz2;
+ while (TEXT('\t')!=*pszT && 0!=*pszT)
+ pszT++;
+ *pszT=0;
+
+ //Build the string and point psz1 to it.
+ wsprintf(psz3, psz1, psz2);
+ psz1=psz3;
+ }
+ }
+
+ //If LoadString failed, we simply clear out the results (*psz1=0 above)
+ SetDlgItemText(hDlg, ID_IO_RESULTTEXT, psz1);
+
+ //Go change the image and Presto! There you have it.
+ SendDlgItemMessage(hDlg, ID_IO_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
+
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)pszTemp);
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ return;
+ }
+
+
+
+/*
+ * FValidateInsertFile
+ *
+ * Purpose:
+ * Given a possibly partial pathname from the file edit control,
+ * attempt to locate the file and if found, store the full path
+ * in the edit control ID_IO_FILEDISPLAY.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog box.
+ * fTellUser BOOL TRUE if function should tell user, FALSE if
+ * function should validate silently.
+ *
+ * Return Value:
+ * BOOL TRUE if the file is acceptable, FALSE otherwise.
+ */
+
+BOOL FValidateInsertFile(HWND hDlg, BOOL fTellUser, UINT FAR* lpnErrCode)
+ {
+ OFSTRUCT of;
+ HFILE hFile;
+ TCHAR szFile[OLEUI_CCHPATHMAX];
+
+ *lpnErrCode = 0;
+ /*
+ * To validate we attempt OpenFile on the string. If OpenFile
+ * fails then we display an error. If not, OpenFile will store
+ * the complete path to that file in the OFSTRUCT which we can
+ * then stuff in the edit control.
+ */
+
+ if (0==GetDlgItemText(hDlg, ID_IO_FILEDISPLAY, szFile, OLEUI_CCHPATHMAX))
+ return FALSE; // #4569 : return FALSE when there is no text in ctl
+
+ hFile=DoesFileExist(szFile, &of);
+
+ // if file is currently open (ie. sharing violation) OleCreateFromFile
+ // and OleCreateLinkToFile can still succeed; do not consider it an
+ // error.
+ if (HFILE_ERROR==hFile && 0x0020/*sharing violation*/!=of.nErrCode)
+ {
+ *lpnErrCode = of.nErrCode;
+ if (fTellUser)
+ OpenFileError(hDlg, of.nErrCode, szFile);
+ return FALSE;
+ }
+
+ //OFSTRUCT contains an OEM name, not ANSI as we need for the edit box.
+ OemToAnsi(of.szPathName, of.szPathName);
+
+ SetDlgItemText(hDlg, ID_IO_FILEDISPLAY, of.szPathName);
+ return TRUE;
+ }
+
+
+/*
+ * InsertObjectCleanup
+ *
+ * Purpose:
+ * Clears cached icon metafiles from those stored in the listbox.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog.
+ *
+ * Return Value:
+ * None
+ */
+
+void InsertObjectCleanup(HWND hDlg)
+ {
+ HWND hList;
+ UINT iItems;
+ HGLOBAL hMetaPict;
+ LRESULT dwRet;
+ UINT i;
+
+ hList=GetDlgItem(hDlg, ID_IO_OBJECTTYPELIST);
+ iItems=(UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L);
+
+ for (i=0; i < iItems; i++)
+ {
+ dwRet=SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
+
+ //Cast of LRESULT to UINT to HGLOBAL portable to Win32.
+ hMetaPict=(HGLOBAL)(UINT)dwRet;
+
+ if (hMetaPict)
+ OleUIMetafilePictIconFree(hMetaPict);
+ }
+
+ return;
+ }
diff --git a/private/oleutest/letest/ole2ui/insobj.dlg b/private/oleutest/letest/ole2ui/insobj.dlg
new file mode 100644
index 000000000..2f81811a0
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/insobj.dlg
@@ -0,0 +1,51 @@
+//DLGINCLUDE RCDATA DISCARDABLE
+//BEGIN
+// "OLE2UI.H\0"
+//END
+
+IDD_INSERTOBJECT DIALOG 6, 18, 291, 150
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Insert Object"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "Create &New", ID_IO_CREATENEW, "Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 6, 18, 67, 10
+
+ CONTROL "Create from &File", ID_IO_CREATEFROMFILE, "Button",
+ BS_AUTORADIOBUTTON | WS_TABSTOP, 6, 36, 67, 10
+
+ LTEXT "Object &Type:", ID_IO_OBJECTTYPETEXT, 84, 4, 110, 8
+
+ LISTBOX ID_IO_OBJECTTYPELIST, 82, 16, 132, 73, LBS_SORT |
+ LBS_USETABSTOPS | WS_VSCROLL | WS_GROUP | WS_TABSTOP
+
+ LTEXT "Fil&e:", ID_IO_FILETEXT, 82, 24, 20, 8
+ LTEXT "", ID_IO_FILETYPE, 120, 24, 80, 8
+
+ EDITTEXT ID_IO_FILEDISPLAY, 82, 34, 132, 12, ES_AUTOHSCROLL | ES_LOWERCASE | ES_OEMCONVERT
+
+ PUSHBUTTON "&Browse...", ID_IO_FILE, 82, 50, 48, 14
+
+ CONTROL "&Link", ID_IO_LINKFILE, "Button", BS_AUTOCHECKBOX |
+ WS_TABSTOP, 140, 52, 40, 10
+
+ DEFPUSHBUTTON "OK", IDOK, 222, 6, 66, 14, WS_GROUP
+
+ PUSHBUTTON "Cancel", IDCANCEL, 222, 24, 66, 14
+
+ PUSHBUTTON "&Help", ID_OLEUIHELP, 222, 42, 66, 14
+
+ CONTROL "&Display As Icon", ID_IO_DISPLAYASICON, "Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP, 222, 64, 66, 10
+
+ CONTROL "", ID_IO_ICONDISPLAY, SZCLASSICONBOX, 0, 220, 80, 66, 46
+
+ PUSHBUTTON "Change &Icon...", ID_IO_CHANGEICON, 222, 127, 66, 14
+
+ GROUPBOX "Result", ID_STATIC, 6, 96, 210, 47, WS_GROUP
+
+// CONTROL "", ID_IO_RESULTIMAGE, SZCLASSRESULTIMAGE, 0, 10, 106, 42, 34
+
+ LTEXT "Result", ID_IO_RESULTTEXT, 56, 106, 156, 32, SS_NOPREFIX |
+ NOT WS_GROUP
+END
diff --git a/private/oleutest/letest/ole2ui/insobj.h b/private/oleutest/letest/ole2ui/insobj.h
new file mode 100644
index 000000000..1958d7f4f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/insobj.h
@@ -0,0 +1,52 @@
+/*
+ * INSOBJ.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Insert Object dialog.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
+ */
+
+
+#ifndef _INSOBJ_H_
+#define _INSOBJ_H_
+
+//Internally used structure
+typedef struct tagINSERTOBJECT
+ {
+ LPOLEUIINSERTOBJECT lpOIO; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+ DWORD dwFlags;
+ CLSID clsid;
+ TCHAR szFile[OLEUI_CCHPATHMAX];
+ BOOL fFileSelected; //Enables Display As Icon for links
+ BOOL fAsIconNew;
+ BOOL fAsIconFile;
+ BOOL fFileDirty;
+ BOOL fFileValid;
+ UINT nErrCode;
+ HGLOBAL hMetaPictFile;
+ UINT nBrowseHelpID; // Help ID callback for Browse dlg
+ } INSERTOBJECT, *PINSERTOBJECT, FAR *LPINSERTOBJECT;
+
+
+
+//Internal function prototypes
+//INSOBJ.C
+BOOL CALLBACK EXPORT InsertObjectDialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL FInsertObjectInit(HWND, WPARAM, LPARAM);
+UINT UFillClassList(HWND, UINT, LPCLSID, BOOL);
+BOOL FToggleObjectSource(HWND, LPINSERTOBJECT, DWORD);
+void UpdateClassIcon(HWND, LPINSERTOBJECT, HWND);
+void UpdateClassType(HWND, LPINSERTOBJECT, BOOL);
+void SetInsertObjectResults(HWND, LPINSERTOBJECT);
+BOOL FValidateInsertFile(HWND, BOOL, UINT FAR*);
+void InsertObjectCleanup(HWND);
+
+#endif //_INSOBJ_H_
diff --git a/private/oleutest/letest/ole2ui/links.c b/private/oleutest/letest/ole2ui/links.c
new file mode 100644
index 000000000..88c552754
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/links.c
@@ -0,0 +1,2146 @@
+/*
+ * links.c
+ *
+ * Implements the OleUIEditLinks function which invokes the complete
+ * Edit Links dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+
+#include "ole2ui.h"
+#include "common.h"
+#include "edlinks.h"
+#include "utility.h"
+#include <commdlg.h>
+#include <dlgs.h>
+#include <stdlib.h>
+
+OLEDBGDATA
+
+/*
+* OleUIEditLinks
+*
+* Purpose:
+* Invokes the standard OLE Edit Links dialog box allowing the user
+* to manipulate ole links (delete, update, change source, etc).
+*
+* Parameters:
+* lpEL LPOLEUIEditLinks 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
+*/
+
+STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS lpEL)
+{
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpEL, sizeof(OLEUIEDITLINKS)
+ , &hMemDlg);
+
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+ /*
+ * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE!
+ * ON FAILURE:
+ * {
+ * if (NULL!=hMemDlg)
+ * FreeResource(hMemDlg)
+ *
+ * return OLEUI_<ABBREV>ERR_<ERROR>
+ * }
+ */
+
+ //Now that we've validated everything, we can invoke the dialog.
+ uRet=UStandardInvocation(EditLinksDialogProc, (LPOLEUISTANDARD)lpEL,
+ hMemDlg, MAKEINTRESOURCE(IDD_EDITLINKS));
+
+ /*
+ * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
+ */
+
+
+ return uRet;
+}
+
+
+
+/*
+* EditLinksDialogProc
+*
+* Purpose:
+* Implements the OLE Edit Links dialog as invoked through the
+* OleUIEditLinks function.
+*
+* Parameters:
+* Standard
+*
+* Return Value:
+* Standard
+*/
+
+BOOL CALLBACK EXPORT EditLinksDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ LPEDITLINKS lpEL = NULL;
+ BOOL fHook=FALSE;
+ UINT uRet=0;
+ HRESULT hErr;
+ static int nColPos[3];
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ lpEL=(LPEDITLINKS)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &uRet);
+
+ //If the hook processed the message, we're done.
+ if (0!=uRet)
+ return (BOOL)uRet;
+
+ // Process help message from secondary dialog
+ if (iMsg == uMsgHelp) {
+
+ PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp, wParam, lParam);
+ return FALSE;
+
+ }
+
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog) {
+
+ //Free any specific allocations before calling StandardCleanup
+
+ StandardCleanup(lpEL, hDlg);
+
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ switch (iMsg) {
+ static int nHeightLine = -1;
+ static int nMaxCharWidth = -1;
+
+ case WM_INITDIALOG:
+ {
+ RECT rc;
+ int nStart;
+
+ /* calculate the column positions relative to the listbox */
+ GetWindowRect(GetDlgItem(hDlg, ID_EL_LINKSLISTBOX), (LPRECT)&rc);
+ nStart = rc.left;
+ GetWindowRect(GetDlgItem(hDlg, ID_EL_COL1), (LPRECT)&rc);
+ nColPos[0] = rc.left - nStart;
+ GetWindowRect(GetDlgItem(hDlg, ID_EL_COL2), (LPRECT)&rc);
+ nColPos[1] = rc.left - nStart;
+ GetWindowRect(GetDlgItem(hDlg, ID_EL_COL3), (LPRECT)&rc);
+ nColPos[2] = rc.left - nStart;
+
+ return FEditLinksInit(hDlg, wParam, lParam);
+ }
+ break;
+
+ case WM_MEASUREITEM:
+ {
+ LPMEASUREITEMSTRUCT lpMIS;
+
+ lpMIS = (LPMEASUREITEMSTRUCT)lParam;
+
+ if (nHeightLine == -1) {
+ HFONT hFont;
+ HDC hDC;
+ TEXTMETRIC tm;
+
+ /* Attempt to get font dialog. If that fails,
+ use system font
+ */
+
+ hFont = (HANDLE)(UINT)SendMessage(hDlg, WM_GETFONT, 0, 0L);
+
+ if (hFont == NULL)
+ hFont = GetStockObject(SYSTEM_FONT);
+
+ hDC = GetDC(hDlg);
+ hFont = SelectObject(hDC, hFont);
+
+ GetTextMetrics(hDC, &tm);
+ nHeightLine = tm.tmHeight;
+ nMaxCharWidth = tm.tmMaxCharWidth;
+
+ ReleaseDC(hDlg, hDC);
+ }
+
+ lpMIS->itemHeight = nHeightLine;
+ }
+ break;
+
+ case WM_DRAWITEM:
+ {
+ LPDRAWITEMSTRUCT lpDIS;
+ COLORREF crText;
+ LPLINKINFO lpLI;
+ HBRUSH hbr;
+ int nOldBkMode;
+ TCHAR tsz[OLEUI_CCHPATHMAX];
+ LPTSTR lpsz;
+ RECT rcClip;
+
+ lpDIS = (LPDRAWITEMSTRUCT)lParam;
+ lpLI = (LPLINKINFO)lpDIS->itemData;
+
+ if ((int)lpDIS->itemID < 0)
+ break;
+
+ if ((ODA_DRAWENTIRE | ODA_SELECT) & lpDIS->itemAction) {
+
+ if (ODS_SELECTED & lpDIS->itemState) {
+ /*Get proper txt colors */
+ crText = SetTextColor(lpDIS->hDC,
+ GetSysColor(COLOR_HIGHLIGHTTEXT));
+ hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
+ lpLI->fIsSelected = TRUE;
+ }
+ else {
+ hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+ lpLI->fIsSelected = FALSE;
+ }
+
+ FillRect(lpDIS->hDC, &lpDIS->rcItem, hbr);
+ DeleteObject(hbr);
+
+ nOldBkMode = SetBkMode(lpDIS->hDC, TRANSPARENT);
+
+ if (lpLI->lpszDisplayName) {
+ lstrcpy((LPTSTR)tsz, lpLI->lpszDisplayName);
+ lpsz = ChopText(
+ lpDIS->hwndItem,
+ nColPos[1] - nColPos[0]
+ - (nMaxCharWidth > 0 ? nMaxCharWidth : 5),
+ tsz
+ );
+ rcClip.left = lpDIS->rcItem.left + nColPos[0];
+ rcClip.top = lpDIS->rcItem.top;
+ rcClip.right = lpDIS->rcItem.left + nColPos[1]
+ - (nMaxCharWidth > 0 ? nMaxCharWidth : 5);
+ rcClip.bottom = lpDIS->rcItem.bottom;
+ ExtTextOut(
+ lpDIS->hDC,
+ rcClip.left,
+ rcClip.top,
+ ETO_CLIPPED,
+ (LPRECT)&rcClip,
+ lpsz,
+ lstrlen(lpsz),
+ NULL
+ );
+ }
+ if (lpLI->lpszShortLinkType) {
+ rcClip.left = lpDIS->rcItem.left + nColPos[1];
+ rcClip.top = lpDIS->rcItem.top;
+ rcClip.right = lpDIS->rcItem.left + nColPos[2]
+ - (nMaxCharWidth > 0 ? nMaxCharWidth : 5);
+
+ rcClip.bottom = lpDIS->rcItem.bottom;
+ ExtTextOut(
+ lpDIS->hDC,
+ rcClip.left,
+ rcClip.top,
+ ETO_CLIPPED,
+ (LPRECT)&rcClip,
+ lpLI->lpszShortLinkType,
+ lstrlen(lpLI->lpszShortLinkType),
+ NULL
+ );
+ }
+ if (lpLI->lpszAMX) {
+ rcClip.left = lpDIS->rcItem.left + nColPos[2];
+ rcClip.top = lpDIS->rcItem.top;
+ rcClip.right = lpDIS->rcItem.right;
+ rcClip.bottom = lpDIS->rcItem.bottom;
+ ExtTextOut(
+ lpDIS->hDC,
+ rcClip.left,
+ rcClip.top,
+ ETO_CLIPPED,
+ (LPRECT)&rcClip,
+ lpLI->lpszAMX,
+ lstrlen(lpLI->lpszAMX),
+ NULL
+ );
+ }
+
+ SetBkMode(lpDIS->hDC, nOldBkMode);
+
+ // restore orig colors if we changed them
+ if (ODS_SELECTED & lpDIS->itemState)
+ SetTextColor(lpDIS->hDC, crText);
+
+ }
+
+ InitControls(hDlg, lpEL);
+
+ if (ODA_FOCUS & lpDIS->itemAction)
+ DrawFocusRect(lpDIS->hDC, &lpDIS->rcItem);
+
+ }
+ return TRUE;
+
+
+ case WM_DELETEITEM:
+ {
+ UINT idCtl;
+ LPDELETEITEMSTRUCT lpDIS;
+ LPLINKINFO lpLI;
+
+ lpDIS = (LPDELETEITEMSTRUCT)lParam;
+ idCtl = wParam;
+ lpLI = (LPLINKINFO)lpDIS->itemData;
+
+ if (lpLI->lpszDisplayName)
+ OleStdFree((LPVOID)lpLI->lpszDisplayName);
+ if (lpLI->lpszShortLinkType)
+ OleStdFree((LPVOID)lpLI->lpszShortLinkType);
+ if (lpLI->lpszFullLinkType)
+ OleStdFree((LPVOID)lpLI->lpszFullLinkType);
+
+ /* The ChangeSource processing reuses allocated space for
+ ** links that have been modified.
+ */
+ // Don't free the LINKINFO for the changed links
+ if (lpLI->fDontFree)
+ lpLI->fDontFree = FALSE;
+ else {
+ if (lpLI->lpszAMX)
+ OleStdFree((LPVOID)lpLI->lpszAMX);
+ OleStdFree((LPVOID)lpLI);
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMPAREITEM:
+ {
+ LPCOMPAREITEMSTRUCT lpCIS = (LPCOMPAREITEMSTRUCT)lParam;
+ LPLINKINFO lpLI1 = (LPLINKINFO)lpCIS->itemData1;
+ LPLINKINFO lpLI2 = (LPLINKINFO)lpCIS->itemData2;
+
+ // Sort list entries by DisplayName
+ return lstrcmp(lpLI1->lpszDisplayName,lpLI2->lpszDisplayName);
+ }
+
+ case WM_COMMAND:
+ switch (wID) {
+
+ case ID_EL_CHANGESOURCE:
+ {
+ BOOL fRet = FALSE;
+
+ /* This will bring up the file open dlg with one
+ edit field containing the whole link name. The file part
+ will (eventually) be highlighted to indicate where the
+ file part is. We need to hook on OK here to be able to
+ send the changed string to the Parse function */
+
+ fRet = Container_ChangeSource(hDlg, lpEL);
+ if (!fRet)
+ PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
+ MB_ICONEXCLAMATION | MB_OK);
+ InitControls(hDlg, lpEL);
+ }
+ break;
+
+ case ID_EL_AUTOMATIC:
+ {
+ /* This is available for single or multi-select. There is
+ a flag in the structure that is set initially indicating
+ whether the link is auto or manual so that we need not
+ query the link each time we want to find out.
+
+ This command will make the link automatic if not already.
+ It will have no effect on links already set to auto.
+ */
+ // turn the button ON
+
+ CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 1);
+ CheckDlgButton(hDlg, ID_EL_MANUAL, 0);
+
+ hErr = Container_AutomaticManual(hDlg, TRUE, lpEL);
+ if (hErr != NOERROR)
+ PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
+ MB_ICONEXCLAMATION | MB_OK);
+
+ InitControls(hDlg, lpEL);
+ }
+ break;
+
+ case ID_EL_MANUAL:
+ {
+ /* Same rules apply here as they do to auto link.
+ Additional note - just because something is changed does
+ not mean that it updates at the moment. It simply
+ reflects what kind of updating it does while it lives in
+ the document.
+ */
+ // turn the button ON
+
+ CheckDlgButton(hDlg, ID_EL_MANUAL, 1);
+ CheckDlgButton(hDlg, ID_EL_AUTOMATIC, 0);
+
+ hErr = Container_AutomaticManual(hDlg, FALSE, lpEL);
+ if (hErr != NOERROR)
+ PopupMessage(hDlg, IDS_LINKS, IDS_FAILED,
+ MB_ICONEXCLAMATION | MB_OK);
+
+ InitControls(hDlg, lpEL);
+ }
+ break;
+
+ case ID_EL_CANCELLINK:
+ {
+ /* This is Break Link now in the dlg. This sets the
+ moniker to null, thereby effectively breaking the link.
+ The object still has its data effective at the time of
+ breaking, but becomes a static object.
+ *****It will need to be deleted from the listbox
+ */
+
+ CancelLink(hDlg,lpEL);
+ InitControls(hDlg, lpEL);
+ }
+ break;
+
+ case ID_EL_UPDATENOW:
+ {
+ /* This forces an immediate update of the selected
+ links. This will start the server etc, so this is a very
+ expensive operation.
+ */
+ hErr = Container_UpdateNow(hDlg, lpEL);
+ InitControls(hDlg, lpEL);
+ }
+ break;
+
+ case ID_EL_OPENSOURCE:
+ {
+ /* This will only work on single selection. It makes no
+ sense to open multiple sources at the same time, since
+ the one opened will try to show itself and become the
+ primary operating target, so to speak. Button is greyed
+ if multi select.
+
+ Here we do not add the break because we want to exit the
+ dlg in this case.
+ */
+ hErr = Container_OpenSource(hDlg, lpEL);
+ if (hErr != NOERROR) {
+ InitControls(hDlg, lpEL);
+ break; // don't close dialog
+ }
+ } // fall through
+
+ case ID_EL_CLOSE:
+ {
+ /* The user is finished with their editing - they now
+ return to their container document.
+
+ */
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ }
+ break;
+
+ case IDCANCEL:
+ {
+ /* This changes to CLOSE after the user does even ONE
+ thing in the dlg. Nothing can really effectively be undone.
+ */
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ }
+ break;
+
+ case ID_OLEUIHELP:
+ {
+ PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp
+ , (WPARAM)hDlg, MAKELPARAM(IDD_EDITLINKS, 0));
+ break;
+ }
+ break;
+ }
+ break;
+
+ default:
+ {
+ if (lpEL && iMsg == lpEL->nChgSrcHelpID) {
+ PostMessage(lpEL->lpOEL->hWndOwner, uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_CHANGESOURCE, 0));
+ }
+ }
+ break;
+ }
+
+ return FALSE;
+}
+
+
+/*
+ * FEditLinksInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Edit Links dialog box.
+ *
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FEditLinksInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ LPEDITLINKS lpEL;
+ LPOLEUIEDITLINKS lpOEL;
+ HFONT hFont;
+ BOOL fDlgItem = FALSE;
+ DWORD dwLink = 0;
+ ULONG cLinks;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr;
+ int n;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+
+
+
+ //1. Copy the structure at lParam into our instance memory.
+ lpEL = (LPEDITLINKS)LpvStandardInit(hDlg, sizeof(OLEUIEDITLINKS), TRUE,
+ &hFont);
+
+ //PvStandardInit send a termination to us already.
+ if (NULL==lpEL)
+ return FALSE;
+
+ lpOEL=(LPOLEUIEDITLINKS)lParam;
+
+ lpEL->lpOEL=lpOEL;
+
+ lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+
+ cLinks = LoadLinkLB(hListBox, lpOleUILinkCntr);
+ if (cLinks < 0)
+ return FALSE;
+
+ fDlgItem = (BOOL)cLinks;
+ lpEL->fItemsExist = (BOOL)cLinks;
+
+
+ InitControls(hDlg, lpEL);
+
+ //Copy other information from lpOEL that we might modify.
+
+ //2. 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, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+
+ //3. Show or hide the help button
+ if (!(lpEL->lpOEL->dwFlags & ELF_SHOWHELP))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+ /*
+ * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
+ * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
+ */
+
+ //4. If requested disable UpdateNow button
+ if ((lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
+ StandardShowDlgItem(hDlg, ID_EL_UPDATENOW, SW_HIDE);
+
+ //5. If requested disable OpenSource button
+ if ((lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
+ StandardShowDlgItem(hDlg, ID_EL_OPENSOURCE, SW_HIDE);
+
+ //6. If requested disable UpdateNow button
+ if ((lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
+ StandardShowDlgItem(hDlg, ID_EL_CHANGESOURCE, SW_HIDE);
+
+ //7. If requested disable CancelLink button
+ if ((lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
+ StandardShowDlgItem(hDlg, ID_EL_CANCELLINK, SW_HIDE);
+
+ //8. Load 'Close' string used to rename Cancel button
+ n = LoadString(ghInst, IDS_CLOSE, lpEL->szClose, sizeof(lpEL->szClose)/sizeof(TCHAR));
+ if (!n)
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
+ return FALSE;
+ }
+
+ if (cLinks > 0)
+ SetFocus(hListBox);
+ else
+ SetFocus(GetDlgItem(hDlg, IDCANCEL));
+
+ lpEL->nChgSrcHelpID = RegisterWindowMessage(HELPMSGSTRING);
+
+ //n. Call the hook with lCustData in lParam
+ UStandardHook(lpEL, hDlg, WM_INITDIALOG, wParam, lpOEL->lCustData);
+
+ return FALSE;
+}
+
+
+
+/*
+ * ChangeSourceHook
+ *
+ * Purpose:
+ * Hooks the ChangeSource dialog to attempt to validate link source changes
+ * specified by the user.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * uMsg UINT Message
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * UNIT Zero = Do default processing;
+ * Non Zero = Don't do default processing.
+ */
+
+UINT CALLBACK EXPORT ChangeSourceHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LPCHANGESOURCEHOOKDATA lpCshData = NULL;
+ LPLINKINFO lpLI = NULL;
+ LPEDITLINKS lpEL = NULL;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr;
+ HRESULT hErr;
+ UINT uRet;
+ ULONG ulChEaten;
+ HGLOBAL gh;
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ if (NULL!=(gh = GetProp(hDlg, STRUCTUREPROP)))
+ {
+ // gh was locked previously, lock and unlock to get lpv
+ lpCshData=(LPCHANGESOURCEHOOKDATA)GlobalLock(gh);
+ GlobalUnlock(gh);
+ if (lpCshData)
+ {
+ lpLI = lpCshData->lpOCshData->lpLI;
+ lpEL = lpCshData->lpOCshData->lpEL;
+ }
+ }
+
+ //Process the temination message
+ if (uMsg==uMsgEndDialog)
+ {
+ if (NULL!=(gh = RemoveProp(hDlg, STRUCTUREPROP)))
+ {
+ GlobalUnlock(gh);
+ GlobalFree(gh);
+ }
+ return TRUE;
+ }
+
+ // User pressed the OK button
+ if (uMsg == uMsgFileOKString) {
+ lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+
+ /* NOTE: trigger the focus lost of the edit control. This is
+ ** not necessary if the user click OK with the mouse but is
+ ** needed when the user just press <Enter>. If the mouse was
+ ** used, no extra is done as the MODIFY flag of the edit control
+ ** has been cleared.
+ */
+ SendMessage(hDlg, WM_COMMAND, edt1,
+ MAKELPARAM(GetDlgItem(hDlg, edt1), EN_KILLFOCUS));
+ if (lpCshData->bItemNameStored) {
+ lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit) -
+ lstrlen((LPTSTR)lpCshData->szItemName);
+ }
+ else {
+ lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
+ }
+
+ // Try to validate link source change
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPTSTR)lpCshData->szEdit,
+ (ULONG)lpCshData->nFileLength,
+ &ulChEaten,
+ TRUE
+ );
+ OLEDBG_END2
+
+ // Link source change not validated
+ if (hErr != NOERROR) {
+ uRet =PopupMessage(hDlg, IDS_CHANGESOURCE, IDS_INVALIDSOURCE,
+ MB_ICONQUESTION | MB_YESNO);
+
+ if (uRet == IDYES) {
+ /* User wants to correct invalid link. Set the edit
+ ** control selection to the invalid part of the contents.
+ */
+ SetFocus(GetDlgItem(hDlg, edt1));
+ SendDlgItemMessage(hDlg, edt1, EM_SETSEL, 0,
+ MAKELPARAM(ulChEaten, -1));
+ return 1; // Don't close ChangeSource dialog
+ }
+ else {
+ /* User does not want to correct invalid link. So set
+ ** the link source but don't validate the link.
+ */
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkSource called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPTSTR)lpCshData->szEdit,
+ (ULONG)lpCshData->nFileLength,
+ &ulChEaten,
+ FALSE
+ );
+ OLEDBG_END2
+ lpCshData->fValidLink = FALSE;
+ }
+ }
+ else { // Link source change validated
+ lpCshData->fValidLink = TRUE;
+ }
+
+ if (lpCshData->bItemNameStored && lpCshData->bFileNameStored) {
+ HWND hListBox = GetDlgItem(lpCshData->lpOfn->hwndOwner, ID_EL_LINKSLISTBOX);
+
+ DiffPrefix(
+ lpLI->lpszDisplayName,
+ (LPTSTR)lpCshData->szEdit,
+ (TCHAR FAR* FAR*)&lpCshData->lpszFrom,
+ (TCHAR FAR* FAR*)&lpCshData->lpszTo
+ );
+
+ /* we keep the strings if there is a difference between the
+ ** lpszFrom and lpszTo strings AND if the change is only
+ ** in the file portion otherwise free them and other
+ ** links won't be compared.
+ */
+ if ( (lstrcmp(lpCshData->lpszTo, lpCshData->lpszFrom)==0)
+ || (lstrlen(lpCshData->lpszTo)>lpCshData->nFileLength)) {
+ if (lpCshData->lpszFrom) {
+ OleStdFree(lpCshData->lpszFrom);
+ lpCshData->lpszFrom = NULL;
+ }
+ if (lpCshData->lpszTo) {
+ OleStdFree(lpCshData->lpszTo);
+ lpCshData->lpszTo = NULL;
+ }
+ }
+ }
+
+ // Copy OUT results to original structure
+ lpCshData->lpOCshData->lpszFrom = lpCshData->lpszFrom;
+ lpCshData->lpOCshData->lpszTo = lpCshData->lpszTo;
+ lpCshData->lpOCshData->fValidLink = lpCshData->fValidLink;
+
+ SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
+ return 0; // Close ChangeSource dialog
+ }
+
+ switch (uMsg) {
+ case WM_INITDIALOG:
+ {
+ LPOPENFILENAME lpOfn = (LPOPENFILENAME)lParam;
+ LPOLEUICHANGESOURCEHOOKDATA lpOCshData =
+ (LPOLEUICHANGESOURCEHOOKDATA)lpOfn->lCustData;
+
+ gh=GlobalAlloc(
+ GMEM_MOVEABLE|GMEM_ZEROINIT,sizeof(CHANGESOURCEHOOKDATA));
+ if (NULL==gh)
+ {
+ // Memory allocation error; fail to bring up dialog
+ PostMessage(hDlg, uMsgEndDialog, 0, 0L);
+ return 0;
+ }
+ lpCshData = GlobalLock(gh);
+ SetProp(hDlg, STRUCTUREPROP, gh);
+
+ lpCshData->lpOCshData = lpOCshData;
+ lpCshData->lpOfn = lpOfn;
+ lpLI = lpCshData->lpOCshData->lpLI;
+
+ lpCshData->bFileNameStored = TRUE;
+ lpCshData->bItemNameStored = TRUE;
+ lpCshData->nFileLength = (int)lpLI->clenFileName;
+ if (lpLI->lpszDisplayName) {
+ LSTRCPYN((LPTSTR)lpCshData->szFileName, lpLI->lpszDisplayName,
+ lpCshData->nFileLength + 1);
+ lstrcpy((LPTSTR)lpCshData->szEdit, lpLI->lpszDisplayName);
+ } else {
+ lpCshData->szFileName[0] = TEXT('\0');
+ lpCshData->szEdit[0] = TEXT('\0');
+ }
+ if (lpLI->lpszItemName)
+ lstrcpy((LPTSTR)lpCshData->szItemName, lpLI->lpszItemName);
+ else
+ lpCshData->szItemName[0] = TEXT('\0');
+
+ return 0;
+ }
+
+ case WM_COMMAND:
+
+ // User pressed the CANCEL button
+ if (wParam == IDCANCEL)
+ {
+ if (lpCshData->lpszFrom)
+ {
+ OleStdFree(lpCshData->lpszFrom);
+ lpCshData->lpszFrom = NULL;
+ }
+ if (lpCshData->lpszTo)
+ {
+ OleStdFree(lpCshData->lpszTo);
+ lpCshData->lpszTo = NULL;
+ }
+
+ // Copy OUT results to original structure
+ lpCshData->lpOCshData->lpszFrom = NULL;
+ lpCshData->lpOCshData->lpszTo = NULL;
+ lpCshData->lpOCshData->fValidLink = FALSE;
+
+ SendMessage(hDlg, uMsgEndDialog, 0, 0L); // do cleanup
+ return 0; // Close ChangeSource dialog
+ }
+
+ if ((wParam == lst1) &&
+ (HIWORD(lParam) == LBN_SELCHANGE)) {
+
+ int nIndex;
+ HWND hListBox = (HWND)LOWORD(lParam);
+ static TCHAR szFileNameBuf[OLEUI_CCHPATHMAX];
+ static TCHAR szEditBuf[OLEUI_CCHPATHMAX];
+
+ nIndex = (int)SendMessage(hListBox, LB_GETCURSEL, 0, 0L);
+ SendMessage(hListBox, LB_GETTEXT,
+ (WPARAM)nIndex, (LPARAM)(LPTSTR)szFileNameBuf);
+
+ /* need to build the full path filename for the moniker */
+#ifdef WIN32
+ CharToOem(szFileNameBuf, szFileNameBuf);
+#else
+ AnsiToOem(szFileNameBuf, szFileNameBuf);
+#endif
+ _fullpath(szEditBuf, szFileNameBuf, sizeof(szEditBuf));
+#ifdef WIN32
+ OemToChar(szEditBuf, szEditBuf);
+#else
+ OemToAnsi(szEditBuf, szEditBuf);
+#endif
+
+ /* convert filename to lower case as it appears in the
+ ** listbox
+ */
+#ifdef WIN32
+ CharLower(szEditBuf);
+#else
+ AnsiLower(szEditBuf);
+#endif
+ LSTRCPYN((LPTSTR)lpCshData->szEdit, (LPTSTR)szEditBuf,
+ sizeof(lpCshData->szEdit) / sizeof(TCHAR));
+ LSTRCPYN((LPTSTR)lpCshData->szFileName,
+ (LPTSTR)lpCshData->szEdit,
+ sizeof(lpCshData->szFileName) / sizeof(TCHAR) );
+ lpCshData->nFileLength = lstrlen((LPTSTR)lpCshData->szEdit);
+ if (lpCshData->bItemNameStored)
+ lstrcat((LPTSTR)lpCshData->szEdit, lpCshData->szItemName);
+
+ SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szEdit);
+ lpCshData->nEditLength = lstrlen((LPTSTR)lpCshData->szEdit);
+ lpCshData->bFileNameStored = TRUE;
+
+ return 1;
+ }
+
+ if ((wParam == lst2) &&
+ (HIWORD(lParam) == LBN_SELCHANGE)) {
+
+ if (lpCshData->bItemNameStored)
+ SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
+
+ return 1;
+ }
+
+ if ((wParam == cmb2) &&
+ (HIWORD(lParam) == CBN_SELCHANGE)) {
+
+ if (lpCshData->bItemNameStored)
+ SetDlgItemText(hDlg, edt1, (LPTSTR)lpCshData->szItemName);
+
+ return 1;
+ }
+
+ if (wParam == edt1) {
+ HWND hEdit = (HWND)LOWORD(lParam);
+
+ switch (HIWORD(lParam)) {
+ case EN_SETFOCUS:
+ SendMessage(hEdit, EM_SETSEL, 0,
+ MAKELPARAM(0, lpCshData->nFileLength));
+ return 1;
+
+ case EN_KILLFOCUS:
+ if (SendMessage(hEdit, EM_GETMODIFY, 0, 0L)) {
+ TCHAR szTmp[OLEUI_CCHPATHMAX];
+ int nItemLength = lstrlen((LPTSTR)lpCshData->szItemName);
+
+ *(LPWORD)lpCshData->szEdit = sizeof(lpCshData->szEdit)/
+ sizeof(TCHAR) - 1;
+ lpCshData->nEditLength = (int)SendMessage(hEdit,
+ EM_GETLINE, 0, (LPARAM)(LPTSTR)lpCshData->szEdit);
+ lpCshData->szEdit[lpCshData->nEditLength] = TEXT('\0');
+ LSTRCPYN((LPTSTR)szTmp, (LPTSTR)lpCshData->szEdit,
+ lpCshData->nFileLength + 1);
+
+ if (lpCshData->bFileNameStored &&
+ !lstrcmp((LPTSTR)lpCshData->szFileName, (LPTSTR)szTmp)) {
+ lstrcpy((LPTSTR)lpCshData->szItemName,
+ (LPTSTR)lpCshData->szEdit + lpCshData->nFileLength);
+ lpCshData->bItemNameStored = TRUE;
+ }
+ else if (lpCshData->bItemNameStored &&
+ !lstrcmp((LPTSTR)lpCshData->szItemName,
+ (LPTSTR)lpCshData->szEdit +
+ lpCshData->nEditLength -
+ nItemLength)) {
+ if (lpCshData->nEditLength==nItemLength) {
+
+ lpCshData->bFileNameStored = FALSE;
+ } else {
+ LSTRCPYN((LPTSTR)lpCshData->szFileName,
+ (LPTSTR)lpCshData->szEdit,
+ lpCshData->nEditLength -
+ nItemLength+1);
+ lpCshData->bFileNameStored = TRUE;
+ }
+ }
+ else {
+ lpCshData->bItemNameStored = FALSE;
+ lpCshData->bFileNameStored = FALSE;
+ }
+
+ SendMessage(hEdit, EM_SETMODIFY, FALSE, 0L);
+ }
+ return 0;
+ }
+ }
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+
+/*
+* ChangeSource
+*
+* Purpose:
+* Displays the standard GetOpenFileName dialog with a customized template and
+* hook.
+*
+* Parameters:
+* hWndOwner HWND owning the dialog
+* lpszFile LPSTR specifying the initial file. If there is no
+* initial file the first character of this string should
+* be a null.
+* cchFile UINT length of pszFile
+* iFilterString UINT index into the stringtable for the filter string.
+* lpfnBrowseHook COMMDLGHOOKPROC hook to process link source information when user
+* presses OK
+* lpCshData LPCHANGESOURCEHOOKDATA custom data that is accessible to the hook
+*
+* Return Value:
+* BOOL TRUE if the user selected a file and pressed OK.
+* FALSE otherwise, such as on pressing Cancel.
+*/
+
+BOOL WINAPI ChangeSource(
+ HWND hWndOwner,
+ LPTSTR lpszFile,
+ UINT cchFile,
+ UINT iFilterString,
+ COMMDLGHOOKPROC lpfnBrowseHook,
+ LPOLEUICHANGESOURCEHOOKDATA lpCshData
+)
+{
+ UINT cch;
+ TCHAR szFilters[OLEUI_CCHPATHMAX];
+ TCHAR szDir[OLEUI_CCHPATHMAX];
+ TCHAR szTitle[OLEUI_CCHPATHMAX];
+ OPENFILENAME ofn;
+ BOOL fStatus;
+ LPTSTR lpszFileBuffer;
+
+ if (NULL==lpszFile || 0==cchFile)
+ return FALSE;
+
+ lpszFileBuffer = (LPTSTR)OleStdMalloc(cchFile * sizeof(TCHAR));
+ if (!lpszFileBuffer)
+ return FALSE;
+
+ lstrcpy(lpszFileBuffer, lpszFile);
+
+ // Get filters
+ if (0!=iFilterString)
+ cch = LoadString(ghInst, iFilterString, (LPTSTR)szFilters,
+ OLEUI_CCHPATHMAX);
+ else
+ {
+ szFilters[0]=0;
+ cch=1;
+ }
+ if (0==cch) {
+ fStatus = FALSE;
+ goto cleanup;
+ }
+
+ ReplaceCharWithNull(szFilters, szFilters[cch-1]);
+
+ LSTRCPYN((LPTSTR)szDir, lpszFile, OLEUI_CCHPATHMAX);
+ for (cch = lstrlen((LPTSTR)szDir) - 1; cch >= 0; cch--)
+ {
+ if ((szDir[cch]==TEXT('\\')) || (szDir[cch]==TEXT(':')) || (szDir[cch]==TEXT('/')))
+ break;
+ }
+ if (cch < 0)
+ cch = 0;
+
+ szDir[cch] = TEXT('\0');
+
+ LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle, OLEUI_CCHPATHMAX);
+ _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hWndOwner;
+ ofn.lpstrFile = lpszFileBuffer;
+ ofn.nMaxFile = cchFile;
+ ofn.lpstrFilter = (LPTSTR)szFilters;
+ ofn.nFilterIndex = 1;
+ ofn.lpstrTitle = (LPTSTR)szTitle;
+ ofn.lpstrInitialDir = (LPTSTR)szDir;
+ ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN);
+ ofn.lpfnHook = lpfnBrowseHook;
+ ofn.hInstance = ghInst;
+ ofn.lCustData = (LPARAM)lpCshData;
+ ofn.Flags = OFN_NOVALIDATE | OFN_HIDEREADONLY |
+ OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;
+
+ // Only show help button if edit links dialog shows it.
+ if (lpCshData->lpEL->lpOEL->dwFlags & ELF_SHOWHELP)
+ ofn.Flags |= OFN_SHOWHELP;
+
+ fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
+
+cleanup:
+ OleStdFree((LPVOID)lpszFileBuffer);
+ return fStatus;
+
+}
+
+/*
+* Container_ChangeSource
+*
+* Purpose:
+* Tunnel to File Open type dlg and allow user to select new file
+* for file based monikers, OR to change the whole moniker to what
+* the user types into the editable field.
+*
+* Parameters:
+* hDlg HWND of the dialog
+* LPEDITLINKS Pointer to EditLinks structure (contains all nec.
+* info)
+*
+* Return Value:
+* BOOL for now, because we are not using any ole functions
+* to return an HRESULT.
+* HRESULT HRESULT value indicating success or failure of
+* changing the moniker value
+*/
+
+BOOL Container_ChangeSource(HWND hDlg, LPEDITLINKS lpEL)
+{
+ UINT uRet;
+ int cSelItems;
+ int FAR* rgIndex;
+ int i = 0;
+ LPLINKINFO lpLI;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+ LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+ OLEUICHANGESOURCEHOOKDATA cshData; // Data that needs to be accessed
+ // by the ChangeSource dialog hook
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+
+ if (cSelItems < 0)
+ return FALSE;
+
+ if (!cSelItems)
+ return TRUE;
+
+ if (!lpEL->fClose) {
+ SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
+ lpEL->fClose = TRUE;
+ }
+
+ _fmemset((LPOLEUICHANGESOURCEHOOKDATA)&cshData, 0, sizeof(cshData));
+ cshData.cbStruct=sizeof(cshData);
+ cshData.hWndOwner=hDlg;
+ cshData.lpEL = (LPEDITLINKS)lpEL;
+ cshData.lpszFrom = NULL;
+ cshData.lpszTo = NULL;
+
+ for (i = cSelItems-1; i >=0; i--) {
+ SendMessage(hListBox, LB_GETTEXT, rgIndex[i],
+ (LPARAM) (LPLINKINFO FAR*) &lpLI);
+
+ uRet = UStandardHook(lpEL, hDlg, uMsgBrowse,
+ OLEUI_CCHPATHMAX_SIZE, (LONG)(LPTSTR)lpLI->lpszDisplayName);
+
+ if (!uRet) {
+ cshData.lpLI = lpLI;
+ /* Bring up the ChangeSource dialog after hooking it so
+ ** that the user specified link source is verified
+ ** when OK is pressed.
+ */
+ uRet = (UINT)ChangeSource(hDlg, lpLI->lpszDisplayName,
+ OLEUI_CCHPATHMAX, IDS_FILTERS, ChangeSourceHook,
+ &cshData);
+ }
+
+ /* If Cancel is pressed in any ChangeSource dialog, stop
+ ** the ChangeSource processing for all links.
+ */
+ if (!uRet) {
+ if (rgIndex)
+ OleStdFree(rgIndex);
+ return TRUE;
+ }
+
+ UpdateLinkLBItem(hListBox, rgIndex[i], lpEL, TRUE);
+
+ if (cshData.lpszFrom && cshData.lpszTo) {
+ ChangeAllLinks(hListBox, lpOleUILinkCntr, cshData.lpszFrom,
+ cshData.lpszTo);
+ OleStdFree(cshData.lpszFrom);
+ OleStdFree(cshData.lpszTo);
+ }
+
+ } // end FOR
+
+
+ if (rgIndex)
+ OleStdFree(rgIndex);
+
+ return TRUE;
+
+}
+
+
+/*
+* Container_AutomaticManual
+*
+* Purpose:
+* To change the selected moniker to manual or automatic update.
+*
+* Parameters:
+* hDlg HWND of the dialog
+* FAutoMan Flag indicating AUTO (TRUE/1) or MANUAL(FALSE/0)
+* LPEDITLINKS Pointer to EditLinks structure (contains all nec.
+* info)
+* * this may change - don't know how the linked list
+* * of multi-selected items will work.
+* Return Value:
+* HRESULT HRESULT value indicating success or failure of
+* changing the moniker value
+*/
+
+HRESULT Container_AutomaticManual(HWND hDlg, BOOL fAutoMan, LPEDITLINKS lpEL)
+{
+
+ HRESULT hErr = NOERROR;
+ int cSelItems;
+ int FAR* rgIndex;
+ int i = 0;
+ LPLINKINFO lpLI;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+ BOOL bUpdate = FALSE;
+
+ OleDbgAssert(lpOleUILinkCntr);
+
+ /* Change so looks at flag in structure. Only update those that
+ need to be updated. Make sure to change flag if status changes.
+ */
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+
+ if (cSelItems < 0)
+ return ResultFromScode(E_FAIL);
+
+ if (!cSelItems)
+ return NOERROR;
+
+ if (!lpEL->fClose)
+ SetDlgItemText(hDlg, IDCANCEL, (LPTSTR)lpEL->szClose);
+
+ for (i = 0; i < cSelItems; i++) {
+ SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
+ (LPARAM) (LPLINKINFO FAR*) &lpLI);
+
+ if (fAutoMan) { // If switching to AUTOMATIC
+ if (!lpLI->fIsAuto) { // Only change MANUAL links
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
+ hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ OLEUPDATE_ALWAYS
+ );
+ OLEDBG_END2
+
+ lpLI->fIsAuto=TRUE;
+ lpLI->fIsMarked = TRUE;
+ bUpdate = TRUE;
+ }
+ }
+ else { // If switching to MANUAL
+ if (lpLI->fIsAuto) { // Only do AUTOMATIC Links
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::SetLinkUpdateOptions called\r\n"));
+ hErr=lpOleUILinkCntr->lpVtbl->SetLinkUpdateOptions(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ OLEUPDATE_ONCALL
+ );
+ OLEDBG_END2
+
+ lpLI->fIsAuto = FALSE;
+ lpLI->fIsMarked = TRUE;
+ bUpdate = TRUE;
+ }
+ }
+
+ if (hErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::SetLinkUpdateOptions returned"),hErr);
+ break;
+ }
+
+ }
+
+ if (bUpdate)
+ RefreshLinkLB(hListBox, lpOleUILinkCntr);
+
+ if (rgIndex)
+ OleStdFree((LPVOID)rgIndex);
+
+ return hErr;
+}
+
+
+HRESULT CancelLink(HWND hDlg, LPEDITLINKS lpEL)
+{
+ HRESULT hErr;
+ LPMONIKER lpmk;
+ int cSelItems;
+ int FAR* rgIndex;
+ int i = 0;
+ LPLINKINFO lpLI;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+ BOOL bUpdate = FALSE;
+
+ OleDbgAssert(lpOleUILinkCntr);
+
+ lpmk = NULL;
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+
+ if (cSelItems < 0)
+ return ResultFromScode(E_FAIL);
+
+ if (!cSelItems)
+ return NOERROR;
+
+ if (!lpEL->fClose) {
+ SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
+ lpEL->fClose = TRUE;
+ }
+
+ for (i = 0; i < cSelItems; i++) {
+ SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[i],
+ (LPARAM)(LPLINKINFO FAR*) &lpLI);
+
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::CancelLink called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->CancelLink(
+ lpOleUILinkCntr,
+ lpLI->dwLink
+ );
+ OLEDBG_END2
+
+ if (hErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::CancelLink returned"),hErr);
+ lpLI->fIsMarked = TRUE;
+ bUpdate = TRUE;
+ }
+ else
+ // Delete links that we make null from listbox
+ SendMessage(hListBox, LB_DELETESTRING, (WPARAM) rgIndex[i], 0L);
+
+ }
+
+ if (bUpdate)
+ RefreshLinkLB(hListBox, lpOleUILinkCntr);
+
+ if (rgIndex)
+ OleStdFree((LPVOID)rgIndex);
+
+ return hErr;
+
+}
+
+
+/*
+ * Container_UpdateNow
+ *
+ * Purpose:
+ * Immediately force an update for all (manual) links
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * LPEDITLINKS Pointer to EditLinks structure (contains all nec. info)
+ * * this may change - don't know how the linked list
+ * * of multi-selected items will work.
+ * Return Value:
+ * HRESULT HRESULT value indicating success or failure of
+ * changing the moniker value
+ */
+
+HRESULT Container_UpdateNow(HWND hDlg, LPEDITLINKS lpEL)
+{
+ HRESULT hErr;
+ LPLINKINFO lpLI;
+ int cSelItems;
+ int FAR* rgIndex;
+ int i = 0;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+ BOOL bUpdate = FALSE;
+
+ OleDbgAssert(lpOleUILinkCntr);
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+
+ if (cSelItems < 0)
+ return ResultFromScode(E_FAIL);
+
+ if (!cSelItems)
+ return NOERROR;
+
+ if (!lpEL->fClose) {
+ SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
+ lpEL->fClose = TRUE;
+ }
+
+ for (i = 0; i < cSelItems; i++) {
+ SendMessage(hListBox, LB_GETTEXT,
+ (WPARAM)rgIndex[i], (LPARAM)(LPLINKINFO FAR*)&lpLI);
+
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::UpdateLink called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->UpdateLink(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ TRUE,
+ FALSE
+ );
+ OLEDBG_END2
+ bUpdate = TRUE;
+ lpLI->fIsMarked = TRUE;
+
+ if (hErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::UpdateLink returned"),hErr);
+ break;
+ }
+
+ }
+
+ if (bUpdate)
+ RefreshLinkLB(hListBox, lpOleUILinkCntr);
+
+ if (rgIndex)
+ OleStdFree((LPVOID)rgIndex);
+
+ return hErr;
+
+}
+
+/*
+ * Container_OpenSource
+ *
+ * Purpose:
+ * Immediately force an update for all (manual) links
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * LPEDITLINKS Pointer to EditLinks structure (contains all nec.
+ * info)
+ *
+ * Return Value:
+ * HRESULT HRESULT value indicating success or failure of
+ * changing the moniker value
+ */
+
+HRESULT Container_OpenSource(HWND hDlg, LPEDITLINKS lpEL)
+{
+ HRESULT hErr;
+ int cSelItems;
+ int FAR* rgIndex;
+ LPLINKINFO lpLI;
+ RECT rcPosRect;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+ HWND hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+
+ OleDbgAssert(lpOleUILinkCntr);
+
+ rcPosRect.top = 0;
+ rcPosRect.left = 0;
+ rcPosRect.right = 0;
+ rcPosRect.bottom = 0;
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+
+ if (cSelItems < 0)
+ return ResultFromScode(E_FAIL);
+
+ if (cSelItems != 1) // can't open source for multiple items
+ return NOERROR;
+
+ if (!lpEL->fClose) {
+ SetWindowText(GetDlgItem(hDlg, IDCANCEL), (LPTSTR)lpEL->szClose);
+ lpEL->fClose = TRUE;
+ }
+
+ SendMessage(hListBox, LB_GETTEXT, (WPARAM)rgIndex[0],
+ (LPARAM)(LPLINKINFO FAR*)&lpLI);
+
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::OpenLinkSource called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->OpenLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink
+ );
+ OLEDBG_END2
+
+ UpdateLinkLBItem(hListBox, rgIndex[0], lpEL, TRUE);
+ if (hErr != NOERROR)
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::OpenLinkSource returned"),hErr);
+
+ if (rgIndex)
+ OleStdFree((LPVOID)rgIndex);
+
+ return hErr;
+}
+
+
+
+/* AddLinkLBItem
+** -------------
+**
+** Add the item pointed to by lpLI to the Link ListBox and return
+** the index of it in the ListBox
+*/
+int AddLinkLBItem(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPLINKINFO lpLI, BOOL fGetSelected)
+{
+ HRESULT hErr;
+ DWORD dwUpdateOpt;
+ int nIndex;
+
+ OleDbgAssert(lpOleUILinkCntr && hListBox && lpLI);
+
+ lpLI->fDontFree = FALSE;
+
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkSource called\r\n"));
+ hErr = lpOleUILinkCntr->lpVtbl->GetLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPTSTR FAR*)&lpLI->lpszDisplayName,
+ (ULONG FAR*)&lpLI->clenFileName,
+ (LPTSTR FAR*)&lpLI->lpszFullLinkType,
+ (LPTSTR FAR*)&lpLI->lpszShortLinkType,
+ (BOOL FAR*)&lpLI->fSourceAvailable,
+ fGetSelected ? (BOOL FAR*)&lpLI->fIsSelected : NULL
+ );
+ OLEDBG_END2
+
+ if (hErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkSource returned"),hErr);
+ PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKSOURCE,
+ MB_ICONEXCLAMATION | MB_OK);
+
+ goto cleanup;
+ }
+
+ OLEDBG_BEGIN2(TEXT("IOleUILinkContainer::GetLinkUpdateOptions called\r\n"));
+ hErr=lpOleUILinkCntr->lpVtbl->GetLinkUpdateOptions(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPDWORD)&dwUpdateOpt
+ );
+ OLEDBG_END2
+
+
+ if (hErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: IOleUILinkContainer::GetLinkUpdateOptions returned"),hErr);
+ PopupMessage(hListBox, IDS_LINKS, IDS_ERR_GETLINKUPDATEOPTIONS,
+ MB_ICONEXCLAMATION | MB_OK);
+
+ goto cleanup;
+ }
+
+ if (lpLI->fSourceAvailable) {
+ if (dwUpdateOpt == OLEUPDATE_ALWAYS) {
+ lpLI->fIsAuto = TRUE;
+ LoadString(ghInst, IDS_LINK_AUTO, lpLI->lpszAMX,
+ (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
+ }
+ else {
+ lpLI->fIsAuto = FALSE;
+ LoadString(ghInst, IDS_LINK_MANUAL, lpLI->lpszAMX,
+ (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
+ }
+ }
+ else
+ LoadString(ghInst, IDS_LINK_UNKNOWN, lpLI->lpszAMX,
+ (int)OleStdGetSize((LPVOID)lpLI->lpszAMX));
+
+ BreakString(lpLI);
+
+ nIndex = (int)SendMessage(hListBox, LB_ADDSTRING, (WPARAM)0,
+ (LPARAM)(DWORD)lpLI);
+
+ if (nIndex == LB_ERR) {
+ PopupMessage(hListBox, IDS_LINKS, IDS_ERR_ADDSTRING,
+ MB_ICONEXCLAMATION | MB_OK);
+
+ goto cleanup;
+ }
+
+ return nIndex;
+
+cleanup:
+ if (lpLI->lpszDisplayName)
+ OleStdFree((LPVOID)lpLI->lpszDisplayName);
+
+ if (lpLI->lpszShortLinkType)
+ OleStdFree((LPVOID)lpLI->lpszShortLinkType);
+
+ if (lpLI->lpszFullLinkType)
+ OleStdFree((LPVOID)lpLI->lpszFullLinkType);
+
+ return -1;
+}
+
+
+/* BreakString
+ * -----------
+ *
+ * Purpose:
+ * Break the lpszDisplayName into various parts
+ *
+ * Parameters:
+ * lpLI pointer to LINKINFO structure
+ *
+ * Returns:
+ *
+ */
+VOID BreakString(LPLINKINFO lpLI)
+{
+ LPTSTR lpsz;
+
+ if (!lpLI->clenFileName ||
+ (lstrlen(lpLI->lpszDisplayName)==(int)lpLI->clenFileName)) {
+
+ lpLI->lpszItemName = NULL;
+ }
+ else {
+ lpLI->lpszItemName = lpLI->lpszDisplayName + lpLI->clenFileName;
+ }
+
+ // search from last character of filename
+ lpsz = lpLI->lpszDisplayName + lstrlen(lpLI->lpszDisplayName);
+ while (lpsz > lpLI->lpszDisplayName) {
+#ifdef WIN32
+ // AnsiPrev is obsolete in Win32
+ lpsz = CharPrev(lpLI->lpszDisplayName, lpsz);
+#else
+ lpsz = AnsiPrev(lpLI->lpszDisplayName, lpsz);
+#endif
+ if ((*lpsz == TEXT('\\')) || (*lpsz == TEXT('/')) || (*lpsz == TEXT(':')))
+ break;
+ }
+
+ if (lpsz == lpLI->lpszDisplayName)
+ lpLI->lpszShortFileName = lpsz;
+ else
+#ifdef WIN32
+ // AnsiNext is obsolete in Win32
+ lpLI->lpszShortFileName = CharNext(lpsz);
+#else
+ lpLI->lpszShortFileName = AnsiNext(lpsz);
+#endif
+}
+
+
+/* GetSelectedItems
+ * ----------------
+ *
+ * Purpose:
+ * Retrieve the indices of the selected items in the listbox
+ * Note that *lprgIndex needed to be free after using the function
+ *
+ * Parameters:
+ * hListBox window handle of listbox
+ * lprgIndex pointer to an integer array to receive the indices
+ * must be freed afterwards
+ *
+ * Returns:
+ * number of indices retrieved, -1 if error
+ */
+int GetSelectedItems(HWND hListBox, int FAR* FAR* lprgIndex)
+{
+ DWORD cSelItems;
+ DWORD cCheckItems;
+
+ *lprgIndex = NULL;
+
+ cSelItems = SendMessage(hListBox, LB_GETSELCOUNT, 0, 0L);
+ if (cSelItems < 0) // error
+ return (int)cSelItems;
+
+ if (!cSelItems)
+ return 0;
+
+ *lprgIndex = (int FAR*)OleStdMalloc((int)cSelItems * sizeof(int));
+
+ cCheckItems = SendMessage(hListBox, LB_GETSELITEMS,
+ (WPARAM) cSelItems, (LPARAM) (int FAR*) *lprgIndex);
+
+ if (cCheckItems == cSelItems)
+ return (int)cSelItems;
+ else {
+ if (*lprgIndex)
+ OleStdFree((LPVOID)*lprgIndex);
+ *lprgIndex = NULL;
+ return 0;
+ }
+}
+
+
+/* InitControls
+ * ------------
+ *
+ * Purpose:
+ * Initialize the state of the Auto/Manual button, Link source/type
+ * static field, etc in the dialogs according to the selection in the
+ * listbox
+ *
+ * Parameters:
+ * hDlg handle to the dialog window
+ */
+VOID InitControls(HWND hDlg, LPEDITLINKS lpEL)
+{
+ int cSelItems;
+ HWND hListBox;
+ int i;
+ int FAR* rgIndex;
+ LPLINKINFO lpLI;
+ LPTSTR lpszType = NULL;
+ LPTSTR lpszSource = NULL;
+ int cAuto = 0;
+ int cManual = 0;
+ BOOL bSameType = TRUE;
+ BOOL bSameSource = TRUE;
+ TCHAR tsz[OLEUI_CCHPATHMAX];
+ LPTSTR lpsz;
+
+
+ hListBox = GetDlgItem(hDlg, ID_EL_LINKSLISTBOX);
+
+ cSelItems = GetSelectedItems(hListBox, &rgIndex);
+ if (cSelItems < 0)
+ return;
+
+ EnableWindow(GetDlgItem(hDlg, ID_EL_AUTOMATIC), (BOOL)cSelItems);
+ EnableWindow(GetDlgItem(hDlg, ID_EL_MANUAL), (BOOL)cSelItems);
+ if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECANCELLINK))
+ EnableWindow(GetDlgItem(hDlg, ID_EL_CANCELLINK), (BOOL)cSelItems);
+ if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEOPENSOURCE))
+ EnableWindow(GetDlgItem(hDlg, ID_EL_OPENSOURCE), cSelItems == 1);
+ if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLECHANGESOURCE))
+ EnableWindow(GetDlgItem(hDlg, ID_EL_CHANGESOURCE), cSelItems == 1);
+ if (lpEL && !(lpEL->lpOEL->dwFlags & ELF_DISABLEUPDATENOW))
+ EnableWindow(GetDlgItem(hDlg, ID_EL_UPDATENOW), (BOOL)cSelItems);
+
+ for (i = 0; i < cSelItems; i++) {
+ SendDlgItemMessage(
+ hDlg,
+ ID_EL_LINKSLISTBOX,
+ LB_GETTEXT,
+ (WPARAM)rgIndex[i],
+ (LPARAM)(LPLINKINFO FAR*)&lpLI);
+
+ if (lpszSource && lpLI->lpszDisplayName) {
+ if (bSameSource && lstrcmp(lpszSource, lpLI->lpszDisplayName)) {
+ bSameSource = FALSE;
+ }
+ }
+ else
+ lpszSource = lpLI->lpszDisplayName;
+
+ if (lpszType && lpLI->lpszFullLinkType) {
+ if (bSameType && lstrcmp(lpszType, lpLI->lpszFullLinkType)) {
+ bSameType = FALSE;
+ }
+ }
+ else
+ lpszType = lpLI->lpszFullLinkType;
+
+ if (lpLI->fIsAuto)
+ cAuto++;
+ else
+ cManual++;
+ }
+
+ CheckDlgButton(hDlg, ID_EL_AUTOMATIC, cAuto && !cManual);
+ CheckDlgButton(hDlg, ID_EL_MANUAL, !cAuto && cManual);
+
+ /* fill full source in static text box
+ ** below list
+ */
+ if (!bSameSource || !lpszSource)
+ lpszSource = szNULL;
+ lstrcpy((LPTSTR)tsz, lpszSource);
+ lpsz = ChopText(GetDlgItem(hDlg, ID_EL_LINKSOURCE), 0, tsz);
+ SetDlgItemText(hDlg, ID_EL_LINKSOURCE, lpsz);
+
+ /* fill full link type name in static
+ ** "type" text box
+ */
+ if (!bSameType || !lpszType)
+ lpszType = szNULL;
+ SetDlgItemText(hDlg, ID_EL_LINKTYPE, lpszType);
+
+ if (rgIndex)
+ OleStdFree((LPVOID)rgIndex);
+}
+
+
+/* UpdateLinkLBItem
+ * -----------------
+ *
+ * Purpose:
+ * Update the linkinfo struct in the listbox to reflect the changes
+ * made by the last operation. It is done simply by removing the item
+ * from the listbox and add it back.
+ *
+ * Parameters:
+ * hListBox handle of listbox
+ * nIndex index of listbox item
+ * lpEL pointer to editlinks structure
+ * bSelect select the item or not after update
+ */
+VOID UpdateLinkLBItem(HWND hListBox, int nIndex, LPEDITLINKS lpEL, BOOL bSelect)
+{
+ LPLINKINFO lpLI;
+ DWORD dwErr;
+ LPOLEUILINKCONTAINER lpOleUILinkCntr;
+
+ if (!hListBox || (nIndex < 0) || !lpEL)
+ return;
+
+ lpOleUILinkCntr = lpEL->lpOEL->lpOleUILinkContainer;
+
+ dwErr = SendMessage(hListBox, LB_GETTEXT, nIndex,
+ (LPARAM)(LPLINKINFO FAR*) &lpLI);
+
+ if ((dwErr == LB_ERR) || !lpLI)
+ return;
+
+ /* Don't free the data associated with this listbox item
+ ** because we are going to reuse the allocated space for
+ ** the modified link. WM_DELETEITEM processing in the
+ ** dialog checks this flag before deleting data
+ ** associcated with list item.
+ */
+ lpLI->fDontFree = TRUE;
+ SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
+
+ nIndex = AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
+ if (bSelect) {
+ SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE, MAKELPARAM(nIndex, 0));
+ SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
+ }
+}
+
+
+
+/* DiffPrefix
+ * ----------
+ *
+ * Purpose:
+ * Compare (case-insensitive) two strings and return the prefixes of the
+ * the strings formed by removing the common suffix string from them.
+ * Integrity of tokens (directory name, filename and object names) are
+ * preserved. Note that the prefixes are converted to upper case
+ * characters.
+ *
+ * Parameters:
+ * lpsz1 string 1
+ * lpsz2 string 2
+ * lplpszPrefix1 prefix of string 1
+ * lplpszPrefix2 prefix of string 2
+ *
+ * Returns:
+ *
+ */
+VOID DiffPrefix(LPCTSTR lpsz1, LPCTSTR lpsz2, TCHAR FAR* FAR* lplpszPrefix1, TCHAR FAR* FAR* lplpszPrefix2)
+{
+ LPTSTR lpstr1;
+ LPTSTR lpstr2;
+
+ OleDbgAssert(lpsz1 && lpsz2 && *lpsz1 && *lpsz2 && lplpszPrefix1 &&
+ lplpszPrefix2);
+
+ *lplpszPrefix1 = NULL;
+ *lplpszPrefix2 = NULL;
+#ifdef WIN32
+ *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(TCHAR));
+#else
+ *lplpszPrefix1 = OleStdMalloc((lstrlen(lpsz1)+1) * sizeof(BYTE));
+#endif
+ if (!*lplpszPrefix1)
+ return;
+
+#ifdef WIN32
+ *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(TCHAR));
+#else
+ *lplpszPrefix2 = OleStdMalloc((lstrlen(lpsz2)+1) * sizeof(BYTE));
+#endif
+ if (!*lplpszPrefix2) {
+ OleStdFree(*lplpszPrefix1);
+ *lplpszPrefix1 = NULL;
+ return;
+ }
+
+ lstrcpy(*lplpszPrefix1, lpsz1);
+ lstrcpy(*lplpszPrefix2, lpsz2);
+// AnsiLower(*lplpszPrefix1);
+// AnsiLower(*lplpszPrefix2);
+
+ lpstr1 = *lplpszPrefix1 + lstrlen(*lplpszPrefix1);
+ lpstr2 = *lplpszPrefix2 + lstrlen(*lplpszPrefix2);
+
+ while ((lpstr1>*lplpszPrefix1) && (lpstr2>*lplpszPrefix2)) {
+#ifdef WIN32
+ lpstr1 = CharPrev(*lplpszPrefix1, lpstr1);
+ lpstr2 = CharPrev(*lplpszPrefix2, lpstr2);
+#else
+ lpstr1 = AnsiPrev(*lplpszPrefix1, lpstr1);
+ lpstr2 = AnsiPrev(*lplpszPrefix2, lpstr2);
+#endif
+ if (*lpstr1 != *lpstr2) {
+#ifdef WIN32
+ // AnsiNext is obsolete in Win32
+ lpstr1 = CharNext(lpstr1);
+ lpstr2 = CharNext(lpstr2);
+#else
+ lpstr1 = AnsiNext(lpstr1);
+ lpstr2 = AnsiNext(lpstr2);
+#endif
+ break;
+ }
+ }
+
+ for (; *lpstr1 && *lpstr1!=TEXT('\\') && *lpstr1!=TEXT('!');
+#ifdef WIN32
+ lpstr1=CharNext(lpstr1));
+#else
+ lpstr1=AnsiNext(lpstr1));
+#endif
+ for (; *lpstr2 && *lpstr2!=TEXT('\\') && *lpstr2!=TEXT('!');
+#ifdef WIN32
+ lpstr2=CharNext(lpstr2));
+#else
+ lpstr2=AnsiNext(lpstr2));
+#endif
+
+ *lpstr1 = TEXT('\0');
+ *lpstr2 = TEXT('\0');
+}
+
+
+/* PopupMessage
+ * ------------
+ *
+ * Purpose:
+ * Popup s messagebox and get some response from the user. It is the same
+ * as MessageBox() except that the title and message string are loaded
+ * from the resource file.
+ *
+ * Parameters:
+ * hwndParent parent window of message box
+ * idTitle id of title string
+ * idMessage id of message string
+ * fuStyle style of message box
+ */
+int PopupMessage(HWND hwndParent, UINT idTitle, UINT idMessage, UINT fuStyle)
+{
+ TCHAR szTitle[256];
+ TCHAR szMsg[256];
+
+ LoadString(ghInst, idTitle, (LPTSTR)szTitle, sizeof(szTitle)/sizeof(TCHAR));
+ LoadString(ghInst, idMessage, (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
+ return MessageBox(hwndParent, szMsg, szTitle, fuStyle);
+}
+
+
+/* ChangeAllLinks
+ * --------------
+ *
+ * Purpose:
+ * Enumerate all the links in the listbox and change those starting
+ * with lpszFrom to lpszTo.
+ *
+ * Parameters:
+ * hListBox window handle of
+ * lpOleUILinkCntr pointer to OleUI Link Container
+ * lpszFrom prefix for matching
+ * lpszTo prefix to substitution
+ *
+ * Returns:
+ */
+VOID ChangeAllLinks(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr, LPTSTR lpszFrom, LPTSTR lpszTo)
+{
+ int cItems;
+ int nIndex;
+ int cFrom;
+ LPLINKINFO lpLI;
+ LPTSTR szTmp[OLEUI_CCHPATHMAX];
+ BOOL bFound;
+
+ cFrom = lstrlen(lpszFrom);
+
+ cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
+ OleDbgAssert(cItems >= 0);
+
+ bFound = FALSE;
+
+ OleDbgPrint(3, TEXT("From : "), lpszFrom, 0);
+ OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
+ OleDbgPrint(3, TEXT("To : "), lpszTo, 0);
+ OleDbgPrint(3, TEXT(""), TEXT("\r\n"), 0);
+
+ for (nIndex=0; nIndex<cItems; nIndex++) {
+ SendMessage(hListBox, LB_GETTEXT, nIndex,
+ (LPARAM)(LPLINKINFO FAR*)&lpLI);
+
+ // unmark the item
+ lpLI->fIsMarked = FALSE;
+
+ /* if the corresponding position for the end of lpszFrom in the
+ ** display name is not a separator. We stop comparing this
+ ** link.
+ */
+ if (!*(lpLI->lpszDisplayName + cFrom) ||
+ (*(lpLI->lpszDisplayName + cFrom) == TEXT('\\')) ||
+ (*(lpLI->lpszDisplayName + cFrom) == TEXT('!'))) {
+
+ LSTRCPYN((LPTSTR)szTmp, lpLI->lpszDisplayName, cFrom + 1);
+ if (!lstrcmp((LPTSTR)szTmp, lpszFrom)) {
+ HRESULT hErr;
+ int nFileLength;
+ ULONG ulDummy;
+
+ if (!bFound) {
+ TCHAR szTitle[256];
+ TCHAR szMsg[256];
+ TCHAR szBuf[256];
+ int uRet;
+
+ LoadString(ghInst, IDS_CHANGESOURCE, (LPTSTR)szTitle,
+ sizeof(szTitle)/sizeof(TCHAR));
+ LoadString(ghInst, IDS_CHANGEADDITIONALLINKS,
+ (LPTSTR)szMsg, sizeof(szMsg)/sizeof(TCHAR));
+ wsprintf((LPTSTR)szBuf, (LPTSTR)szMsg, lpszFrom);
+ uRet = MessageBox(hListBox, (LPTSTR)szBuf, (LPTSTR)szTitle,
+ MB_ICONQUESTION | MB_YESNO);
+ if (uRet == IDYES)
+ bFound = TRUE;
+ else
+ return; // exit function
+ }
+
+ lstrcpy((LPTSTR)szTmp, lpszTo);
+ lstrcat((LPTSTR)szTmp, lpLI->lpszDisplayName + cFrom);
+ nFileLength = lstrlen((LPTSTR)szTmp) -
+ (lpLI->lpszItemName ? lstrlen(lpLI->lpszItemName) : 0);
+
+
+ hErr = lpOleUILinkCntr->lpVtbl->SetLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPTSTR)szTmp,
+ (ULONG)nFileLength,
+ (ULONG FAR*)&ulDummy,
+ TRUE
+ );
+ if (hErr != NOERROR)
+ lpOleUILinkCntr->lpVtbl->SetLinkSource(
+ lpOleUILinkCntr,
+ lpLI->dwLink,
+ (LPTSTR)szTmp,
+ (ULONG)nFileLength,
+ (ULONG FAR*)&ulDummy,
+ FALSE
+ );
+ lpLI->fIsMarked = TRUE;
+ }
+ }
+ }
+
+ /* have to do the refreshing after processing all links, otherwise
+ ** the item positions will change during the process as the
+ ** listbox stores items in order
+ */
+ if (bFound)
+ RefreshLinkLB(hListBox, lpOleUILinkCntr);
+}
+
+
+
+/* LoadLinkLB
+ * ----------
+ *
+ * Purpose:
+ * Enumerate all links from the Link Container and build up the Link
+ * ListBox
+ *
+ * Parameters:
+ * hListBox window handle of
+ * lpOleUILinkCntr pointer to OleUI Link Container
+ * lpszFrom prefix for matching
+ * lpszTo prefix to substitution
+ *
+ * Returns:
+ * number of link items loaded, -1 if error
+ */
+int LoadLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
+{
+ DWORD dwLink = 0;
+ LPLINKINFO lpLI;
+ int nIndex;
+ int cLinks;
+
+ cLinks = 0;
+
+ while ((dwLink = lpOleUILinkCntr->lpVtbl->GetNextLink(lpOleUILinkCntr,
+ dwLink)) != 0) {
+ lpLI = (LPLINKINFO)OleStdMalloc(sizeof(LINKINFO));
+ if (NULL == lpLI)
+ return -1;
+
+ lpLI->fIsMarked = FALSE;
+ lpLI->fIsSelected = FALSE;
+ lpLI->fDontFree = FALSE;
+
+#ifdef WIN32
+ lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(TCHAR));
+#else
+ lpLI->lpszAMX = (LPTSTR)OleStdMalloc((LINKTYPELEN+1)*sizeof(BYTE));
+#endif
+
+ lpLI->dwLink = dwLink;
+ cLinks++;
+ if ((nIndex = AddLinkLBItem(hListBox,lpOleUILinkCntr,lpLI,TRUE)) < 0)
+ // can't load list box
+ return -1;
+
+ if (lpLI->fIsSelected) {
+ SendMessage(hListBox, LB_SETSEL, TRUE, MAKELPARAM(nIndex, 0));
+ }
+ }
+ if (SendMessage(hListBox,LB_GETSELITEMS,(WPARAM)1,(LPARAM)(int FAR*)&nIndex))
+ SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex, MAKELPARAM(TRUE, 0));
+
+ return cLinks;
+}
+
+
+/* RefreshLinkLB
+ * -------------
+ *
+ * Purpose:
+ * Enumerate all items in the links listbox and update those with
+ * fIsMarked set.
+ * Note that this is a time consuming routine as it keeps iterating
+ * all items in the listbox until all of them are unmarked.
+ *
+ * Parameters:
+ * hListBox window handle of listbox
+ * lpOleUILinkCntr pointer to OleUI Link Container
+ *
+ * Returns:
+ *
+ */
+VOID RefreshLinkLB(HWND hListBox, LPOLEUILINKCONTAINER lpOleUILinkCntr)
+{
+ int cItems;
+ int nIndex;
+ LPLINKINFO lpLI;
+ BOOL bStop;
+
+ OleDbgAssert(hListBox);
+
+ cItems = (int)SendMessage(hListBox, LB_GETCOUNT, 0, 0L);
+ OleDbgAssert(cItems >= 0);
+
+ do {
+ bStop = TRUE;
+ for (nIndex=0; nIndex<cItems; nIndex++) {
+ SendMessage(hListBox, LB_GETTEXT, nIndex,
+ (LPARAM)(LPLINKINFO FAR*)&lpLI);
+ if (lpLI->fIsMarked) {
+ lpLI->fIsMarked = FALSE;
+ lpLI->fDontFree = TRUE;
+
+ SendMessage(hListBox, LB_DELETESTRING, nIndex, 0L);
+ nIndex=AddLinkLBItem(hListBox, lpOleUILinkCntr, lpLI, FALSE);
+ if (lpLI->fIsSelected) {
+ SendMessage(hListBox, LB_SETSEL, (WPARAM)TRUE,
+ MAKELPARAM(nIndex, 0));
+ SendMessage(hListBox, LB_SETCARETINDEX, (WPARAM)nIndex,
+ MAKELPARAM(TRUE, 0));
+ }
+ bStop = FALSE;
+ break;
+ }
+ }
+ } while (!bStop);
+}
+
+
diff --git a/private/oleutest/letest/ole2ui/links.dlg b/private/oleutest/letest/ole2ui/links.dlg
new file mode 100644
index 000000000..6bc8d7258
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/links.dlg
@@ -0,0 +1,35 @@
+// DLGINCLUDE RCDATA DISCARDABLE
+// BEGIN
+// "OLE2UI.H\0"
+// END
+
+IDD_EDITLINKS DIALOG 9, 25, 320, 158
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Links"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "&Links:", ID_EL_COL1, 11, 11, 26, 8
+ LTEXT "Type", ID_EL_COL2, 137, 12, 20, 8
+ LTEXT "Update", ID_EL_COL3, 201, 12, 25, 8
+ LISTBOX ID_EL_LINKSLISTBOX, 11, 23, 229, 81, LBS_OWNERDRAWFIXED
+ | LBS_EXTENDEDSEL | WS_VSCROLL | LBS_USETABSTOPS
+ | WS_TABSTOP | LBS_SORT | LBS_NOTIFY
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 249, 11, 66, 14
+ PUSHBUTTON "&Update Now", ID_EL_UPDATENOW, 249, 34, 66, 14
+ PUSHBUTTON "&Open Source", ID_EL_OPENSOURCE, 249, 54, 66, 14,
+ WS_GROUP
+ PUSHBUTTON "&Change Source...", ID_EL_CHANGESOURCE, 249, 73, 66, 14,
+ WS_GROUP
+ PUSHBUTTON "&Break Link", ID_EL_CANCELLINK, 249, 96, 66, 14
+ PUSHBUTTON "&Help", ID_OLEUIHELP, 249, 136, 66, 14
+ CONTROL "&Automatic", ID_EL_AUTOMATIC, "Button",
+ BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP, 61, 138, 65,
+ 10
+ CONTROL "&Manual", ID_EL_MANUAL, "Button", BS_AUTORADIOBUTTON,
+ 130, 138, 39, 10
+ LTEXT "Source:", 219, 9, 113, 30, 8
+ LTEXT "Type:", 220, 9, 125, 20, 8
+ LTEXT "Update:", ID_EL_UPDATE, 9, 139, 32, 8
+ LTEXT "", ID_EL_LINKSOURCE, 45, 113, 195, 8, SS_NOPREFIX
+ LTEXT "", ID_EL_LINKTYPE, 45, 125, 195, 8, SS_NOPREFIX
+END
diff --git a/private/oleutest/letest/ole2ui/makefile b/private/oleutest/letest/ole2ui/makefile
new file mode 100644
index 000000000..21eedcbe0
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/makefile
@@ -0,0 +1,12 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!ifdef NTMAKEENV
+all:
+ echo $(BUILDMSG)
+clean: all
+!else
+!INCLUDE $(NTMAKEENV)\makefile.def
+!endif
diff --git a/private/oleutest/letest/ole2ui/makefile.32 b/private/oleutest/letest/ole2ui/makefile.32
new file mode 100644
index 000000000..e69bb6ff8
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/makefile.32
@@ -0,0 +1,590 @@
+##########################################################################
+#
+# Makefile for OUTLUI.DLL
+#
+# Usage: NMAKE (builds DEBUG library)
+# or: NMAKE RELEASE=1 (builds RELEASE library -- no debug symbols)
+# or: NMAKE clean (erase all compiled files)
+#
+# Environment variables:
+# DEVROOT_DIR=<path> (root dir for sample code development)
+#
+##########################################################################
+
+LIBNAME = outlui
+
+!ifndef DEVROOT_DIR
+!error You must define DEVROOT_DIR (ole20 sub-tree)
+!endif
+!ifndef INCLUDE
+!error You must define INCLUDE (non ole20 include files)
+!endif
+!ifndef LIB
+!error You must deinfe LIB (non ole20 libraries)
+!endif
+!ifndef OLEBUILD
+OLEBUILD=NT
+!endif
+
+OLE2_H=$(DEVROOT_DIR)\h
+OLE2_LIB=$(DEVROOT_DIR)\lib
+
+!ifndef SAMPLE_DIR
+SAMPLE_DIR = $(DEVROOT_DIR)\samples
+!endif
+SRC_DIR = $(SAMPLE_DIR)\$(APP)
+
+MAKEFILE = makefile.32
+
+# ============================================================================
+# File: M A K E F I L E
+#
+# NMAKE description file for the OLE2.0 User Interface DLL
+#
+# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved.
+# Microsoft Confidential.
+# ============================================================================
+
+# ----------------------------------------------------------------------------
+# U I M A K E . I N I
+# ----------------------------------------------------------------------------
+
+
+!if "$(OLEBUILD)" == "DOS" || "$(OLEBUILD)" == ""
+DOS=1
+!endif
+
+!if "$(OLEBUILD)" == "NT"
+NT=1
+
+!if "$(MACHINE)" == "i386" || "$(MACHINE)" == ""
+MACHINE = i386
+MACHINE_D = _X86_
+MACHINE_CC = cl386
+!endif
+
+!if "$(MACHINE)" == "MIPS"
+MACHINE = mips
+MACHINE_D = _MIPS_
+MACHINE_CC = cc
+!endif
+
+!endif
+
+!include "uimake.ini"
+
+!ifndef LANG
+LANG=USA
+!endif
+
+!ifndef BUILD
+BUILD=dll
+!endif
+
+GOAL: MAKEINI
+ nmake -f $(MAKEFILE) PRELUDE SETFLAGS $(LIBNAME).$(BUILD)
+
+
+MAKEINI:
+ nmake -f $(MAKEFILE) LIBNAME=$(LIBNAME) LANG=$(LANG) BUILD=$(BUILD) RESOURCE=RESOUCE REL_DIR=$(OLEREL_DIR) DEBUG
+
+
+!if "$(INSTALL_DIR)"==""
+INSTALL_DIR = $(REL_DIR)
+!endif
+
+#use src/tok pairs to build if localized version
+!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa")
+SRCTOK=1
+!endif
+
+# ----------------------------------------------------------------------------
+# O B J E C T F I L E L I S T
+# ----------------------------------------------------------------------------
+
+UI_COBJS = \
+ D^\busy.obj\
+ D^\common.obj\
+ D^\convert.obj\
+ D^\dbgutil.obj\
+ D^\drawicon.obj\
+ D^\hatch.obj\
+ D^\icon.obj\
+ D^\iconbox.obj\
+ D^\insobj.obj\
+ D^\links.obj\
+ D^\msgfiltr.obj\
+ D^\enumfetc.obj\
+ D^\objfdbk.obj\
+ D^\ole2ui.obj\
+ D^\olestd.obj\
+ D^\targtdev.obj\
+ D^\oleutl.obj\
+ D^\pastespl.obj\
+ D^\regdb.obj\
+ D^\resimage.obj\
+ D^\utility.obj\
+
+UI_NOPCOBJS = \
+ D^\geticon.obj\
+
+UI_DLLOBJS = \
+ D^\dllfuncs.obj\
+
+PRECOMPOBJ=$(O)precomp.obj
+
+PRECOMP=$(O)precomp.pch
+
+# ----------------------------------------------------------------------------
+# R E S O U R C E L I S T
+# ----------------------------------------------------------------------------
+RES = \
+ busy.h \
+ common.h \
+ convert.h \
+ edlinks.h \
+ geticon.h \
+ icon.h \
+ iconbox.h \
+ insobj.h \
+ msgfiltr.h \
+ enumfetc.h \
+ ole2ui.h \
+ pastespl.h \
+ resimage.h \
+ $(RESOURCE)\STATIC\default.ico \
+ $(RESOURCE)\STATIC\bang.ico \
+ $(RESOURCE)\STATIC\egares.bmp \
+ $(RESOURCE)\STATIC\hivgares.bmp \
+ $(RESOURCE)\STATIC\vgares.bmp \
+ $(RESOURCE)\$(LANG)\strings.rc \
+ $(RESOURCE)\$(LANG)\busy.dlg \
+ $(RESOURCE)\$(LANG)\convert.dlg \
+ $(RESOURCE)\$(LANG)\fileopen.dlg \
+ $(RESOURCE)\$(LANG)\icon.dlg \
+ $(RESOURCE)\$(LANG)\insobj.dlg \
+ $(RESOURCE)\$(LANG)\links.dlg \
+ $(RESOURCE)\$(LANG)\pastespl.dlg \
+ $(RESOURCE)\$(LANG)\prompt.dlg \
+ $(RESOURCE)\ole2ui.rcv \
+ $(RESOURCE)\$(LANG)\verlocal.h \
+
+# ----------------------------------------------------------------------------
+# D E B U G S T A T I C L I B M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+DEBUGLIB:
+ @echo Creating DEBUG LIB <<uimake.ini
+# This is the DEBUG static .LIB UILibrary INI file
+MSG=DEBUG Static LIB Version ($$(LANG))
+DEBUG=1
+MODEL=M
+# Make a static library called OLE2UI.LIB
+LIBNAME=OLE2UI
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=DEBUGLIB
+BUILD=LIB
+RESOURCE=RESOURCE
+CFLAGS=-c -Od -GA2s -W3 -Zpei -A$(MODEL) -D_DEBUG
+RFLAGS=-D DEBUG
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=$(LANG)
+LIBOBJS = $$(UI_COBJS:D^\=DEBUGLIB^\) $$(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define OLEUICLASS1 "$(LIBNAME)Class1"
+#define OLEUICLASS2 "$(LIBNAME)Class2"
+<<KEEP
+ @echo Enter "$(MAKE)" to make Debug static LIB UILibrary
+
+
+# ----------------------------------------------------------------------------
+# R E T A I L S T A T I C L I B M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+RETAILIB:
+ @echo Creating RETAIL LIB <<uimake.ini
+# This is the RETAIL static .LIB UILibrary INI file
+MSG=RETAIL Static LIB Version ($$(LANG))
+RETAIL=1
+MODEL=M
+# Make a static library called OLE2UI.LIB
+LIBNAME=OLE2UI
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=RETAILIB
+BUILD=LIB
+RESOURCE=RESOURCE
+CFLAGS=-c -Os -GA2s -W3 -Zpe -A$(MODEL)
+RFLAGS=
+LFLAGS=/MAP:FULL /LINE /NOD /NOE /SE:300
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=$(LANG)
+LIBOBJS = $$(UI_COBJS:D^\=RETAILIB^\) $$(UI_NOPCOBJS:D^\=RETAILIB\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define OLEUICLASS1 "$(LIBNAME)Class1"
+#define OLEUICLASS2 "$(LIBNAME)Class2"
+<<KEEP
+ @echo Enter "$(MAKE)" to make Retail static LIB UILibrary
+
+# ----------------------------------------------------------------------------
+# D E B U G M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+!ifdef NT
+
+DEBUG:
+ @echo Creating DEBUG for NT <<uimake.ini
+# This is the DEBUG UILibrary INI file
+MSG=DEBUG Version ($$(LANG))
+DEBUG=1
+LIBNAME=$(LIBNAME)
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=DEBUG
+RESOURCE=RESOURCE
+
+CC = $(MACHINE_CC)
+DEFS1 = /D$(MACHINE_D) /D_DEBUG /D_DEBUGTRACE=0 /DWIN32 /DOLE2SHIP
+DEFS2 = /D$(MACHINE)=1 /D_NTWIN /D_WINDOWS /DWINVER=0x030A /D_NTDLL /D_DLL
+CFLAGS = $$(DEFS1) $$(DEFS2) /Z7 /Od /c /Fc /G3 /W3 /nologo $(CL)
+LFLAGS = -subsystem:windows -machine:$(MACHINE) -debug:mapped,full -debugtype:both
+RFLAGS = /DWIN32 /D_DEBUG
+UILIBS1 = mpr.lib crtdll.lib ntdll.lib
+UILIBS2 = ole2w32.lib storag32.lib
+UILIBS3 = kernel32.lib user32.lib gdi32.lib advapi32.lib shell32.lib comdlg32.lib
+UILIBS = $$(UILIBS1) $$(UILIBS2) $$(UILIBS3)
+
+LK = link32
+
+LANG = $(LANG)
+RS = rc
+
+DLLOBJS = $$(UI_DLLOBJS:D^\=DEBUG^\)
+LIBOBJS = $$(UI_COBJS:D^\=DEBUG^\) $$(UI_NOPCOBJS:D^\=DEBUG\NOPC^\)
+<<KEEP
+ @echo Enter "$(MAKE)" to make Debug UILibrary
+
+!else
+
+DEBUG:
+ @echo Creating DEBUG <<uimake.ini
+# This is the DEBUG UILibrary INI file
+MSG=DEBUG DLL Version ($$(LANG))
+DEBUG=1
+MODEL=M
+LIBNAME=$(LIBNAME)
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=DEBUG
+BUILD=DLL
+RESOURCE=RESOURCE
+CFLAGS=-c -Od -GD2s -W3 -Zpei -AMw -D_DEBUG -DDLL_VER -D_WINDLL
+RFLAGS=-D DEBUG -D DLL_VER
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300
+UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+RS=rc
+LK=link
+LANG=$(LANG)
+DLLOBJS = $$(UI_DLLOBJS:D^\=DEBUG^\)
+LIBOBJS = $$(UI_COBJS:D^\=DEBUG^\) $$(UI_NOPCOBJS:D^\=DEBUG\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define OLEUICLASS1 "$(LIBNAME)Class1"
+#define OLEUICLASS2 "$(LIBNAME)Class2"
+<<KEEP
+ @echo Enter "$(MAKE)" to make Debug UILibrary
+
+!endif
+# ----------------------------------------------------------------------------
+# R E T A I L D L L M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+RETAIL:
+ @echo Creating RETAIL <<uimake.ini
+# This is the RETAIL UILibrary INI file
+MSG=RETAIL DLL Version ($$(LANG))
+RETAIL=1
+MODEL=M
+LIBNAME=$(LIBNAME)
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=RETAIL
+BUILD=DLL
+RESOURCE=RESOURCE
+CFLAGS=-c -Os -GD2s -W3 -Zpe -AMw -DOPTIMIZE -DDLL_VER -D_WINDLL
+RFLAGS=-D DLL_VER
+LFLAGS=/MAP /NOD /NOE /SE:300 /AL:16
+UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+RS=rc
+LK=link
+LANG=$(LANG)
+DLLOBJS = $$(UI_DLLOBJS:D^\=RETAIL^\)
+LIBOBJS = $$(UI_COBJS:D^\=RETAIL^\) $$(UI_NOPCOBJS:D^\=RETAIL\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define OLEUICLASS1 "$(LIBNAME)Class1"
+#define OLEUICLASS2 "$(LIBNAME)Class2"
+<<KEEP
+ @echo Enter "$(MAKE)" to make Retail UILibrary
+
+!if [if not exist $(OBJ)\*. md $(OBJ) >nul]
+!error Object subdirectory $(OBJ)\ could not be created
+!endif
+!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul]
+!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created
+!endif
+
+#select language for version resource if localized version
+!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa")
+RFLAGS=$(RFLAGS) -D VER_LOC
+!endif
+
+!if ("$(LIBNAME)"=="PUBOLEUI")
+RFLAGS=$(RFLAGS) -D PUBLISHER
+!endif
+
+.SUFFIXES: .c .asm .obj .res .rc .def .bmp .ico .exe .dll .cod .str
+
+O=.\$(OBJ)^\
+
+# ----------------------------------------------------------------------------
+# I N F E R E N C E R U L E S
+# ----------------------------------------------------------------------------
+# compile C file without precompiled headers into object directory\NOPC
+# dont compile c files etc for lcoalized builds.
+!ifndef SRCTOK
+
+{}.c{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -Fo$(O)NOPC\$(@B) $(@B).c
+!endif
+
+# compile C file into object directory
+{}.c{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -Fo$(O)$(@B) $(@B).c
+!endif
+
+!endif
+#endif SRCTOK
+
+{}.rc{$(O)}.res:
+ @echo ²²²²²²²²²²²²²²²²²²² Resource Compiling $(@B).res ²²²²²²²²²²²²²²²²²²²²
+ $(RS) -I $(RESOURCE)\$(LANG);$(RESOURCE)\static;$(RESOURCE) -FO $(O)$(@B).res -R $(RFLAGS) $(@B).rc
+ -del $(LIBNAME).dll
+
+!ifndef SRCTOK
+{}.c.cod:
+ @echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Making $(@B).cod ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
+!ifdef DOS
+ SET CL=$(CFLAGS) -f -Fc
+ $(CC) $(@B).c
+!else
+ $(CC) $(CFLAGS) -f- -Fc $(@B).c
+!endif
+!endif
+#endif SRCTOK
+
+
+# rules for creating rc & dlg files for localized verisons from src/tok pairs
+!ifdef SRCTOK
+
+$(RESOURCE)\$(LANG)\busy.dlg : $(RESOURCE)\$(LANG)\busy.tok $(RESOURCE)\src\busy.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\convert.dlg : $(RESOURCE)\$(LANG)\convert.tok $(RESOURCE)\src\convert.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\fileopen.dlg : $(RESOURCE)\$(LANG)\fileopen.tok $(RESOURCE)\src\fileopen.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\icon.dlg : $(RESOURCE)\$(LANG)\icon.tok $(RESOURCE)\src\icon.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\insobj.dlg : $(RESOURCE)\$(LANG)\insobj.tok $(RESOURCE)\src\insobj.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\links.dlg : $(RESOURCE)\$(LANG)\links.tok $(RESOURCE)\src\links.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\pastespl.dlg : $(RESOURCE)\$(LANG)\pastespl.tok $(RESOURCE)\src\pastespl.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\prompt.dlg : $(RESOURCE)\$(LANG)\prompt.tok $(RESOURCE)\src\prompt.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\strings.rc : $(RESOURCE)\$(LANG)\strings.tok $(RESOURCE)\src\strings.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+!endif
+
+# ----------------------------------------------------------------------------
+# D E P E N D F I L E C R E A T I O N
+# ----------------------------------------------------------------------------
+UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c)
+UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c)
+DEPEND: nul
+ @echo Making a NEW dependancy file.
+ mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp
+ sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend
+ -del tmp.tmp
+ mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend
+ mkdep -p $$(O) -s .pch precomp.c >> depend
+
+# ----------------------------------------------------------------------------
+# W E L C O M E B A N N E R
+# ----------------------------------------------------------------------------
+PRELUDE:
+ @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+ @echo º Makefile for UILibrary º
+ @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+ @echo $(MSG)
+!ifndef SRCTOK
+ set INCLUDE=$(OLEREL_DIR);$(INCLUDE)
+ set LIB=$(OLEREL_DIR);$(LIB)
+!endif
+
+SETFLAGS:
+ set INCLUDE=$(INCLUDE);$(OLE2_H)
+ set LIB=$(LIB);$(OLE2_LIB)
+
+
+# ----------------------------------------------------------------------------
+# G O A L T A R G E T S
+# ----------------------------------------------------------------------------
+!include "depend"
+
+CLEAN: CleanUp GOAL
+
+CleanUp: MAKEINI
+ nmake -f $(MAKEFILE) SETFLAGS Delete
+
+Delete:
+ -echo y|del .\$(OBJ)\*.*
+ -del $(LIBNAME).dll
+ -del $(LIBNAME).lib
+
+!ifndef SRCTOK
+
+$(O)precomp.pch: precomp.c
+!ifdef DOS
+ SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h
+ $(CC) -Fo$(O)$(@B) precomp.c
+!else
+ $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -Fo$(O)$(@B) precomp.c
+!endif
+!endif
+#endif SRCTOK
+
+$(O)ole2ui.res: ole2ui.rc $(RES)
+
+ole2ui.rc : $(RESOURCE)\$(LANG)\strings.rc
+
+#
+# Build .LIB static library
+#
+
+$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ)
+ -del $(O)$(LIBNAME).lib
+ lib @<<
+$(O)$(LIBNAME).lib
+y
+$(PRECOMPOBJ: = +) $(LIBOBJS: = +)
+
+<<
+ copy $(O)$(LIBNAME).lib $(LIBNAME).lib
+
+#
+# Build .DLL dynamic-link library
+#
+
+!if "$(OLEBUILD)" == "NT"
+!else
+$(O)$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJS)
+ -del $(O)$(LIBNAME).lib
+ lib @<<
+$(O)$(LIBNAME).lib
+y
+$(PRECOMPOBJ: = +) $(LIBOBJS: = +)
+
+<<
+!endif
+
+!if "$(OLEBUILD)" == "NT"
+
+$(LIBNAME).dll: $(LIBNAME).d32 $(PRECOMPOBJS) $(LIBOBJS) $(DLLOBJS) $(O)ole2ui.res
+ @echo Linking ...
+ lib32 -out:$*.lib -def:$(LIBNAME).d32 -machine:$(MACHINE) $(LIBOBJS) $(DLLOBJS)
+ cvtres -$(MACHINE) $(O)ole2ui.res -o $*.rs
+ link32 $(LFLAGS) -entry:LibMain@12 @<<$(BUILD_DIR)\ole2util.lnk
+ $(LIBNAME).exp $(LIBOBJS) $(DLLOBJS) $(PRECOMPOBJ) $(UILIBS) $*.rs -out:$@ -map:$*.map -dll $(UILIBS)
+<<KEEP
+
+!else
+$(O)$(LIBNAME).exe: $(O)$(LIBNAME).lib $(DLLOBJS) $(O)ole2ui.res
+ @echo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄį Linking UILibrary ®ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+ @echo Creating <<$(O)$(@B).lnk
+$(LFLAGS) +
+$(PRECOMPOBJ: = +^
+)+
+$(DLLOBJS: = +^
+)+
+
+$(O)$(@B)
+$(@B).map
+$(UILIBS) $(O)$(LIBNAME).lib
+$(LIBNAME).def
+<<KEEP
+
+ $(LK) @$(O)$(@B).lnk
+ $(RS) -31 $(RFLAGS) $(O)ole2ui.res $(O)$(LIBNAME).exe
+
+!ifndef SRCTOK
+$(LIBNAME).dll: $(O)$(LIBNAME).exe ole2ui.def
+ copy $(O)$(LIBNAME).exe $(LIBNAME).dll
+ mapsym -n -l $(LIBNAME).map
+ implib $(LIBNAME).lib $(LIBNAME).dll
+!else
+$(LIBNAME).dll: $(O)ole2ui.res
+ copy $(RESOURCE)\USA\$(LIBNAME).dll $(LIBNAME).dll
+ $(RS) -31 -K $(RFLAGS) $(O)ole2ui.res $(LIBNAME).dll
+!endif
+!endif
+#endif SRCTOK
+
+
+install: MAKEINI
+ nmake -f $(MAKEFILE) SETFLAGS InstallAll
+
+# install built library to $(INSTALL_DIR) dir
+InstallAll:
+ copy $(LIBNAME).dll $(INSTALL_DIR)
+ copy $(LIBNAME).lib $(INSTALL_DIR)
+ copy $(LIBNAME).sym $(INSTALL_DIR)
+ copy ole2ui.h $(INSTALL_DIR)
+ copy msgfiltr.h $(INSTALL_DIR)
+ copy enumfetc.h $(INSTALL_DIR)
+ copy regdb.h $(INSTALL_DIR)
+ copy olestd.h $(INSTALL_DIR)
+ copy geticon.h $(INSTALL_DIR)
+ copy ole2ui.rc $(INSTALL_DIR)
+ copy uiclass.h $(INSTALL_DIR)
+
+# EOF ========================================================================
diff --git a/private/oleutest/letest/ole2ui/makefile.old b/private/oleutest/letest/ole2ui/makefile.old
new file mode 100644
index 000000000..3fadaf177
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/makefile.old
@@ -0,0 +1,607 @@
+# ============================================================================
+# File: M A K E F I L E
+#
+# NMAKE description file for the OLE2.0 User Interface DLL
+#
+# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved.
+# ============================================================================
+#
+# Usage Notes:
+# -----------
+#
+# This makefile is designed to be used in two steps. The first time you
+# call the makefile, it generates a file called UIMAKE.INI. The second time
+# you call the makefile, it reads settings from UIMAKE.INI and actually
+# performs the build. See the section below "UIMAKE.INI" for more information
+# on this file.
+#
+# 1. Initial Step -- Before building your library for the first time, you
+# need to run one of the following commands. (This step will only be needed
+# to run again if you want to build a different variant of the library, for
+# instance if you want to switch from a DEBUG to a RETAIL build).
+#
+# NMAKE DEBUG - Prepares for building DEBUG DLL version
+# NMAKE RETAIL - Prepares for building RETAIL DLL version
+# NMAKE DEBUGLIB - Prepares for building DEBUG static LIB version
+# NMAKE RETAILIB - Prepares for building RETAIL static LIB version
+#
+# This step builds the UIMAKE.INI file, which contains the settings
+# which specify what version of the library you want to build.
+#
+# 2. Build Step
+#
+# NMAKE
+#
+# This second step reads the settings in the UIMAKE.INI file and builds
+# the requested library.
+#
+#
+# UIMAKE.INI
+# ----------
+#
+# This file is used to specify which variant of the library to build,
+# as well as details like which compiler and linker options to use. The
+# file is created based on the settings in the "MAKE PARAMETERS" section
+# of this makefile.
+#
+# For most builds, using the default settings will work fine, but if you
+# need to change how you build the library, the UIMAKE.INI file is a
+# simple way to make this change without changing the makefile.
+#
+# The following lists a few of the settings in the UIMAKE.INI file which
+# you might change, and what effect those changes might have. For a
+# complete listing of all the available options and how they are used,
+# see the makefile below.
+#
+# MODEL=[S|M|C|L] -- The memory model. Only available
+# on static .LIB version. This flag is
+# also included (but not used) in the DLL
+# version of UIMAKE.INI in order to allow
+# switching between the DLL and LIB version.
+# LIBNAME= -- The library name. For building your own
+# library (other than the ones for the samples),
+# this must be set to a unique name for your
+# application.
+# LANG= -- Used for international versions of this
+# library. Specifies which directory the
+# resources come from. Default is USA
+#
+# ============================================================================
+
+
+# ----------------------------------------------------------------------------
+# U I M A K E . I N I
+# ----------------------------------------------------------------------------
+# XXXXXXX DOS=1
+!ifndef LANG
+LANG=USA
+!endif
+
+!if [if not exist uimake.ini dir uimake.ini >nul] != 0
+#!if [test -f uimake.ini] != 0
+LIBNAME=
+MODEL=M
+RESOURCE=RESOURCE
+!ifndef REL_DIR
+@echo REL_DIR not defined
+REL_DIR=c:\ole2samp\release
+!endif
+!ifndef OLERELDIR
+@echo OLEREL_DIR not defined
+OLEREL_DIR=c:\ole2samp\release
+!endif
+GOAL: DEBUG
+!else
+!include "uimake.ini"
+GOAL: PRELUDE $(LIBNAME).$(BUILD)
+!endif
+
+!if "$(INSTALL_DIR)"==""
+INSTALL_DIR = $(REL_DIR)
+!endif
+
+#use src/tok pairs to build if localized version
+!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa")
+SRCTOK=1
+!endif
+# ----------------------------------------------------------------------------
+# O B J E C T F I L E L I S T
+# ----------------------------------------------------------------------------
+
+UI_COBJS = \
+ D^\ole2ui.obj\
+ D^\busy.obj\
+ D^\common.obj\
+ D^\convert.obj\
+ D^\dbgutil.obj\
+ D^\drawicon.obj\
+ D^\hatch.obj\
+ D^\icon.obj\
+ D^\iconbox.obj\
+ D^\insobj.obj\
+ D^\links.obj\
+ D^\msgfiltr.obj\
+ D^\enumfetc.obj\
+ D^\enumstat.obj\
+ D^\objfdbk.obj\
+ D^\olestd.obj\
+ D^\targtdev.obj\
+ D^\oleutl.obj\
+ D^\pastespl.obj\
+ D^\regdb.obj\
+ D^\resimage.obj\
+ D^\utility.obj\
+
+UI_NOPCOBJS = \
+ D^\geticon.obj\
+ D^\dballoc.obj\
+ D^\suminfo.obj\
+ D^\stdpal.obj\
+
+UI_DLLOBJS = \
+ D^\dllfuncs.obj\
+
+PRECOMPOBJ= $(O)precomp.obj
+
+PRECOMP=$(O)precomp.pch
+
+# ----------------------------------------------------------------------------
+# R E S O U R C E L I S T
+# ----------------------------------------------------------------------------
+RES = \
+ busy.h \
+ common.h \
+ convert.h \
+ edlinks.h \
+ geticon.h \
+ icon.h \
+ iconbox.h \
+ insobj.h \
+ msgfiltr.h \
+ enumfetc.h \
+ ole2ui.h \
+ pastespl.h \
+ resimage.h \
+ dballoc.h \
+ suminfo.h \
+ stdpal.h \
+ $(RESOURCE)\STATIC\default.ico \
+ $(RESOURCE)\STATIC\bang.ico \
+ $(RESOURCE)\STATIC\egares.bmp \
+ $(RESOURCE)\STATIC\hivgares.bmp \
+ $(RESOURCE)\STATIC\vgares.bmp \
+ $(RESOURCE)\$(LANG)\strings.rc \
+ $(RESOURCE)\$(LANG)\busy.dlg \
+ $(RESOURCE)\$(LANG)\convert.dlg \
+ $(RESOURCE)\$(LANG)\fileopen.dlg \
+ $(RESOURCE)\$(LANG)\icon.dlg \
+ $(RESOURCE)\$(LANG)\insobj.dlg \
+ $(RESOURCE)\$(LANG)\links.dlg \
+ $(RESOURCE)\$(LANG)\pastespl.dlg \
+ $(RESOURCE)\$(LANG)\prompt.dlg \
+ $(RESOURCE)\ole2ui.rcv \
+ $(RESOURCE)\$(LANG)\verlocal.h \
+
+# ----------------------------------------------------------------------------
+# D E B U G S T A T I C L I B M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+DEBUGLIB: DbgUI
+
+DbgUI:
+ @echo Creating DEBUG LIB <<uimake.ini
+# This is the DEBUG static .LIB UILibrary INI file
+MSG=DEBUG Static LIB Version ($$(LANG))
+DEBUG=1
+MODEL=M
+# Make a static library called OLE2UI.LIB
+LIBNAME=OLE2UI
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=DEBUGLIB
+BUILD=LIB
+RESOURCE=RESOURCE
+
+# 16 bit CFLAGS=-c -Od -GA2s -W3 -Zpei -A$(MODEL) -D_DEBUG -DWIN32 -DUNICODE
+
+CFLAGS=-c -Od -Gs -W3 -Zpei -D_DEBUG -DWIN32 -DUNICODE
+RFLAGS=-D DEBUG
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=$(LANG)
+LIBOBJS = $$(UI_COBJS:D^\=DEBUGLIB^\) $$(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define SZCLASSICONBOX TEXT("$(LIBNAME)IBClass")
+#define SZCLASSRESULTIMAGE TEXT("$(LIBNAME)RIClass")
+<<KEEP
+ @echo Enter "$(MAKE)" to make Debug static LIB UILibrary
+
+
+# ----------------------------------------------------------------------------
+# R E T A I L S T A T I C L I B M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+RETAILIB:
+ @echo Creating RETAIL LIB <<uimake.ini
+# This is the RETAIL static .LIB UILibrary INI file
+MSG=RETAIL Static LIB Version ($$(LANG))
+RETAIL=1
+MODEL=M
+# Make a static library called OLE2UI.LIB
+LIBNAME=OLE2UI
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=RETAILIB
+BUILD=LIB
+RESOURCE=RESOURCE
+
+# 16 bit CFLAGS=-c -Os -GA2s -W3 -Zpe -A$(MODEL) -DWIN32 -DUNICODE
+
+CFLAGS=-c -Os -Gs -W3 -Zpe -DWIN32 -DUNICODE
+RFLAGS=
+LFLAGS=/MAP:FULL /LINE /NOD /NOE /SE:300 /NOPACKCODE
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=$(LANG)
+LIBOBJS = $$(UI_COBJS:D^\=RETAILIB^\) $$(UI_NOPCOBJS:D^\=RETAILIB\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define SZCLASSICONBOX TEXT("$(LIBNAME)IBClass")
+#define SZCLASSRESULTIMAGE TEXT("$(LIBNAME)RIClass")
+<<KEEP
+ @echo Enter "$(MAKE)" to make Retail static LIB UILibrary
+
+# ----------------------------------------------------------------------------
+# D E B U G D L L M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+DEBUG: Dbg
+
+Dbg:
+ @echo Creating DEBUG <<uimake.ini
+# This is the DEBUG UILibrary INI file
+MSG=DEBUG DLL Version ($$(LANG))
+DEBUG=1
+MODEL=M
+LIBNAME=$(LIBNAME)
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=DEBUG
+BUILD=DLL
+RESOURCE=RESOURCE
+#CFLAGS=-c -Od -GD2s -W3 -Zpei -AMw -D_DEBUG -DDLL_VER -D_WINDLL
+
+# 16 bit CFLAGS=-c -Od -GA2s -GEd -W3 -Zpei -AMw -D_DEBUG -DDLL_VER -D_WINDLL -DWIN32 -DUNICODE
+
+CFLAGS=-c -Od -Gs -Gd -W3 -Zpei -AMw -D_DEBUG -DDLL_VER -D_WINDLL -DWIN32 -DUNICODE -DNOASSERT
+RFLAGS=-D DEBUG -D DLL_VER
+
+# 16 bit LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE
+LFLAGS=/MAP:$(LIBNAME).map /NOD /DLL /IMPLIB:$(LIBNAME).lib
+
+# 16 bit UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp
+UILIBS= $(IMPORT)\nt475\lib\objind\advapi32.lib \
+ $(IMPORT)\nt475\lib\objind\comdlg32.lib \
+ $(IMPORT)\nt475\lib\objind\crtdll.lib \
+ $(IMPORT)\nt475\lib\objind\gdi32.lib \
+ $(IMPORT)\nt475\lib\objind\kernel32.lib \
+ $(IMPORT)\nt475\lib\objind\libcnt.lib \
+ $(IMPORT)\nt475\lib\objind\shell32.lib \
+ $(IMPORT)\nt475\lib\objind\user32.lib \
+ $(COMMON)\ilib\OBJind\ole232.lib \
+ $(COMMON)\types\OBJind\uuid.lib \
+ $(COMMON)\ilib\OBJind\storag32.lib \
+ $(COMMON)\ilib\OBJind\compob32.lib
+CC=cl
+RS=rc
+LK=link
+LANG=$(LANG)
+DLLOBJS = $$(UI_DLLOBJS:D^\=DEBUG^\)
+LIBOBJS = $$(UI_COBJS:D^\=DEBUG^\) $$(UI_NOPCOBJS:D^\=DEBUG\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define SZCLASSICONBOX "$(LIBNAME)IBClass"
+#define SZCLASSRESULTIMAGE "$(LIBNAME)RIClass"
+<<KEEP
+ @echo Enter "$(MAKE)" to make Debug UILibrary
+
+# ----------------------------------------------------------------------------
+# R E T A I L M A K E P A R A M E T E R S
+# ----------------------------------------------------------------------------
+RETAIL:
+ @echo Creating RETAIL <<uimake.ini
+# This is the RETAIL UILibrary INI file
+MSG=RETAIL DLL Version ($$(LANG))
+RETAIL=1
+MODEL=M
+LIBNAME=$(LIBNAME)
+REL_DIR=$(REL_DIR)
+OLEREL_DIR=$(OLEREL_DIR)
+OBJ=RETAIL
+BUILD=DLL
+RESOURCE=RESOURCE
+#CFLAGS=-c -Os -GD2s -W3 -Zpe -AMw -DOPTIMIZE -DDLL_VER -D_WINDLL
+
+# 16 bit CFLAGS=-c -Os -GA2s -GEd -W3 -Zpe -AMw -DOPTIMIZE -DDLL_VER -D_WINDLL -DWIN32 -DUNICODE
+
+CFLAGS=-c -Os -Gs -Gd -W3 -Zpe -DOPTIMIZE -DDLL_VER -D_WINDLL -DWIN32 -DUNICODE
+RFLAGS=-D DLL_VER
+LFLAGS=/MAP /NOD /NOE /SE:300 /AL:16 /NOPACKCODE
+UILIBS=mdllcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+RS=rc
+LK=link
+LANG=$(LANG)
+DLLOBJS = $$(UI_DLLOBJS:D^\=RETAIL^\)
+LIBOBJS = $$(UI_COBJS:D^\=RETAIL^\) $$(UI_NOPCOBJS:D^\=RETAIL\NOPC^\)
+<<KEEP
+ @echo Creating <<uiclass.h
+#define SZCLASSICONBOX TEXT("$(LIBNAME)IBClass")
+#define SZCLASSRESULTIMAGE TEXT("$(LIBNAME)RIClass")
+<<KEEP
+ @echo Enter "$(MAKE)" to make Retail UILibrary
+
+!if [if not exist $(OBJ)\*. md $(OBJ) >nul]
+!error Object subdirectory $(OBJ)\ could not be created
+!endif
+!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul]
+!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created
+!endif
+
+#select language for version resource if localized version
+!if ("$(LANG)"!="USA") && ("$(LANG)"!="usa")
+RFLAGS=$(RFLAGS) -D VER_LOC
+!endif
+
+.SUFFIXES: .c .asm .obj .res .rc .def .bmp .ico .exe .dll .cod .str
+
+O=.\$(OBJ)^\
+
+# ----------------------------------------------------------------------------
+# I N F E R E N C E R U L E S
+# ----------------------------------------------------------------------------
+!ifndef SRCTOK
+
+# compile C file without precompiled headers into object directory\NOPC
+# dont compile c files etc for lcoalized builds.
+{}.c{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).c
+!else
+!undef _FILE_
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c
+!endif
+
+# compile C file into object directory
+{}.c{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).c
+!else
+!undef _FILE_
+# $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c
+!endif
+
+# compile CPP file without precompiled headers into object directory\NOPC
+# dont compile cpp files etc for lcoalized builds.
+{}.cpp{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp
+!else
+!undef _FILE_
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp
+!endif
+
+# compile CPP file into object directory
+{}.cpp{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).cpp
+!else
+!undef _FILE_
+# $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp
+!endif
+
+!endif
+#endif SRCTOK
+
+{}.rc{$(O)}.res:
+ @echo ²²²²²²²²²²²²²²²²²²² Resource Compiling $(@B).res ²²²²²²²²²²²²²²²²²²²²
+ $(RS) -I $(RESOURCE)\$(LANG);$(RESOURCE)\static;$(RESOURCE) -FO $(O)$(@B).res -DWIN32 -DUNICODE -R $(RFLAGS) $(@B).rc
+ -del $(LIBNAME).dll
+
+!ifndef SRCTOK
+{}.c.cod:
+ @echo ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ Making $(@B).cod ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
+!ifdef DOS
+ SET CL=$(CFLAGS) -f -Fc
+ $(CC) $(@B).c
+!else
+!undef _FILE_
+ $(CC) $(CFLAGS) -f- -Fc -D_FILE_=\"$(*B).c\" $(@B).c
+!endif
+!endif
+
+
+# rules for creating rc & dlg files for localized verisons from src/tok pairs
+!ifdef SRCTOK
+
+$(RESOURCE)\$(LANG)\busy.dlg : $(RESOURCE)\$(LANG)\busy.tok $(RESOURCE)\src\busy.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\convert.dlg : $(RESOURCE)\$(LANG)\convert.tok $(RESOURCE)\src\convert.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\fileopen.dlg : $(RESOURCE)\$(LANG)\fileopen.tok $(RESOURCE)\src\fileopen.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\icon.dlg : $(RESOURCE)\$(LANG)\icon.tok $(RESOURCE)\src\icon.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\insobj.dlg : $(RESOURCE)\$(LANG)\insobj.tok $(RESOURCE)\src\insobj.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\links.dlg : $(RESOURCE)\$(LANG)\links.tok $(RESOURCE)\src\links.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\pastespl.dlg : $(RESOURCE)\$(LANG)\pastespl.tok $(RESOURCE)\src\pastespl.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\prompt.dlg : $(RESOURCE)\$(LANG)\prompt.tok $(RESOURCE)\src\prompt.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+
+$(RESOURCE)\$(LANG)\strings.rc : $(RESOURCE)\$(LANG)\strings.tok $(RESOURCE)\src\strings.src
+ tok -q -f $*.tok $(RESOURCE)\src\$(@B).src > $@
+!endif
+
+# ----------------------------------------------------------------------------
+# D E P E N D F I L E C R E A T I O N
+# ----------------------------------------------------------------------------
+UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c)
+UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c)
+DEPEND: nul
+ @echo Making a NEW dependancy file.
+ mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp
+ sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend
+ -del tmp.tmp
+ mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend
+ mkdep -p $$(O) -s .pch precomp.c >> depend
+
+# ----------------------------------------------------------------------------
+# W E L C O M E B A N N E R
+# ----------------------------------------------------------------------------
+PRELUDE:
+ @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+ @echo º Makefile for UILibrary º
+ @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+ @echo $(MSG)
+!ifndef SRCTOK
+ set INCLUDE=$(OLEREL_DIR);$(INCLUDE)
+ set LIB=$(OLEREL_DIR);$(LIB)
+!endif
+
+
+# ----------------------------------------------------------------------------
+# G O A L T A R G E T S
+# ----------------------------------------------------------------------------
+!include "depend"
+
+CLEAN: CleanUp GOAL
+CleanUp:
+ -echo y|del .\$(OBJ)\*.*
+ -del $(LIBNAME).dll
+ -del $(LIBNAME).lib
+
+!ifndef SRCTOK
+
+$(O)precomp.pch: precomp.c
+!ifdef DOS
+ SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h
+ $(CC) -Fo$(O)$(@B) precomp.c
+!else
+!undef _FILE_
+ @echo Precompiling Header Files....
+ $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c
+!endif
+!endif
+
+$(O)ole2ui.res: ole2ui.rc $(RES)
+
+ole2ui.rc : $(RESOURCE)\$(LANG)\strings.rc
+
+#
+# Build .LIB static library
+#
+
+$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ)
+ -del $(O)$(LIBNAME).lib
+ lib @<<
+$(O)$(LIBNAME).lib
+y
+$(PRECOMPOBJ: = +) $(LIBOBJS: = +)
+
+<<
+ copy $(O)$(LIBNAME).lib $(LIBNAME).lib
+
+#
+# Build .DLL dynamic-link library
+#
+
+# HACK!
+# XXXXX
+# after echo LIBRARY $(LIBNAME) INITINSTANCE
+$(O)$(LIBNAME).exe: $(LIBOBJS) $(PRECOMPOBJ) $(DLLOBJS) $(O)ole2ui.res defoleui.def
+ @echo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄį Linking UILibrary ®ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
+ -del $(LIBNAME).def
+ @echo Creating <<$(LIBNAME).def
+LIBRARY ole2ui
+DESCRIPTION 'OLE 2.0 UI Support Library.'
+<<KEEP
+ type defoleui.def >> $(LIBNAME).def
+ $(LK) @<<
+$(LFLAGS)
+$(LIBOBJS: = ^
+)
+$(DLLOBJS: = ^
+)
+$(O)$(LIBNAME).res
+$(UILIBS)
+/DEF:$(LIBNAME).def
+<<KEEP
+# $(RS) $(O)ole2ui.res $(O)$(LIBNAME).dll
+
+
+#$(LIBOBJS: = +^
+#) +
+#$(DLLOBJS: = +^
+#)+
+#$(PRECOMPOBJ: = +^
+#)
+#$(LFLAGS)
+#$(O)$(@B)
+#$(@B).map
+#$(UILIBS)
+#$(LIBNAME).def
+#<<KEEP
+# $(RS) -31 -K $(RFLAGS) $(O)ole2ui.res $(O)$(LIBNAME).exe
+
+!ifndef SRCTOK
+$(LIBNAME).dll: $(O)$(LIBNAME).exe ole2ui.def
+# copy $(O)$(LIBNAME).exe $(LIBNAME).dll
+ mapsym -n -l $(LIBNAME).map
+# implib -NOWEP $(LIBNAME).lib $(LIBNAME).dll
+!else
+$(LIBNAME).dll: $(O)ole2ui.res
+ copy $(RESOURCE)\USA\$(LIBNAME).dll $(LIBNAME).dll
+# 16 bit $(RS) -31 -K $(RFLAGS) $(O)ole2ui.res $(LIBNAME).dll
+ $(RS) $(O)ole2ui.res $(LIBNAME).dll
+!endif
+
+
+# install built library to $(INSTALL_DIR) dir
+install:
+ @echo Gets HERE!!!!!!
+ copy $(LIBNAME).dll $(RESOURCE)\USA
+ copy $(LIBNAME).dll $(INSTALL_DIR)
+ copy $(LIBNAME).lib $(INSTALL_DIR)
+ copy $(LIBNAME).sym $(INSTALL_DIR)
+ copy ole2ui.h $(INSTALL_DIR)
+ copy olestd.h $(INSTALL_DIR)
+ copy msgfiltr.h $(INSTALL_DIR)
+ copy enumfetc.h $(INSTALL_DIR)
+ copy uiclass.h $(INSTALL_DIR)
+
+# EOF ========================================================================
diff --git a/private/oleutest/letest/ole2ui/makelib b/private/oleutest/letest/ole2ui/makelib
new file mode 100644
index 000000000..f7729d5d3
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/makelib
@@ -0,0 +1,503 @@
+# ============================================================================
+# File: MAKELIB
+#
+# NMAKE description file to build STATIC version of OLE2.0 User Interface LIB
+#
+# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved.
+# ============================================================================
+#
+# Usage Notes:
+# -----------
+#
+# This makefile is designed to be used in one step. This makefile does
+# NOT use the file called UIMAKE.INI. This makefile builds the following
+# libraries (depending on the value of "LIBFORDLL" and "DEBUG"):
+# OLE2UIX.LIB -- static RETAIL library to be used with EXE's
+# OLE2UIXD.LIB -- static DEBUG library to be used with EXE's
+#
+# OLE2UID.LIB -- static RETAIL library to be used with DLL's
+# OLE2UIDD.LIB -- static DEBUG library to be used with DLL's
+#
+# It is NOT necessary to build custom versions of the static
+# library version of OLE2UI. Everyone can use the same static OLE2UI
+# libraries as built by this makefile.
+#
+# NMAKE -F MAKELIB
+# NMAKE -F MAKELIB DEBUG=0
+# NMAKE -F MAKELIB LIBFORDLL=1
+# NMAKE -F MAKELIB LIBFORDLL=1 DEBUG=0
+#
+#
+# The following lists a few of the settings in this makefile file which
+# you might change, and what effect those changes might have. For a
+# complete listing of all the available options and how they are used,
+# see the makefile below.
+#
+# MODEL=[M|L] -- The memory model. (Default: M)
+# DEBUG=[0|1] -- Enable DEBUG or RETAIL version (Default: 1)
+# LIBFORDLL=[0|1] -- Enable DEBUG or RETAIL version (Default: 0)
+# SAMPLIB_DIR -- Directory to install built .LIB file
+# (Default: \ole2\samp\bin)
+# SAMPINC_DIR -- Directory to install public header files
+# (Default: \ole2\samp\include)
+# OLELIB_DIR -- Directory for OLE2 libraries
+# (Default: \ole2\bin)
+# OLEINC_DIR -- Directory for OLE2 public header files
+# (Default: \ole2\include)
+#
+# Comments:
+# --------
+#
+# In order to use the static library form of the OLE2UI library then you must
+# include "ole2ui.rc" resource file in your applications resource file. Also
+# "OleUIInitialize" must be called before calling any library functions.
+# This is called typically before entering the main message loop in an EXE
+# and called from LibMain for an in-proc server (DLL). Two unique strings
+# should be passed as paramters to OleUIInitialize. These strings are used
+# as class names for two custom controls used in the OLE2UI dialogs.
+# Before shutting down "OleUIUninitialize" must be called in order to clean up
+# resources used by the OLE2UI library. In an EXE, this is typically called
+# after leaving the main message loop; in an DLL, this is typically called
+# from the DLL's WEP function.
+# If the OLE2UI library is used in DLL form then explicitly including the
+# "ole2ui.rc" resource file and calling OleUIInitialize/OleUIUninitialize
+# is NOT necessary.
+# ============================================================================
+
+DEBUG=1
+MODEL=M
+LIBFORDLL=0
+NOASSERT=1
+OLE201=1
+DOS=1
+
+!if "$(OPSYS)"=="DOS"
+OBJDIR=objidd
+!else
+OBJDIR=obji1d
+!endif
+
+!ifndef SAMPINC_DIR
+SAMPINC_DIR=..\include
+!endif
+
+!ifndef SAMPLIB_DIR
+SAMPLIB_DIR=..\lib
+!endif
+
+!ifndef OLEINC_DIR
+!if "$(OPSYS)"=="DOS"
+OLEINC_DIR=..\..\include;$(CAIROLE)\h\export;$(IMPORT)\CHICAGO\h;\
+ $(IMPORT)\CHICAGO\h\crt;$(COMMON)\ih;$(COMMON)\types
+!else
+OLEINC_DIR=..\..\include;$(CAIROLE)\h\export;$(IMPORT)\$(OPSYS)\h\sdk;\
+ $(IMPORT)\$(OPSYS)\h\sdk\crt;$(COMMON)\ih;$(COMMON)\types
+!endif
+!endif
+
+!ifndef OLELIB_DIR
+!if "$(OPSYS)"=="DOS"
+OLELIB_DIR=..\..\lib;$(CAIROLE)\ilib\$(OBJDIR);$(IMPORT)\chicago\lib
+!else
+OLELIB_DIR=..\..\lib;$(CAIROLE)\ilib\$(OBJDIR)
+!endif
+!endif
+
+!if ("$(OLE201)"=="1")
+MISCFLAGS=/DOLE201
+!endif
+
+!if ("$(NOASSERT)"=="1")
+MISCFLAGS=$(MISCFLAGS) /DNOASSERT
+!endif
+
+!if ("$(DEBUG)"=="1")
+MSG=DEBUG Static LIB Version
+#CFLAGS=-c -Od -GA2s -W3 -Zpei -A$(MODEL) -D_DEBUG
+
+!ifdef WIN16
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE
+!else
+LFLAGS=/MAP:$(O)$(LIBNAME).map /DEBUGTYPE:CV /NOD /NOPACK
+!endif
+
+CC=$(IMPORT)\n386\bin\cl
+AS=$(IMPORT)\n386\bin\masm
+RS=$(IMPORT)\n386\bin\rc
+LINK=$(COMMON)\bin\link $(LFLAGS)
+LIB=lib
+
+!if ("$(LIBFORDLL)"=="1")
+#
+# Build DEBUG OLE2UI library for use with DLL's (eg. in-proc server objects)
+#
+MSG=DEBUG Static LIB Version (for use with DLL's)
+LIBNAME=OLE2UIDD
+OBJ=OLE2UIDD
+
+CFLAGS=-c -Od -W3 -Zpei -D_DEBUG -DDLL_VER -D_WINDLL -DLIBNAME=\"$$(LIBNAME)\"
+!ifdef WIN16
+CFLAGS=$(CFLAGS) -GD -GEd -AMw
+UILIBS=ldllcew libw ole2 storage shell
+!else
+CFLAGS=$(CFLAGS) -Gd -DWIN32 -DUNICODE -D_UNICODE -D_INC_OLE -D_X86_ $(MISCFLAGS)
+UILIBS=libw32.lib storag32.lib shell32.lib
+!if "$(OLE201)"=="1"
+UILIBS=$(UILIBS) ole2w32.lib
+!else
+UILIBS=$(UILIBS) ole232.lib
+!endif
+
+!endif
+
+LIBOBJS = $(UI_COBJS:D^\=OLE2UIDD^\) $(UI_NOPCOBJS:D^\=OLE2UIDD\NOPC^\)
+!else
+#
+# Build DEBUG OLE2UI library for use with EXE's
+#
+MSG=DEBUG Static LIB Version (for use with EXE's)
+LIBNAME=OLE2UIXD
+OBJ=OLE2UIXD
+
+CFLAGS=-c -Od -W3 -Zpei #-D_DEBUG
+!ifdef WIN16
+CFLAGS=$(CFLAGS) -GA2s -A$(MODEL)
+UILIBS=mlibcew libw ole2 storage shell
+!else
+CFLAGS=$(CFLAGS) -Gs -DWIN32 -DUNICODE -D_UNICODE -D_INC_OLE -D_X86_ $(MISCFLAGS)
+
+!if "$(OPSYS)"=="DOS"
+UILIBS= $(IMPORT)\CHICAGO\lib\advapi32.lib \
+ $(IMPORT)\CHICAGO\lib\comdlg32.lib \
+ $(IMPORT)\CHICAGO\lib\crtdll.lib \
+ $(IMPORT)\CHICAGO\lib\gdi32.lib \
+ $(IMPORT)\CHICAGO\lib\kernel32.lib \
+ $(IMPORT)\CHICAGO\lib\libcmt.lib \
+ $(IMPORT)\CHICAGO\lib\shell32.lib \
+ $(IMPORT)\CHICAGO\lib\user32.lib \
+ $(IMPORT)\CHICAGO\lib\wsock32.lib
+!else
+UILIBS= $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\advapi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\comdlg32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\crtdll.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\gdi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\kernel32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\libcmt.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\shell32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\user32.lib
+!endif
+UILIBS= $(UILIBS) \
+ $(CAIROLE)\ilib\$(OBJDIR)\ole2w32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\storag32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib
+
+!endif
+
+LIBOBJS = $(UI_COBJS:D^\=OLE2UIXD^\) $(UI_NOPCOBJS:D^\=OLE2UIXD\NOPC^\)
+!endif
+
+!else
+
+#CFLAGS=-c -Os -GA2s -W3 -Zpe -A$(MODEL)
+
+!ifdef WIN16
+LFLAGS=/MAP:FULL /LINE /NOD /NOE /SE:300 /NOPACKCODE
+!else
+LFLAGS=/MAP:$(O)$(LIBNAME).map /NOD /NOPACK
+!endif
+
+CC=$(IMPORT)\n386\bin\cl
+AS=$(IMPORT)\n386\bin\masm
+RS=$(IMPORT)\n386\bin\rc
+LINK=$(COMMON)\bin\link $(LFLAGS)
+LIB=lib
+
+!if ("$(LIBFORDLL)"=="1")
+#
+# Build RETAIL OLE2UI library for use with DLL's (eg. in-proc server objects)
+#
+MSG=RETAIL Static LIB Version (for use with DLL's)
+LIBNAME=OLE2UID
+OBJ=OLE2UID
+
+CFLAGS=-c -Os -D_WINDLL -W3 -Zpe
+!ifdef WIN16
+CFLAGS=$(CFLAGS) -GD -GEd -A$(MODEL)
+UILIBS=ldllcew libw ole2 storage shell
+!else
+CFLAGS=$(CFLAGS) -Gd -DWIN32 -DUNICODE -D_UNICODE -D_INC_OLE -D_X86_ $(MISCFLAGS)
+
+!if "$(OPSYS)"=="DOS"
+UILIBS= $(IMPORT)\CHICAGO\lib\advapi32.lib \
+ $(IMPORT)\CHICAGO\lib\comdlg32.lib \
+ $(IMPORT)\CHICAGO\lib\crtdll.lib \
+ $(IMPORT)\CHICAGO\lib\gdi32.lib \
+ $(IMPORT)\CHICAGO\lib\kernel32.lib \
+ $(IMPORT)\CHICAGO\lib\libcmt.lib \
+ $(IMPORT)\CHICAGO\lib\shell32.lib \
+ $(IMPORT)\CHICAGO\lib\user32.lib
+!else
+UILIBS= $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\advapi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\comdlg32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\crtdll.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\gdi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\kernel32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\libcmt.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\shell32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\user32.lib
+!endif
+UILIBS= $(UILIBS) \
+ $(CAIROLE)\ilib\$(OBJDIR)\ole2w32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\storag32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib
+
+!endif
+
+LIBOBJS = $(UI_COBJS:D^\=OLE2UID^\) $(UI_NOPCOBJS:D^\=OLE2UID\NOPC^\)
+!else
+#
+# Build RETAIL OLE2UI library for use with EXE's
+#
+MSG=RETAIL Static LIB Version (for use with EXE's)
+LIBNAME=OLE2UIX
+OBJ=OLE2UIX
+
+CFLAGS=-c -Os -W3 -Zpe
+!ifdef WIN16
+CFLAGS=$(CFLAGS) -GA2s -GEs -A$(MODEL)
+UILIBS=mlibcew libw ole2 storage shell
+!else
+CFLAGS=$(CFLAGS) -Gs -DWIN32 -DUNICODE -D_UNICODE -D_INC_OLE -D_X86_ $(MISCFLAGS)
+
+!if "$(OPSYS)"=="DOS"
+UILIBS= $(IMPORT)\CHICAGO\lib\advapi32.lib \
+ $(IMPORT)\CHICAGO\lib\comdlg32.lib \
+ $(IMPORT)\CHICAGO\lib\crtdll.lib \
+ $(IMPORT)\CHICAGO\lib\gdi32.lib \
+ $(IMPORT)\CHICAGO\lib\kernel32.lib \
+ $(IMPORT)\CHICAGO\lib\libcmt.lib \
+ $(IMPORT)\CHICAGO\lib\shell32.lib \
+ $(IMPORT)\CHICAGO\lib\user32.lib
+!else
+UILIBS= $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\advapi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\comdlg32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\crtdll.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\gdi32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\kernel32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\libcmt.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\shell32.lib \
+ $(IMPORT)\$(OPSYS)\lib\$(OBJDIR)\user32.lib
+!endif
+UILIBS= $(UILIBS) \
+ $(CAIROLE)\ilib\$(OBJDIR)\ole2w32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\storag32.lib \
+ $(CAIROLE)\ilib\$(OBJDIR)\compob32.lib
+
+!endif
+
+LIBOBJS = $(UI_COBJS:D^\=OLE2UIX^\) $(UI_NOPCOBJS:D^\=OLE2UIX\NOPC^\)
+!endif
+
+!endif
+
+GOAL: PRELUDE $(LIBNAME).LIB
+
+# ----------------------------------------------------------------------------
+# O B J E C T F I L E L I S T
+# ----------------------------------------------------------------------------
+
+UI_COBJS = \
+ D^\busy.obj\
+ D^\common.obj\
+ D^\convert.obj\
+ D^\dbgutil.obj\
+ D^\drawicon.obj\
+ D^\hatch.obj\
+ D^\icon.obj\
+ D^\iconbox.obj\
+ D^\insobj.obj\
+ D^\links.obj\
+ D^\msgfiltr.obj\
+ D^\enumfetc.obj\
+ D^\enumstat.obj\
+ D^\objfdbk.obj\
+ D^\ole2ui.obj\
+ D^\olestd.obj\
+ D^\targtdev.obj\
+ D^\oleutl.obj\
+ D^\pastespl.obj\
+ D^\regdb.obj\
+ D^\resimage.obj\
+ D^\utility.obj\
+
+UI_NOPCOBJS = \
+ D^\geticon.obj\
+ D^\dballoc.obj\
+ D^\suminfo.obj\
+ D^\stdpal.obj\
+
+PRECOMPOBJ= $(O)precomp.obj
+
+PRECOMP=$(O)precomp.pch
+
+# ----------------------------------------------------------------------------
+# R E S O U R C E L I S T
+# ----------------------------------------------------------------------------
+RES = \
+ busy.h \
+ common.h \
+ convert.h \
+ edlinks.h \
+ geticon.h \
+ icon.h \
+ iconbox.h \
+ insobj.h \
+ msgfiltr.h \
+ enumfetc.h \
+ ole2ui.h \
+ pastespl.h \
+ resimage.h \
+ dballoc.h \
+ suminfo.h \
+ stdpal.h \
+
+
+.SUFFIXES: .c .cpp .obj
+
+O=.\$(OBJ)^\
+
+!if [if not exist $(OBJ)\*. md $(OBJ) >nul]
+!error Object subdirectory $(OBJ)\ could not be created
+!endif
+!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul]
+!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created
+!endif
+
+# ----------------------------------------------------------------------------
+# I N F E R E N C E R U L E S
+# ----------------------------------------------------------------------------
+
+# compile C file without precompiled headers into object directory\NOPC
+# dont compile c files etc for lcoalized builds.
+{}.c{$(O)NOPC\}.obj:
+ @echo Are you compiling with OLE 2.01 ??????
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c
+!endif
+
+# compile C file into object directory
+{}.c{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c
+!endif
+
+# compile CPP file without precompiled headers into object directory\NOPC
+# dont compile cpp files etc for lcoalized builds.
+{}.cpp{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp
+!else
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp
+!endif
+
+# compile CPP file into object directory
+{}.cpp{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).cpp
+!else
+ $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp
+!endif
+
+
+# ----------------------------------------------------------------------------
+# D E P E N D F I L E C R E A T I O N
+# ----------------------------------------------------------------------------
+UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c)
+UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c)
+DEPEND: nul
+ @echo Making a NEW dependancy file.
+ mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp
+ sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend
+ -del tmp.tmp
+ mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend
+ mkdep -p $$(O) -s .pch precomp.c >> depend
+
+# ----------------------------------------------------------------------------
+# W E L C O M E B A N N E R
+# ----------------------------------------------------------------------------
+PRELUDE:
+ @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+ @echo º Makefile for UILibrary º
+ @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+ @echo $(MSG)
+!ifndef SRCTOK
+ set INCLUDE=$(OLEINC_DIR);$(INCLUDE)
+ set LIB=$(OLELIB_DIR);$(LIB)
+!endif
+
+
+# ----------------------------------------------------------------------------
+# G O A L T A R G E T S
+# ----------------------------------------------------------------------------
+!include "depend"
+
+CLEAN: CleanUp
+CleanUp:
+ -echo y|del .\$(OBJ)\*.*
+ -echo y|del .\$(OBJ)\NOPC\*.*
+ -del $(LIBNAME).lib
+
+$(O)precomp.pch: precomp.c
+!ifdef DOS
+ SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h
+ $(CC) -Fo$(O)$(@B) precomp.c
+!else
+ $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c
+!endif
+
+#
+# Build .LIB static library
+#
+
+$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ)
+ -del $(O)$(LIBNAME).lib
+!ifdef WIN16
+ lib @<<
+$(O)$(LIBNAME).lib
+y
+$(PRECOMPOBJ: = +) $(LIBOBJS: = +)
+
+<<
+!else
+ $(LINK) @<<
+/OUT:$(O)$(LIBNAME).lib
+/MACHINE:i386
+$(PRECOMPOBJ: = ) $(LIBOBJS: = ) $(UILIBS)
+
+<<
+!endif
+ copy $(O)$(LIBNAME).lib $(LIBNAME).lib
+
+
+# install built library and public header files to release directories
+install:
+ copy $(LIBNAME).lib $(SAMPLIB_DIR)
+ copy ole2ui.h $(SAMPINC_DIR)
+ copy olestd.h $(SAMPINC_DIR)
+ copy msgfiltr.h $(SAMPINC_DIR)
+ copy enumfetc.h $(SAMPINC_DIR)
+
+# EOF ========================================================================
+ \ No newline at end of file
diff --git a/private/oleutest/letest/ole2ui/msgfiltr.c b/private/oleutest/letest/ole2ui/msgfiltr.c
new file mode 100644
index 000000000..562dfb802
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/msgfiltr.c
@@ -0,0 +1,809 @@
+/*
+ * MSGFILTR.C
+ *
+ * This file contains a standard implementation of IMessageFilter
+ * interface.
+ * This file is part of the OLE 2.0 User Interface support library.
+ *
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ *
+ */
+
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "msgfiltr.h"
+
+OLEDBGDATA
+
+
+typedef struct tagOLESTDMESSAGEFILTER {
+ IMessageFilterVtbl FAR* m_lpVtbl;
+ UINT m_cRef;
+ HWND m_hWndParent;
+ DWORD m_dwInComingCallStatus; // Status to return from
+ // HandleIncomingCall
+ HANDLEINCOMINGCALLBACKPROC m_lpfnHandleInComingCallback;
+ // Callback function
+ // to selectively handle
+ // interface method calls
+ BOOL m_fEnableBusyDialog; // enable RetryRejected
+ // Call dialog
+ BOOL m_fEnableNotRespondingDialog; // enable
+ // MessagePending dialog
+ MSGPENDINGPROC m_lpfnMessagePendingCallback; // MessagePending
+ // Callback function
+ LPFNOLEUIHOOK m_lpfnBusyDialogHookCallback; // Busy dialog hook
+ LPTSTR m_lpszAppName; // Name of application
+ // installing filter
+ HWND m_hWndBusyDialog; // HWND of busy dialog. Used
+ // to tear down dialog.
+ BOOL m_bUnblocking;
+
+ }OLESTDMESSAGEFILTER, FAR* LPOLESTDMESSAGEFILTER;
+
+/* interface IMessageFilter implementation */
+STDMETHODIMP OleStdMsgFilter_QueryInterface(
+ LPMESSAGEFILTER lpThis, REFIID riid, LPVOID FAR* ppvObj);
+STDMETHODIMP_(ULONG) OleStdMsgFilter_AddRef(LPMESSAGEFILTER lpThis);
+STDMETHODIMP_(ULONG) OleStdMsgFilter_Release(LPMESSAGEFILTER lpThis);
+STDMETHODIMP_(DWORD) OleStdMsgFilter_HandleInComingCall (
+ LPMESSAGEFILTER lpThis,
+ DWORD dwCallType,
+ HTASK htaskCaller,
+ DWORD dwTickCount,
+#ifdef WIN32
+ LPINTERFACEINFO dwReserved
+#else
+ DWORD dwReserved
+#endif
+);
+STDMETHODIMP_(DWORD) OleStdMsgFilter_RetryRejectedCall (
+ LPMESSAGEFILTER lpThis,
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwRejectType
+);
+STDMETHODIMP_(DWORD) OleStdMsgFilter_MessagePending (
+ LPMESSAGEFILTER lpThis,
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwPendingType
+);
+
+
+static IMessageFilterVtbl g_OleStdMessageFilterVtbl = {
+ OleStdMsgFilter_QueryInterface,
+ OleStdMsgFilter_AddRef,
+ OleStdMsgFilter_Release,
+ OleStdMsgFilter_HandleInComingCall,
+ OleStdMsgFilter_RetryRejectedCall,
+ OleStdMsgFilter_MessagePending
+};
+
+
+/* GetTopWindowInWindowsTask
+** -------------------------
+** Get the top most window that has focus in the given task to be
+** used as the parent for the busy dialog. we do this to handle the
+** case where a dialog window is currently up when we need to give
+** the busy dialog. if we use the current assigned parent window
+** (which typically will be the frame window of the app), then the
+** busy dialog will not be modal to the current active dialog
+** window.
+*/
+static HWND GetTopWindowInWindowsTask(HWND hwnd)
+{
+ HWND hwndActive = GetActiveWindow();
+ if (!hwndActive)
+ return hwnd;
+
+ if (GetWindowTask(hwnd) == GetWindowTask(hwndActive))
+ return hwndActive;
+ else
+ return hwnd;
+}
+
+STDAPI_(LPMESSAGEFILTER) OleStdMsgFilter_Create(
+ HWND hWndParent,
+ LPTSTR szAppName,
+ MSGPENDINGPROC lpfnCallback,
+ LPFNOLEUIHOOK lpfnOleUIHook // Busy dialog hook callback
+)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter;
+ LPMALLOC lpMalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR)
+ return NULL;
+
+ lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpMalloc->lpVtbl->Alloc(
+ lpMalloc, (sizeof(OLESTDMESSAGEFILTER)));
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ if (! lpStdMsgFilter) return NULL;
+
+ lpStdMsgFilter->m_lpVtbl = &g_OleStdMessageFilterVtbl;
+ lpStdMsgFilter->m_cRef = 1;
+ lpStdMsgFilter->m_hWndParent = hWndParent;
+ lpStdMsgFilter->m_dwInComingCallStatus = SERVERCALL_ISHANDLED;
+ lpStdMsgFilter->m_lpfnHandleInComingCallback = NULL;
+ lpStdMsgFilter->m_fEnableBusyDialog = TRUE;
+ lpStdMsgFilter->m_fEnableNotRespondingDialog = TRUE;
+ lpStdMsgFilter->m_lpszAppName = szAppName;
+ lpStdMsgFilter->m_lpfnMessagePendingCallback = lpfnCallback;
+ lpStdMsgFilter->m_lpfnBusyDialogHookCallback = lpfnOleUIHook;
+ lpStdMsgFilter->m_hWndBusyDialog = NULL;
+ lpStdMsgFilter->m_bUnblocking = FALSE;
+
+ return (LPMESSAGEFILTER)lpStdMsgFilter;
+}
+
+
+/* OleStdMsgFilter_SetInComingStatus
+** ---------------------------------
+** This is a private function that allows the caller to control what
+** value is returned from the IMessageFilter::HandleInComing method.
+**
+** if a HandleInComingCallbackProc is installed by a call to
+** OleStdMsgFilter_SetHandleInComingCallbackProc, then this
+** overrides the dwIncomingCallStatus established by a call to
+** OleStdMsgFilter_SetInComingStatus. Using
+** OleStdMsgFilter_SetInComingStatus allows the app to reject or
+** accept ALL in coming calls. Using a HandleInComingCallbackProc
+** allows the app to selectively handle or reject particular method
+** calls.
+*/
+
+STDAPI_(void) OleStdMsgFilter_SetInComingCallStatus(
+ LPMESSAGEFILTER lpThis, DWORD dwInComingCallStatus)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+
+ if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER)))
+ lpStdMsgFilter->m_dwInComingCallStatus = dwInComingCallStatus;
+ else
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_SetIncomingCallStatus: Invalid IMessageFilter*"));
+
+#if defined( _DEBUG )
+ {
+ TCHAR szBuf[80];
+ TCHAR *szReturn;
+
+ switch(dwInComingCallStatus) {
+ case SERVERCALL_ISHANDLED:
+ szReturn = TEXT("SERVERCALL_ISHANDLED");
+ break;
+ case SERVERCALL_REJECTED:
+ szReturn = TEXT("SERVERCALL_REJECTED");
+ break;
+ case SERVERCALL_RETRYLATER:
+ szReturn = TEXT("SERVERCALL_RETRYLATER");
+ break;
+ default:
+ szReturn = TEXT("** ERROR: UNKNOWN **");
+ break;
+ }
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_SetInComingCallStatus: Status set to %s.\r\n"),
+ (LPTSTR)szReturn
+ );
+ OleDbgOut3(szBuf);
+ }
+#endif
+
+}
+
+
+/* OleStdMsgFilter_SetHandleInComingCallbackProc
+** ---------------------------------------------
+** This is a private function that allows the caller to install (or
+** de-install) a special callback function to selectively
+** handle/reject specific incoming method calls on particular
+** interfaces.
+**
+** if a HandleInComingCallbackProc is installed by a call to
+** OleStdMsgFilter_SetHandleInComingCallbackProc, then this
+** overrides the dwIncomingCallStatus established by a call to
+** OleStdMsgFilter_SetInComingStatus. Using
+** OleStdMsgFilter_SetInComingStatus allows the app to reject or
+** accept ALL in coming calls. Using a HandleInComingCallbackProc
+** allows the app to selectively handle or reject particular method
+** calls.
+**
+** to de-install the HandleInComingCallbackProc, call
+** OleStdMsgFilter_SetHandleInComingCallbackProc(NULL);
+**
+** Returns previous callback proc in effect.
+*/
+
+STDAPI_(HANDLEINCOMINGCALLBACKPROC)
+ OleStdMsgFilter_SetHandleInComingCallbackProc(
+ LPMESSAGEFILTER lpThis,
+ HANDLEINCOMINGCALLBACKPROC lpfnHandleInComingCallback)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ HANDLEINCOMINGCALLBACKPROC lpfnPrevCallback =
+ lpStdMsgFilter->m_lpfnHandleInComingCallback;
+
+ if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER))) {
+ lpStdMsgFilter->m_lpfnHandleInComingCallback =
+ lpfnHandleInComingCallback;
+ } else {
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_SetIncomingCallStatus: Invalid IMessageFilter*"));
+ }
+
+#if defined( _DEBUG )
+ {
+ if (lpfnHandleInComingCallback)
+ OleDbgOut3(
+ TEXT("OleStdMsgFilter_SetHandleInComingCallbackProc SET\r\n"));
+ else
+ OleDbgOut3(
+ TEXT("OleStdMsgFilter_SetHandleInComingCallbackProc CLEARED\r\n"));
+
+ }
+#endif // _DEBUG
+
+ return lpfnPrevCallback;
+}
+
+
+/* OleStdMsgFilter_GetInComingStatus
+** ---------------------------------
+** This is a private function that returns the current
+** incoming call status. Can be used to disable/enable options
+** in the calling application.
+**
+** Returns: one of
+**
+** SERVERCALL_ISHANDLED
+** SERVERCALL_REJECTED
+** SERVERCALL_RETRYLATER
+** or -1 for ERROR
+**
+*/
+
+STDAPI_(DWORD) OleStdMsgFilter_GetInComingCallStatus(
+ LPMESSAGEFILTER lpThis)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ DWORD dwReturn;
+
+ if (!IsBadReadPtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER)))
+ dwReturn = lpStdMsgFilter->m_dwInComingCallStatus;
+ else
+ {
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_GetIncomingCallStatus: Invalid IMessageFilter*"));
+ dwReturn = (DWORD)-1;
+ }
+
+#if defined( _DEBUG )
+ {
+ TCHAR szBuf[80];
+ TCHAR *szReturn;
+
+ switch(dwReturn) {
+ case SERVERCALL_ISHANDLED:
+ szReturn = TEXT("SERVERCALL_ISHANDLED");
+ break;
+ case SERVERCALL_REJECTED:
+ szReturn = TEXT("SERVERCALL_REJECTED");
+ break;
+ case SERVERCALL_RETRYLATER:
+ szReturn = TEXT("SERVERCALL_RETRYLATER");
+ break;
+ default:
+ szReturn = TEXT("-1");
+ break;
+ }
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_GetInComingCallStatus returns %s.\r\n"),
+ (LPTSTR)szReturn
+ );
+ OleDbgOut3(szBuf);
+ }
+#endif
+
+ return dwReturn;
+}
+
+
+/* OleStdMsgFilter_EnableBusyDialog
+** --------------------------------
+** This function allows the caller to control whether
+** the busy dialog is enabled. this is the dialog put up when
+** IMessageFilter::RetryRejectedCall is called because the server
+** responded SERVERCALL_RETRYLATER or SERVERCALL_REJECTED.
+**
+** if the busy dialog is NOT enabled, then the rejected call is
+** immediately canceled WITHOUT prompting the user. in this situation
+** OleStdMsgFilter_RetryRejectedCall always retuns
+** OLESTDCANCELRETRY canceling the outgoing LRPC call.
+** If the busy dialog is enabled, then the user is given the choice
+** of whether to retry, switch to, or cancel.
+**
+** Returns previous dialog enable state
+*/
+
+STDAPI_(BOOL) OleStdMsgFilter_EnableBusyDialog(
+ LPMESSAGEFILTER lpThis, BOOL fEnable)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ BOOL fPrevEnable = lpStdMsgFilter->m_fEnableBusyDialog;
+
+ if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER)))
+ lpStdMsgFilter->m_fEnableBusyDialog = fEnable;
+ else
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_EnableBusyDialog: Invalid IMessageFilter*"));
+
+#if defined( _DEBUG )
+ {
+ TCHAR szBuf[80];
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_EnableBusyDialog: Dialog is %s.\r\n"),
+ fEnable ? (LPTSTR) TEXT("ENABLED") : (LPTSTR) TEXT("DISABLED")
+ );
+ OleDbgOut3(szBuf);
+ }
+#endif
+
+ return fPrevEnable;
+}
+
+
+/* OleStdMsgFilter_EnableNotRespondingDialog
+** -----------------------------------------
+** This function allows the caller to control whether
+** the app "NotResponding" (Blocked) dialog is enabled. this is the
+** dialog put up when IMessageFilter::MessagePending is called.
+** If the NotResponding dialog is enabled, then the user is given
+** the choice of whether to retry or switch to, but NOT to cancel.
+**
+** Returns previous dialog enable state
+*/
+
+STDAPI_(BOOL) OleStdMsgFilter_EnableNotRespondingDialog(
+ LPMESSAGEFILTER lpThis, BOOL fEnable)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ BOOL fPrevEnable = lpStdMsgFilter->m_fEnableNotRespondingDialog;
+
+ if (!IsBadWritePtr((LPVOID)lpStdMsgFilter, sizeof(OLESTDMESSAGEFILTER)))
+ lpStdMsgFilter->m_fEnableNotRespondingDialog = fEnable;
+ else
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_EnableNotRespondingDialog: Invalid IMessageFilter*"));
+
+#if defined( _DEBUG )
+ {
+ TCHAR szBuf[80];
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_EnableNotRespondingDialog: Dialog is %s.\r\n"),
+ fEnable ? (LPTSTR) TEXT("ENABLED") : (LPTSTR) TEXT("DISABLED")
+ );
+ OleDbgOut3(szBuf);
+ }
+#endif
+
+ return fPrevEnable;
+}
+
+
+/* OleStdMsgFilter_SetParentWindow
+** -------------------------------
+** This function allows caller to set which window will be used as
+** the parent for the busy dialog.
+**
+** OLE2NOTE: it would be inportant for an in-place active server to
+** reset this to its current in-place frame window when in-place
+** activated. if the hWndParent is set to NULL then the dialogs will
+** be parented to the desktop.
+**
+** Returns: previous parent window
+*/
+
+STDAPI_(HWND) OleStdMsgFilter_SetParentWindow(
+ LPMESSAGEFILTER lpThis, HWND hWndParent)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ HWND hWndPrev = lpStdMsgFilter->m_hWndParent;
+
+ lpStdMsgFilter->m_hWndParent = hWndParent;
+ return hWndPrev;
+}
+
+
+STDMETHODIMP OleStdMsgFilter_QueryInterface(
+ LPMESSAGEFILTER lpThis, REFIID riid, LPVOID FAR* ppvObj)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ SCODE scode;
+
+ /* Two interfaces supported: IUnknown, IMessageFilter
+ */
+
+ if (IsEqualIID(riid, &IID_IMessageFilter) || IsEqualIID(riid, &IID_IUnknown)) {
+ lpStdMsgFilter->m_cRef++; // A pointer to this object is returned
+ *ppvObj = lpThis;
+ scode = S_OK;
+ }
+ else { // unsupported interface
+ *ppvObj = NULL;
+ scode = E_NOINTERFACE;
+ }
+
+ return ResultFromScode(scode);
+}
+
+
+STDMETHODIMP_(ULONG) OleStdMsgFilter_AddRef(LPMESSAGEFILTER lpThis)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ return ++lpStdMsgFilter->m_cRef;
+}
+
+STDMETHODIMP_(ULONG) OleStdMsgFilter_Release(LPMESSAGEFILTER lpThis)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ LPMALLOC lpMalloc;
+
+ if (--lpStdMsgFilter->m_cRef != 0) // Still used by others
+ return lpStdMsgFilter->m_cRef;
+
+ // Free storage
+ if (CoGetMalloc(MEMCTX_TASK, (LPMALLOC FAR*)&lpMalloc) != NOERROR)
+ return (ULONG)0;
+
+ lpMalloc->lpVtbl->Free(lpMalloc, lpStdMsgFilter);
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ return (ULONG)0;
+}
+
+
+STDMETHODIMP_(DWORD) OleStdMsgFilter_HandleInComingCall (
+ LPMESSAGEFILTER lpThis,
+ DWORD dwCallType,
+ HTASK htaskCaller,
+ DWORD dwTickCount,
+#ifdef WIN32
+ LPINTERFACEINFO dwReserved
+#else
+ DWORD dwReserved
+#endif
+)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+
+ /* if a HandleInComingCallbackProc is in effect, then this
+ ** overrides dwIncomingCallStatus established by a call to
+ ** OleStdMsgFilter_SetInComingStatus. we will call this
+ ** callback to allow the app to selectively handle or reject
+ ** incoming method calls. the LPINTERFACEINFO parameter
+ ** describes which method is being called.
+ */
+ if (lpStdMsgFilter->m_lpfnHandleInComingCallback &&
+ !IsBadCodePtr((FARPROC)lpStdMsgFilter->m_lpfnHandleInComingCallback)){
+ return lpStdMsgFilter->m_lpfnHandleInComingCallback(
+ dwCallType,
+ htaskCaller,
+ dwTickCount,
+ dwReserved
+ );
+ }
+
+ switch (dwCallType) {
+ case CALLTYPE_TOPLEVEL:
+ /* OLE2NOTE: we currently have NO pending outgoing call and
+ ** there is a new toplevel incoming call.
+ ** this call may be rejected.
+ */
+ return lpStdMsgFilter->m_dwInComingCallStatus;
+
+ case CALLTYPE_TOPLEVEL_CALLPENDING:
+ /* OLE2NOTE: we currently HAVE a pending outgoing call and
+ ** there is a new toplevel incoming call.
+ ** this call may be rejected.
+ */
+ return lpStdMsgFilter->m_dwInComingCallStatus;
+
+ case CALLTYPE_NESTED:
+ /* OLE2NOTE: we currently HAVE a pending outgoing call and
+ ** there callback on behalf of the previous outgoing
+ ** call. this type of call should ALWAYS be handled.
+ */
+ return SERVERCALL_ISHANDLED;
+
+ case CALLTYPE_ASYNC:
+ /* OLE2NOTE: we currently have NO pending outgoing call and
+ ** there is a new asyncronis incoming call.
+ ** this call can NEVER be rejected. OLE actually ignores
+ ** the return code in this case and always allows the
+ ** call through.
+ */
+ return SERVERCALL_ISHANDLED; // value returned does not matter
+
+ case CALLTYPE_ASYNC_CALLPENDING:
+ /* OLE2NOTE: we currently HAVE a pending outgoing call and
+ ** there is a new asyncronis incoming call.
+ ** this call can NEVER be rejected. OLE ignore the
+ ** return code in this case.
+ */
+ return SERVERCALL_ISHANDLED; // value returned does not
+
+ default:
+ OleDbgAssert(
+ TEXT("OleStdMsgFilter_HandleInComingCall: Invalid CALLTYPE"));
+ return lpStdMsgFilter->m_dwInComingCallStatus;
+ }
+}
+
+STDMETHODIMP_(DWORD) OleStdMsgFilter_RetryRejectedCall (
+ LPMESSAGEFILTER lpThis,
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwRejectType
+)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ DWORD dwRet = 0;
+ UINT uRet;
+#if defined( _DEBUG )
+ TCHAR szBuf[80];
+#endif
+ OLEDBG_BEGIN2(TEXT("OleStdMsgFilter_RetryRejectedCall\r\n"))
+
+ /* OLE2NOTE: we should only put up the application busy dialog when
+ ** the callee has responded SERVERCALL_RETRYLATER. if the
+ ** dwRejectType is SERVERCALL_REJECTED then there is something
+ ** seriously wrong with the callee (perhaps a severe low memory
+ ** situation). we don't want to even try to "Switch To" this app
+ ** or even try to "Retry".
+ */
+ if (dwRejectType == SERVERCALL_RETRYLATER &&
+ lpStdMsgFilter->m_fEnableBusyDialog) {
+
+ OLEUIBUSY bz;
+
+ /* OLE2NOTE: we do not want to put up the Busy dialog immediately
+ ** the when an app says RETRYLATER. we should continue retrying
+ ** for a while in case the app can un-busy itself in a
+ ** reasonable amount of time.
+ */
+ if (dwTickCount <= (DWORD)OLESTDRETRYDELAY) {
+ dwRet = 500; // Retry after .5 sec
+ OLEDBG_END2
+ return dwRet;
+ }
+
+ /*
+ ** Set up structure for calling OLEUIBUSY dialog
+ */
+
+ bz.cbStruct = sizeof(OLEUIBUSY);
+ bz.dwFlags = 0L;
+ bz.hWndOwner =GetTopWindowInWindowsTask(lpStdMsgFilter->m_hWndParent);
+ bz.lpszCaption = lpStdMsgFilter->m_lpszAppName;
+ bz.lpfnHook = lpStdMsgFilter->m_lpfnBusyDialogHookCallback;
+ bz.lCustData = 0;
+ bz.hInstance = NULL;
+ bz.lpszTemplate = NULL;
+ bz.hResource = 0;
+ bz.hTask = htaskCallee;
+ bz.lphWndDialog = NULL; // We don't need the hDlg for this call
+
+ uRet = OleUIBusy(&bz);
+
+ switch (uRet) {
+ case OLEUI_BZ_RETRYSELECTED:
+ dwRet = 0; // Retry immediately
+ break;
+
+ case OLEUI_CANCEL:
+ dwRet = OLESTDCANCELRETRY; // Cancel pending outgoing call
+ break;
+
+ case OLEUI_BZERR_HTASKINVALID:
+ // Htask was invalid, return OLESTDRETRYDELAY anyway
+ dwRet = OLESTDRETRYDELAY; // Retry after <retry delay> msec
+
+#if defined( _DEBUG )
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_RetryRejectedCall, HTASK 0x%x invalid\r\n"),
+ htaskCallee
+ );
+ OleDbgOut3(szBuf);
+#endif
+ break;
+ }
+ } else {
+ dwRet = OLESTDCANCELRETRY; // Cancel pending outgoing call
+ }
+
+#if defined( _DEBUG )
+ wsprintf(szBuf,
+ TEXT("OleStdMsgFilter_RetryRejectedCall returns %d\r\n"),
+ dwRet);
+ OleDbgOut3(szBuf);
+#endif
+
+ OLEDBG_END2
+ return dwRet;
+}
+
+
+
+/* a significant message is consider a mouse click or keyboard input. */
+#define IS_SIGNIFICANT_MSG(lpmsg) \
+ ( \
+ (PeekMessage((lpmsg), NULL, WM_LBUTTONDOWN, WM_LBUTTONDOWN, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ || (PeekMessage((lpmsg), NULL, WM_LBUTTONDBLCLK, WM_LBUTTONDBLCLK, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ || (PeekMessage((lpmsg), NULL, WM_NCLBUTTONDOWN, WM_NCLBUTTONDOWN, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ || (PeekMessage((lpmsg), NULL, WM_NCLBUTTONDBLCLK, WM_NCLBUTTONDBLCLK, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ || (PeekMessage((lpmsg), NULL, WM_KEYDOWN, WM_KEYDOWN, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ || (PeekMessage((lpmsg), NULL, WM_SYSKEYDOWN, WM_SYSKEYDOWN, \
+ PM_NOREMOVE | PM_NOYIELD)) \
+ )
+
+STDMETHODIMP_(DWORD) OleStdMsgFilter_MessagePending (
+ LPMESSAGEFILTER lpThis,
+ HTASK htaskCallee,
+ DWORD dwTickCount,
+ DWORD dwPendingType
+)
+{
+ LPOLESTDMESSAGEFILTER lpStdMsgFilter = (LPOLESTDMESSAGEFILTER)lpThis;
+ DWORD dwReturn = PENDINGMSG_WAITDEFPROCESS;
+ MSG msg;
+ BOOL fIsSignificantMsg = IS_SIGNIFICANT_MSG(&msg);
+ UINT uRet;
+
+#if defined( _DEBUG )
+ TCHAR szBuf[128];
+ wsprintf(
+ szBuf,
+ TEXT("OleStdMsgFilter_MessagePending, dwTickCount = 0x%lX\r\n"),
+ (DWORD)dwTickCount
+ );
+ OleDbgOut4(szBuf);
+#endif
+
+ /* OLE2NOTE: If our tick count for this call exceeds our standard retry
+ ** delay, then we need to put up the dialog. We will only
+ ** consider putting up the dialog if the user has issued a
+ ** "significant" event (ie. mouse click or keyboard event). a
+ ** simple mouse move should NOT trigger this dialog.
+ ** Since our call to
+ ** OleUIBusy below enters a DialogBox() message loop, there's a
+ ** possibility that another call will be initiated during the dialog,
+ ** and this procedure will be re-entered. Just so we don't put up
+ ** two dialogs at a time, we use the m_bUnblocking varable
+ ** to keep track of this situation.
+ */
+
+ if (dwTickCount > (DWORD)OLESTDRETRYDELAY && fIsSignificantMsg
+ && !lpStdMsgFilter->m_bUnblocking)
+ {
+
+ if (lpStdMsgFilter->m_fEnableNotRespondingDialog)
+ {
+ OLEUIBUSY bz;
+
+ lpStdMsgFilter->m_bUnblocking = TRUE;
+
+ // Eat messages in our queue that we do NOT want to be dispatched
+ while (PeekMessage(&msg, NULL, WM_CLOSE, WM_CLOSE, PM_REMOVE | PM_NOYIELD));
+
+ /* Set up structure for calling OLEUIBUSY dialog,
+ ** using the "not responding" variety
+ */
+
+ bz.cbStruct = sizeof(OLEUIBUSY);
+ bz.dwFlags = BZ_NOTRESPONDINGDIALOG;
+ bz.hWndOwner =GetTopWindowInWindowsTask(lpStdMsgFilter->m_hWndParent);
+ bz.lpszCaption = lpStdMsgFilter->m_lpszAppName;
+ bz.lpfnHook = lpStdMsgFilter->m_lpfnBusyDialogHookCallback;
+ bz.lCustData = 0;
+ bz.hInstance = NULL;
+ bz.lpszTemplate = NULL;
+ bz.hResource = 0;
+ bz.hTask = htaskCallee;
+
+ /* Set up the address to the hWnd in our MsgFilter structure. The
+ ** call to OleUIBusy will fill this in with the hWnd of the busy
+ ** dialog box
+ */
+
+ bz.lphWndDialog = (HWND FAR *)&(lpStdMsgFilter->m_hWndBusyDialog);
+ uRet = OleUIBusy(&bz);
+
+ lpStdMsgFilter->m_bUnblocking = FALSE;
+
+ return PENDINGMSG_WAITNOPROCESS;
+ }
+#if defined( _DEBUG )
+ else {
+ OleDbgOut3(TEXT("OleStdMsgFilter_MessagePending: BLOCKED but dialog Disabled\r\n"));
+ }
+#endif
+ }
+
+ /* If we're already unblocking, we're being re-entered. Don't
+ ** process message
+ */
+
+ if (lpStdMsgFilter->m_bUnblocking)
+ return PENDINGMSG_WAITDEFPROCESS;
+
+ /* OLE2NOTE: If we have a callback function set up, call it with the
+ ** current message. If not, tell OLE LPRC mechanism to automatically
+ ** handle all messages.
+ */
+ if (lpStdMsgFilter->m_lpfnMessagePendingCallback &&
+ !IsBadCodePtr((FARPROC)lpStdMsgFilter->m_lpfnMessagePendingCallback)){
+ MSG msg;
+
+ /* OLE2NOTE: the app provided a MessagePendingCallback
+ ** function. we will PeekMessage for the first message in
+ ** the queue and pass it to the app. the app in its callback
+ ** function can decide to Dispatch this message or it can
+ ** PeekMessage on its own giving particular message filter
+ ** criteria. if the app returns TRUE then we return
+ ** PENDINGMSG_WAITNOPROCESS to OLE telling OLE to leave the
+ ** message in the queue. If the app returns FALSE, then we
+ ** return PENDINGMSG_WAITDEFPROCESS to OLE telling OLE to do
+ ** its default processing with the message. by default OLE
+ ** dispatches system messages and eats other messages and
+ ** beeps.
+ */
+ if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD)) {
+
+ if (lpStdMsgFilter->m_lpfnMessagePendingCallback(&msg)) {
+ /* TRUE return means that the app processed message.
+ **
+ ** NOTE: (CHANGE FROM OLE2.0 VERSION) we leave it up to
+ ** the callback routine to remove the message if it
+ ** wants.
+ */
+ dwReturn = PENDINGMSG_WAITNOPROCESS;
+ } else {
+ /* FALSE means that the app did not process the
+ ** message. we will let OLE take its
+ ** default action.
+ **
+ ** NOTE: (CHANGE FROM OLE2.0 VERSION) we used to return
+ ** PENDINGMSG_WAITNOPROCESS to leave the message in
+ ** the queue; now we return PENDINGMSG_WAITDEFPROCESS
+ ** to let OLE do default processing.
+ */
+ dwReturn = PENDINGMSG_WAITDEFPROCESS;
+
+#if defined( _DEBUG )
+ wsprintf(
+ szBuf,
+ TEXT("Message (0x%x) (wParam=0x%x, lParam=0x%lx) using WAITDEFPROCESS while blocked\r\n"),
+ msg.message,
+ msg.lParam,
+ msg.wParam
+ );
+ OleDbgOut2(szBuf);
+#endif // _DEBUG
+ }
+ }
+ }
+
+ return dwReturn;
+}
diff --git a/private/oleutest/letest/ole2ui/msgfiltr.h b/private/oleutest/letest/ole2ui/msgfiltr.h
new file mode 100644
index 000000000..a542d5294
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/msgfiltr.h
@@ -0,0 +1,64 @@
+/*************************************************************************
+**
+** OLE 2 Utility Code
+**
+** msgfiltr.h
+**
+** This file contains Private definitions, structures, types, and
+** function prototypes for the OleStdMessageFilter implementation of
+** the IMessageFilter interface.
+** This file is part of the OLE 2.0 User Interface support library.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#if !defined( _MSGFILTR_H_ )
+#define _MSGFILTR_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING MSGFILTR.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+// Message Pending callback procedure
+typedef BOOL (CALLBACK* MSGPENDINGPROC)(MSG FAR *);
+
+// HandleInComingCall callback procedure
+typedef DWORD (CALLBACK* HANDLEINCOMINGCALLBACKPROC)
+ (
+ DWORD dwCallType,
+ HTASK htaskCaller,
+ DWORD dwTickCount,
+ LPINTERFACEINFO lpInterfaceInfo
+ );
+
+/* PUBLIC FUNCTIONS */
+STDAPI_(LPMESSAGEFILTER) OleStdMsgFilter_Create(
+ HWND hWndParent,
+ LPTSTR szAppName,
+ MSGPENDINGPROC lpfnCallback,
+ LPFNOLEUIHOOK lpfnOleUIHook // Busy dialog hook callback
+);
+
+STDAPI_(void) OleStdMsgFilter_SetInComingCallStatus(
+ LPMESSAGEFILTER lpThis, DWORD dwInComingCallStatus);
+
+STDAPI_(DWORD) OleStdMsgFilter_GetInComingCallStatus(
+ LPMESSAGEFILTER lpThis);
+
+STDAPI_(HANDLEINCOMINGCALLBACKPROC)
+ OleStdMsgFilter_SetHandleInComingCallbackProc(
+ LPMESSAGEFILTER lpThis,
+ HANDLEINCOMINGCALLBACKPROC lpfnHandleInComingCallback);
+
+STDAPI_(BOOL) OleStdMsgFilter_EnableBusyDialog(
+ LPMESSAGEFILTER lpThis, BOOL fEnable);
+
+STDAPI_(BOOL) OleStdMsgFilter_EnableNotRespondingDialog(
+ LPMESSAGEFILTER lpThis, BOOL fEnable);
+
+STDAPI_(HWND) OleStdMsgFilter_SetParentWindow(
+ LPMESSAGEFILTER lpThis, HWND hWndParent);
+
+
+#endif // _MSGFILTR_H_
diff --git a/private/oleutest/letest/ole2ui/objfdbk.c b/private/oleutest/letest/ole2ui/objfdbk.c
new file mode 100644
index 000000000..65e30f907
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/objfdbk.c
@@ -0,0 +1,246 @@
+/*
+ * OBJFDBK.C
+ *
+ * Miscellaneous API's to generate UI feedback effects for OLE objects. This
+ * is part of the OLE 2.0 User Interface Support Library.
+ * The following feedback effects are supported:
+ * 1. Object selection handles (OleUIDrawHandles)
+ * 2. Open Object window shading (OleUIDrawShading)
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+
+static void DrawHandle(HDC hdc, int x, int y, UINT cSize, BOOL bInvert, BOOL fDraw);
+
+/*
+ * OleUIDrawHandles
+ *
+ * Purpose:
+ * Draw handles or/and boundary around Container Object when selected
+ *
+ * Parameters:
+ * lpRect Dimensions of Container Object
+ * hdc HDC of Container Object (MM_TEXT mapping mode)
+ * dwFlags-
+ * Exclusive flags
+ * OLEUI_HANDLES_INSIDE Draw handles on inside of rect
+ * OLEUI_HANDLES_OUTSIDE Draw handles on outside of rect
+ * Optional flags
+ * OLEUI_HANDLES_NOBORDER Draw handles only, no rect
+ * OLEUI_HANDLES_USEINVERSE
+ * use invert for handles and rect, o.t. use COLOR_WINDOWTEXT
+ * cSize size of handle box
+ * fDraw Draw if TRUE, erase if FALSE
+ *
+ * Return Value: null
+ *
+ */
+STDAPI_(void) OleUIDrawHandles(
+ LPRECT lpRect,
+ HDC hdc,
+ DWORD dwFlags,
+ UINT cSize,
+ BOOL fDraw
+)
+{
+ HBRUSH hbr;
+ RECT rc;
+ int bkmodeOld;
+ BOOL bInvert = (BOOL) (dwFlags & OLEUI_HANDLES_USEINVERSE);
+
+ CopyRect((LPRECT)&rc, lpRect);
+
+ bkmodeOld = SetBkMode(hdc, TRANSPARENT);
+
+ if (dwFlags & OLEUI_HANDLES_OUTSIDE)
+ InflateRect((LPRECT)&rc, cSize - 1, cSize - 1);
+
+ // Draw the handles inside the rectangle boundary
+ DrawHandle(hdc, rc.left, rc.top, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.left, rc.top+(rc.bottom-rc.top-cSize)/2, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.left, rc.bottom-cSize, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.left+(rc.right-rc.left-cSize)/2, rc.top, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.left+(rc.right-rc.left-cSize)/2, rc.bottom-cSize, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.right-cSize, rc.top, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.right-cSize, rc.top+(rc.bottom-rc.top-cSize)/2, cSize, bInvert, fDraw);
+ DrawHandle(hdc, rc.right-cSize, rc.bottom-cSize, cSize, bInvert, fDraw);
+
+ if (!(dwFlags & OLEUI_HANDLES_NOBORDER)) {
+ if (fDraw)
+ hbr = GetStockObject(BLACK_BRUSH);
+ else
+ hbr = GetStockObject(WHITE_BRUSH);
+
+ FrameRect(hdc, lpRect, hbr);
+ }
+
+ SetBkMode(hdc, bkmodeOld);
+}
+
+
+
+/*
+ * DrawHandle
+ *
+ * Purpose:
+ * Draw a handle box at the specified coordinate
+ *
+ * Parameters:
+ * hdc HDC to be drawn into
+ * x, y upper left corner coordinate of the handle box
+ * cSize size of handle box
+ * bInvert use InvertRect() if TRUE, otherwise use Rectangle()
+ * fDraw Draw if TRUE, erase if FALSE, ignored if bInvert is TRUE
+ *
+ * Return Value: null
+ *
+ */
+static void DrawHandle(HDC hdc, int x, int y, UINT cSize, BOOL bInvert, BOOL fDraw)
+{
+ HBRUSH hbr;
+ HBRUSH hbrOld;
+ HPEN hpen;
+ HPEN hpenOld;
+ RECT rc;
+
+
+ if (!bInvert) {
+ if (fDraw) {
+ hpen = GetStockObject(BLACK_PEN);
+ hbr = GetStockObject(BLACK_BRUSH);
+ } else {
+ hpen = GetStockObject(WHITE_PEN);
+ hbr = GetStockObject(WHITE_PEN);
+ }
+
+ hpenOld = SelectObject(hdc, hpen);
+ hbrOld = SelectObject(hdc, hbr);
+ Rectangle(hdc, x, y, x+cSize, y+cSize);
+ SelectObject(hdc, hpenOld);
+ SelectObject(hdc, hbrOld);
+ }
+ else {
+ rc.left = x;
+ rc.top = y;
+ rc.right = x + cSize;
+ rc.bottom = y + cSize;
+ InvertRect(hdc, (LPRECT)&rc);
+ }
+}
+
+
+/*
+ * OleUIDrawShading
+ *
+ * Purpose:
+ * Shade the object when it is in in-place editing. Borders are drawn
+ * on the Object rectangle. The right and bottom edge of the rectangle
+ * are excluded in the drawing.
+ *
+ * Parameters:
+ * lpRect Dimensions of Container Object
+ * hdc HDC for drawing
+ * dwFlags-
+ * Exclusive flags
+ * OLEUI_SHADE_FULLRECT Shade the whole rectangle
+ * OLEUI_SHADE_BORDERIN Shade cWidth pixels inside rect
+ * OLEUI_SHADE_BORDEROUT Shade cWidth pixels outside rect
+ * Optional flags
+ * OLEUI_SHADE_USEINVERSE
+ * use PATINVERT instead of the hex value
+ * cWidth width of border in pixel
+ *
+ * Return Value: null
+ *
+ */
+STDAPI_(void) OleUIDrawShading(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cWidth)
+{
+ HBRUSH hbr;
+ HBRUSH hbrOld;
+ HBITMAP hbm;
+ RECT rc;
+ WORD wHatchBmp[] = {0x11, 0x22, 0x44, 0x88, 0x11, 0x22, 0x44, 0x88};
+ COLORREF cvText;
+ COLORREF cvBk;
+
+ hbm = CreateBitmap(8, 8, 1, 1, wHatchBmp);
+ hbr = CreatePatternBrush(hbm);
+ hbrOld = SelectObject(hdc, hbr);
+
+ rc = *lpRect;
+
+ if (dwFlags == OLEUI_SHADE_FULLRECT) {
+ cvText = SetTextColor(hdc, RGB(255, 255, 255));
+ cvBk = SetBkColor(hdc, RGB(0, 0, 0));
+ PatBlt(hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
+ 0x00A000C9L /* DPa */ );
+
+ } else { // either inside or outside rect
+
+ if (dwFlags == OLEUI_SHADE_BORDEROUT)
+ InflateRect((LPRECT)&rc, cWidth - 1, cWidth - 1);
+
+ cvText = SetTextColor(hdc, RGB(255, 255, 255));
+ cvBk = SetBkColor(hdc, RGB(0, 0, 0));
+ PatBlt(hdc, rc.left, rc.top, rc.right - rc.left,
+ cWidth, 0x00A000C9L /* DPa */);
+ PatBlt(hdc, rc.left, rc.top, cWidth, rc.bottom - rc.top,
+ 0x00A000C9L /* DPa */);
+ PatBlt(hdc, rc.right - cWidth, rc.top, cWidth,
+ rc.bottom - rc.top, 0x00A000C9L /* DPa */);
+ PatBlt(hdc, rc.left, rc.bottom - cWidth, rc.right-rc.left,
+ cWidth, 0x00A000C9L /* DPa */);
+ }
+
+ SetTextColor(hdc, cvText);
+ SetBkColor(hdc, cvBk);
+ SelectObject(hdc, hbrOld);
+ DeleteObject(hbr);
+ DeleteObject(hbm);
+}
+
+
+/*
+ * OleUIShowObject
+ *
+ * Purpose:
+ * Draw the ShowObject effect around the object
+ *
+ * Parameters:
+ * lprc rectangle for drawing
+ * hdc HDC for drawing
+ * fIsLink linked object (TRUE) or embedding object (FALSE)
+ *
+ * Return Value: null
+ *
+ */
+STDAPI_(void) OleUIShowObject(LPCRECT lprc, HDC hdc, BOOL fIsLink)
+{
+ HPEN hpen;
+ HPEN hpenOld;
+ HBRUSH hbrOld;
+
+ if (!lprc || !hdc)
+ return;
+
+ hpen = fIsLink ? CreatePen(PS_DASH, 1, RGB(0,0,0)) :
+ GetStockObject(BLACK_PEN);
+
+ if (!hpen)
+ return;
+
+ hpenOld = SelectObject(hdc, hpen);
+ hbrOld = SelectObject(hdc, GetStockObject(NULL_BRUSH));
+
+ Rectangle(hdc, lprc->left, lprc->top, lprc->right, lprc->bottom);
+
+ SelectObject(hdc, hpenOld);
+ SelectObject(hdc, hbrOld);
+
+ if (fIsLink)
+ DeleteObject(hpen);
+
+}
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;
+}
diff --git a/private/oleutest/letest/ole2ui/ole2ui.h b/private/oleutest/letest/ole2ui/ole2ui.h
new file mode 100644
index 000000000..9990c79e0
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/ole2ui.h
@@ -0,0 +1,958 @@
+/*
+ * OLE2UI.H
+ *
+ * Published definitions, structures, types, and function prototypes for the
+ * OLE 2.0 User Interface support library.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
+ */
+
+
+#ifndef _OLE2UI_H_
+#define _OLE2UI_H_
+
+#undef UNICODE
+#undef _UNICODE
+
+#if DBG == 1
+// Lazy way to avoid going through all the files and changing to the
+// new standard.
+#define _DEBUG 1
+#endif // DBG == 1
+
+#ifndef RC_INVOKED
+#pragma message ("Including OLE2UI.H from " __FILE__)
+#endif //RC_INVOKED
+
+// Macro to ensure strings to be UNICODEd in OLE
+#ifdef UNICODE
+ #define OLETEXT(quote) TEXT(quote)
+#else
+ #define OLETEXT(quote) L##quote
+#endif
+
+#if !defined(__cplusplus) && !defined( __TURBOC__)
+// #define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H)
+#endif
+
+#ifndef INC_OLE2
+ #define INC_OLE2
+#endif
+#include <windows.h>
+#include <shellapi.h>
+#include <ole2.h>
+#include <string.h>
+#include <dlgs.h> //For fileopen dlg; standard include
+#include "olestd.h"
+#include <olethunk.h>
+
+#ifdef __TURBOC__
+#define _getcwd getcwd
+#define _itoa itoa
+#define __max max
+#define _find_t find_t
+#endif // __TURBOC__
+
+#ifdef WIN32
+ #define _fmemset memset
+ #define _fmemcpy memcpy
+ #define _fmemcmp memcmp
+
+ #ifdef UNICODE
+ // UNICODE stuff
+ #define _fstrcpy wcscpy
+ #define _fstrlen wcslen
+ #define _fstrrchr wcschr
+ #define _fstrtok wcstok
+
+ #define _fstrchr wcscpy
+ #define _fstrcpy wcscpy
+
+ // BUGBUG32: isspace function does not seem to work properly
+ //
+ // XXXXX
+ // create a wide character image to match the ANSI isspace
+ #undef isspace
+ #undef iswspace
+ #define iswspace(j) (j==TEXT(' ') || j==TEXT('\t') || j==TEXT('\n'))
+ #define isspace(j) (j==' ' || j=='\t' || j=='\n')
+
+ #else
+ // Win32 doesn't support the following _fstrxxx functions
+ #define _fstrcpy strcpy
+ #define _fstrlen strlen
+ #define _fstrrchr strrchr
+ #define _fstrtok strtok
+
+ #define _fstrchr strchr
+ #define _fstrcpy strcpy
+
+ #endif // UNICODE
+
+#endif // WIN32
+
+#if !defined( EXPORT )
+#ifdef WIN32
+#define EXPORT
+#else
+#define EXPORT __export
+#endif // WIN32
+#endif // !EXPORT
+
+/*
+ * Initialization / Uninitialization routines. OleUIInitialize
+ * must be called prior to using any functions in OLE2UI, and OleUIUnInitialize
+ * must be called before you app shuts down and when you are done using the
+ * library.
+ *
+ * NOTE: If you are using the DLL version of this library, these functions
+ * are automatically called in the DLL's LibMain and WEP, so you should
+ * not call them directly from your application.
+ */
+
+// Backward compatibility with older library
+#define OleUIUninitialize OleUIUnInitialize
+
+STDAPI_(BOOL) OleUIInitialize(HINSTANCE hInstance,
+ HINSTANCE hPrevInst,
+ LPTSTR lpszClassIconBox,
+ LPTSTR lpszClassResImage);
+STDAPI_(BOOL) OleUIUninitialize(void);
+
+//Dialog Identifiers as passed in Help messages to identify the source.
+#define IDD_INSERTOBJECT 1000
+#define IDD_CHANGEICON 1001
+#define IDD_CONVERT 1002
+#define IDD_PASTESPECIAL 1003
+#define IDD_EDITLINKS 1004
+#define IDD_FILEOPEN 1005
+#define IDD_BUSY 1006
+#define IDD_UPDATELINKS 1007
+#define IDD_CANNOTUPDATELINK 1008
+#define IDD_CHANGESOURCE 1009
+#define IDD_INSERTFILEBROWSE 1010
+#define IDD_CHANGEICONBROWSE 1011
+
+// The following Dialogs are message dialogs used by OleUIPromptUser API
+#define IDD_LINKSOURCEUNAVAILABLE 1020
+#define IDD_SERVERNOTREG 1021
+#define IDD_LINKTYPECHANGED 1022
+#define IDD_SERVERNOTFOUND 1023
+#define IDD_OUTOFMEMORY 1024
+
+// Stringtable identifers
+#define IDS_OLE2UIUNKNOWN 300
+#define IDS_OLE2UILINK 301
+#define IDS_OLE2UIOBJECT 302
+#define IDS_OLE2UIEDIT 303
+#define IDS_OLE2UICONVERT 304
+#define IDS_OLE2UIEDITLINKCMD_1VERB 305
+#define IDS_OLE2UIEDITOBJECTCMD_1VERB 306
+#define IDS_OLE2UIEDITLINKCMD_NVERB 307
+#define IDS_OLE2UIEDITOBJECTCMD_NVERB 308
+#define IDS_OLE2UIEDITNOOBJCMD 309
+// def. icon label (usu. "Document")
+#define IDS_DEFICONLABEL 310
+#define IDS_OLE2UIPASTELINKEDTYPE 311
+
+
+#define IDS_FILTERS 64
+#define IDS_ICONFILTERS 65
+#define IDS_BROWSE 66
+
+//Resource identifiers for bitmaps
+#define IDB_RESULTSEGA 10
+#define IDB_RESULTSVGA 11
+#define IDB_RESULTSHIRESVGA 12
+
+
+//Missing from windows.h
+#ifndef PVOID
+typedef VOID *PVOID;
+#endif
+
+
+//Hook type used in all structures.
+typedef UINT (CALLBACK *LPFNOLEUIHOOK)(HWND, UINT, WPARAM, LPARAM);
+
+
+//Strings for registered messages
+#define SZOLEUI_MSG_HELP TEXT("OLEUI_MSG_HELP")
+#define SZOLEUI_MSG_ENDDIALOG TEXT("OLEUI_MSG_ENDDIALOG")
+#define SZOLEUI_MSG_BROWSE TEXT("OLEUI_MSG_BROWSE")
+#define SZOLEUI_MSG_CHANGEICON TEXT("OLEUI_MSG_CHANGEICON")
+#define SZOLEUI_MSG_CLOSEBUSYDIALOG TEXT("OLEUI_MSG_CLOSEBUSYDIALOG")
+#define SZOLEUI_MSG_FILEOKSTRING TEXT("OLEUI_MSG_FILEOKSTRING")
+
+//Standard error definitions
+#define OLEUI_FALSE 0
+#define OLEUI_SUCCESS 1 //No error, same as OLEUI_OK
+#define OLEUI_OK 1 //OK button pressed
+#define OLEUI_CANCEL 2 //Cancel button pressed
+
+#define OLEUI_ERR_STANDARDMIN 100
+#define OLEUI_ERR_STRUCTURENULL 101 //Standard field validation
+#define OLEUI_ERR_STRUCTUREINVALID 102
+#define OLEUI_ERR_CBSTRUCTINCORRECT 103
+#define OLEUI_ERR_HWNDOWNERINVALID 104
+#define OLEUI_ERR_LPSZCAPTIONINVALID 105
+#define OLEUI_ERR_LPFNHOOKINVALID 106
+#define OLEUI_ERR_HINSTANCEINVALID 107
+#define OLEUI_ERR_LPSZTEMPLATEINVALID 108
+#define OLEUI_ERR_HRESOURCEINVALID 109
+
+#define OLEUI_ERR_FINDTEMPLATEFAILURE 110 //Initialization errors
+#define OLEUI_ERR_LOADTEMPLATEFAILURE 111
+#define OLEUI_ERR_DIALOGFAILURE 112
+#define OLEUI_ERR_LOCALMEMALLOC 113
+#define OLEUI_ERR_GLOBALMEMALLOC 114
+#define OLEUI_ERR_LOADSTRING 115
+
+#define OLEUI_ERR_STANDARDMAX 116 //Start here for specific errors.
+
+
+
+//Help Button Identifier
+#define ID_OLEUIHELP 99
+
+// Help button for fileopen.dlg (need this for resizing) 1038 is pshHelp
+#undef IDHELP
+#define IDHELP 1038
+
+// Static text control (use this instead of -1 so things work correctly for
+// localization
+#define ID_STATIC 98
+
+/******************
+ * The followings are defined in the fashion that the first
+ * definition is the number of CHARACTERS, while the second one (XXX_SIZE)
+ * is the number of bytes. The number of bytes definition is needed for
+ * UNICODE handling purpose.
+ * Also, please note the prefix of variables cch means that it is the
+ * count of characters and cb means the count of bytes.
+ ******************/
+
+//Maximum key size we read from the RegDB.
+#define OLEUI_CCHKEYMAX 256 // make any changes to this in geticon.c too
+#define OLEUI_CCHKEYMAX_SIZE OLEUI_CCHKEYMAX*sizeof(TCHAR) // # of bytes
+
+//Maximum verb length and length of Object menu
+#define OLEUI_CCHVERBMAX 32
+#define OLEUI_CCHVERBMAX_SIZE OLEUI_CCHVERBMAX*sizeof(TCHAR) // # of bytes
+#define OLEUI_OBJECTMENUMAX 256
+#define OLEUI_OBJECTMENUMAX_SIZE OLEUI_OBJECTMENUMAX*sizeof(TCHAR) // # of bytes
+
+//Maximum MS-DOS pathname.
+#define OLEUI_CCHPATHMAX 256 // make any changes to this in geticon.c too
+#define OLEUI_CCHPATHMAX_SIZE OLEUI_CCHPATHMAX*sizeof(TCHAR) // # of bytes
+#define OLEUI_CCHFILEMAX 13
+#define OLEUI_CCHFILEMAX_SIZE OLEUI_CCHFILEMAX*sizeof(TCHAR) // # of bytes
+
+//Icon label length
+#define OLEUI_CCHLABELMAX 40 // make any changes to this in geticon.c too
+#define OLEUI_CCHLABELMAX_SIZE OLEUI_CCHLABELMAX*sizeof(TCHAR) // # of bytes
+
+//Length of the CLSID string
+#define OLEUI_CCHCLSIDSTRING 39
+#define OLEUI_CCHCLSIDSTRING_SIZE OLEUI_CCHCLSIDSTRING*sizeof(TCHAR) // # of bytes
+
+
+/*
+ * What follows here are first function prototypes for general utility
+ * functions, then sections laid out by dialog. Each dialog section
+ * defines the dialog structure, the API prototype, flags for the dwFlags
+ * field, the dialog-specific error values, and dialog control IDs (for
+ * hooks and custom templates.
+ */
+
+
+//Miscellaneous utility functions.
+STDAPI_(BOOL) OleUIAddVerbMenu(LPOLEOBJECT lpOleObj,
+ LPTSTR lpszShortType,
+ HMENU hMenu,
+ UINT uPos,
+ UINT uIDVerbMin,
+ UINT uIDVerbMax,
+ BOOL bAddConvert,
+ UINT idConvert,
+ HMENU FAR *lphMenu);
+
+//Metafile utility functions
+#ifndef WIN32
+STDAPI_(HGLOBAL) OleUIMetafilePictFromIconAndLabel(HICON, LPTSTR, LPTSTR, UINT);
+#endif
+STDAPI_(void) OleUIMetafilePictIconFree(HGLOBAL);
+STDAPI_(BOOL) OleUIMetafilePictIconDraw(HDC, LPRECT, HGLOBAL, BOOL);
+STDAPI_(UINT) OleUIMetafilePictExtractLabel(HGLOBAL, LPTSTR, UINT, LPDWORD);
+STDAPI_(HICON) OleUIMetafilePictExtractIcon(HGLOBAL);
+STDAPI_(BOOL) OleUIMetafilePictExtractIconSource(HGLOBAL,LPTSTR,UINT FAR *);
+
+
+
+
+
+/*************************************************************************
+** INSERT OBJECT DIALOG
+*************************************************************************/
+
+
+typedef struct tagOLEUIINSERTOBJECT
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIINSERTOBJECT. All are IN-OUT unless otherwise spec.
+ CLSID clsid; //Return space for class ID
+ LPTSTR lpszFile; //Filename for inserts or links
+ UINT cchFile; //Size of lpszFile buffer: OLEUI_CCHPATHMAX
+ UINT cClsidExclude; //IN only: CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //List of CLSIDs to exclude from listing.
+
+ //Specific to create objects if flags say so
+ IID iid; //Requested interface on creation.
+ DWORD oleRender; //Rendering option
+ LPFORMATETC lpFormatEtc; //Desired format
+ LPOLECLIENTSITE lpIOleClientSite; //Site to be use for the object.
+ LPSTORAGE lpIStorage; //Storage used for the object
+ LPVOID FAR *ppvObj; //Where the object is returned.
+ SCODE sc; //Result of creation calls.
+ HGLOBAL hMetaPict; //OUT: METAFILEPICT containing iconic aspect.
+ //IFF we couldn't stuff it in the cache.
+ } OLEUIINSERTOBJECT, *POLEUIINSERTOBJECT, FAR *LPOLEUIINSERTOBJECT;
+
+//API prototype
+STDAPI_(UINT) OleUIInsertObject(LPOLEUIINSERTOBJECT);
+
+
+//Insert Object flags
+#define IOF_SHOWHELP 0x00000001L
+#define IOF_SELECTCREATENEW 0x00000002L
+#define IOF_SELECTCREATEFROMFILE 0x00000004L
+#define IOF_CHECKLINK 0x00000008L
+#define IOF_CHECKDISPLAYASICON 0x00000010L
+#define IOF_CREATENEWOBJECT 0x00000020L
+#define IOF_CREATEFILEOBJECT 0x00000040L
+#define IOF_CREATELINKOBJECT 0x00000080L
+#define IOF_DISABLELINK 0x00000100L
+#define IOF_VERIFYSERVERSEXIST 0x00000200L
+#define IOF_DISABLEDISPLAYASICON 0x00000400L
+
+
+//Insert Object specific error codes
+#define OLEUI_IOERR_LPSZFILEINVALID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_IOERR_LPSZLABELINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_IOERR_HICONINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_IOERR_LPFORMATETCINVALID (OLEUI_ERR_STANDARDMAX+3)
+#define OLEUI_IOERR_PPVOBJINVALID (OLEUI_ERR_STANDARDMAX+4)
+#define OLEUI_IOERR_LPIOLECLIENTSITEINVALID (OLEUI_ERR_STANDARDMAX+5)
+#define OLEUI_IOERR_LPISTORAGEINVALID (OLEUI_ERR_STANDARDMAX+6)
+#define OLEUI_IOERR_SCODEHASERROR (OLEUI_ERR_STANDARDMAX+7)
+#define OLEUI_IOERR_LPCLSIDEXCLUDEINVALID (OLEUI_ERR_STANDARDMAX+8)
+#define OLEUI_IOERR_CCHFILEINVALID (OLEUI_ERR_STANDARDMAX+9)
+
+
+//Insert Object Dialog identifiers
+#define ID_IO_CREATENEW 2100
+#define ID_IO_CREATEFROMFILE 2101
+#define ID_IO_LINKFILE 2102
+#define ID_IO_OBJECTTYPELIST 2103
+#define ID_IO_DISPLAYASICON 2104
+#define ID_IO_CHANGEICON 2105
+#define ID_IO_FILE 2106
+#define ID_IO_FILEDISPLAY 2107
+#define ID_IO_RESULTIMAGE 2108
+#define ID_IO_RESULTTEXT 2109
+#define ID_IO_ICONDISPLAY 2110
+#define ID_IO_OBJECTTYPETEXT 2111
+#define ID_IO_FILETEXT 2112
+#define ID_IO_FILETYPE 2113
+
+// Strings in OLE2UI resources
+#define IDS_IORESULTNEW 256
+#define IDS_IORESULTNEWICON 257
+#define IDS_IORESULTFROMFILE1 258
+#define IDS_IORESULTFROMFILE2 259
+#define IDS_IORESULTFROMFILEICON2 260
+#define IDS_IORESULTLINKFILE1 261
+#define IDS_IORESULTLINKFILE2 262
+#define IDS_IORESULTLINKFILEICON1 263
+#define IDS_IORESULTLINKFILEICON2 264
+
+/*************************************************************************
+** PASTE SPECIAL DIALOG
+*************************************************************************/
+
+// Maximum number of link types
+#define PS_MAXLINKTYPES 8
+
+//NOTE: OLEUIPASTEENTRY and OLEUIPASTEFLAG structs are defined in OLESTD.H
+
+typedef struct tagOLEUIPASTESPECIAL
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIPASTESPECIAL.
+
+ //IN fields
+ LPDATAOBJECT lpSrcDataObj; //Source IDataObject* (on the
+ // clipboard) for data to paste
+
+ LPOLEUIPASTEENTRY arrPasteEntries; //OLEUIPASTEENTRY array which
+ // specifies acceptable formats. See
+ // OLEUIPASTEENTRY for more info.
+ int cPasteEntries; //No. of OLEUIPASTEENTRY array entries
+
+ UINT FAR *arrLinkTypes; //List of link types that are
+ // acceptable. Link types are referred
+ // to using OLEUIPASTEFLAGS in
+ // arrPasteEntries
+ int cLinkTypes; //Number of link types
+ UINT cClsidExclude; //Number of CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //List of CLSIDs to exclude from list.
+
+ //OUT fields
+ int nSelectedIndex; //Index of arrPasteEntries[] that the
+ // user selected
+ BOOL fLink; //Indicates if Paste or Paste Link was
+ // selected by the user
+ HGLOBAL hMetaPict; //Handle to Metafile containing icon
+ // and icon title selected by the user
+ // Use the Metafile utility functions
+ // defined in this header to
+ // manipulate hMetaPict
+ SIZEL sizel; // size of object/link in its source
+ // if the display aspect chosen by
+ // the user matches the aspect
+ // displayed in the source. if
+ // different aspect is chosen then
+ // sizel.cx=sizel.cy=0 is returned.
+ // sizel displayed in source is
+ // retrieved from the
+ // ObjectDescriptor if fLink is FALSE
+ // LinkSrcDescriptor if fLink is TRUE
+ } OLEUIPASTESPECIAL, *POLEUIPASTESPECIAL, FAR *LPOLEUIPASTESPECIAL;
+
+
+//API to bring up PasteSpecial dialog
+STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL);
+
+
+//Paste Special flags
+// Show Help button. IN flag.
+#define PSF_SHOWHELP 0x00000001L
+
+//Select Paste radio button at dialog startup. This is the default if
+// PSF_SELECTPASTE or PSF_SELECTPASTELINK are not specified. Also specifies
+// state of button on dialog termination. IN/OUT flag.
+#define PSF_SELECTPASTE 0x00000002L
+
+//Select PasteLink radio button at dialog startup. Also specifies state of
+// button on dialog termination. IN/OUT flag.
+#define PSF_SELECTPASTELINK 0x00000004L
+
+//Specfies if DisplayAsIcon button was checked on dialog termination. OUT flag
+#define PSF_CHECKDISPLAYASICON 0x00000008L
+#define PSF_DISABLEDISPLAYASICON 0x00000010L
+
+
+//Paste Special specific error codes
+#define OLEUI_IOERR_SRCDATAOBJECTINVALID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_IOERR_ARRPASTEENTRIESINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_IOERR_ARRLINKTYPESINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_PSERR_CLIPBOARDCHANGED (OLEUI_ERR_STANDARDMAX+3)
+
+//Paste Special Dialog identifiers
+#define ID_PS_PASTE 500
+#define ID_PS_PASTELINK 501
+#define ID_PS_SOURCETEXT 502
+#define ID_PS_PASTELIST 503
+#define ID_PS_PASTELINKLIST 504
+#define ID_PS_DISPLAYLIST 505
+#define ID_PS_DISPLAYASICON 506
+#define ID_PS_ICONDISPLAY 507
+#define ID_PS_CHANGEICON 508
+#define ID_PS_RESULTIMAGE 509
+#define ID_PS_RESULTTEXT 510
+#define ID_PS_RESULTGROUP 511
+#define ID_PS_STXSOURCE 512
+#define ID_PS_STXAS 513
+
+// Paste Special String IDs
+#define IDS_PSPASTEDATA 400
+#define IDS_PSPASTEOBJECT 401
+#define IDS_PSPASTEOBJECTASICON 402
+#define IDS_PSPASTELINKDATA 403
+#define IDS_PSPASTELINKOBJECT 404
+#define IDS_PSPASTELINKOBJECTASICON 405
+#define IDS_PSNONOLE 406
+#define IDS_PSUNKNOWNTYPE 407
+#define IDS_PSUNKNOWNSRC 408
+#define IDS_PSUNKNOWNAPP 409
+
+
+/*************************************************************************
+** EDIT LINKS DIALOG
+*************************************************************************/
+
+
+
+/* IOleUILinkContainer Interface
+** -----------------------------
+** This interface must be implemented by container applications that
+** want to use the EditLinks dialog. the EditLinks dialog calls back
+** to the container app to perform the OLE functions to manipulate
+** the links within the container.
+*/
+
+#define LPOLEUILINKCONTAINER IOleUILinkContainer FAR*
+
+#undef INTERFACE
+#define INTERFACE IOleUILinkContainer
+
+DECLARE_INTERFACE_(IOleUILinkContainer, IUnknown)
+{
+ //*** IUnknown methods ***/
+ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
+ STDMETHOD_(ULONG,AddRef) (THIS) PURE;
+ STDMETHOD_(ULONG,Release) (THIS) PURE;
+
+ STDMETHOD_(DWORD,GetNextLink) (THIS_ DWORD dwLink) PURE;
+ STDMETHOD(SetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD dwUpdateOpt) PURE;
+ STDMETHOD(GetLinkUpdateOptions) (THIS_ DWORD dwLink, DWORD FAR* lpdwUpdateOpt) PURE;
+ STDMETHOD(SetLinkSource) (THIS_
+ DWORD dwLink,
+ LPTSTR lpszDisplayName,
+ ULONG lenFileName,
+ ULONG FAR* pchEaten,
+ BOOL fValidateSource) PURE;
+ STDMETHOD(GetLinkSource) (THIS_
+ DWORD dwLink,
+ LPTSTR FAR* lplpszDisplayName,
+ ULONG FAR* lplenFileName,
+ LPTSTR FAR* lplpszFullLinkType,
+ LPTSTR FAR* lplpszShortLinkType,
+ BOOL FAR* lpfSourceAvailable,
+ BOOL FAR* lpfIsSelected) PURE;
+ STDMETHOD(OpenLinkSource) (THIS_ DWORD dwLink) PURE;
+ STDMETHOD(UpdateLink) (THIS_
+ DWORD dwLink,
+ BOOL fErrorMessage,
+ BOOL fErrorAction) PURE;
+ STDMETHOD(CancelLink) (THIS_ DWORD dwLink) PURE;
+};
+
+
+typedef struct tagOLEUIEDITLINKS
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUI<STRUCT>. All are IN-OUT unless otherwise spec.
+
+ LPOLEUILINKCONTAINER lpOleUILinkContainer; //IN: Interface to manipulate
+ //links in the container
+ } OLEUIEDITLINKS, *POLEUIEDITLINKS, FAR *LPOLEUIEDITLINKS;
+
+
+//API Prototype
+STDAPI_(UINT) OleUIEditLinks(LPOLEUIEDITLINKS);
+
+
+// Edit Links flags
+#define ELF_SHOWHELP 0x00000001L
+#define ELF_DISABLEUPDATENOW 0x00000002L
+#define ELF_DISABLEOPENSOURCE 0x00000004L
+#define ELF_DISABLECHANGESOURCE 0x00000008L
+#define ELF_DISABLECANCELLINK 0x00000010L
+
+// Edit Links Dialog identifiers
+#define ID_EL_CHANGESOURCE 201
+#define ID_EL_AUTOMATIC 202
+#define ID_EL_CLOSE 208
+#define ID_EL_CANCELLINK 209
+#define ID_EL_UPDATENOW 210
+#define ID_EL_OPENSOURCE 211
+#define ID_EL_MANUAL 212
+#define ID_EL_LINKSOURCE 216
+#define ID_EL_LINKTYPE 217
+#define ID_EL_UPDATE 218
+#define ID_EL_NULL -1
+#define ID_EL_LINKSLISTBOX 206
+#define ID_EL_COL1 220
+#define ID_EL_COL2 221
+#define ID_EL_COL3 222
+
+
+
+/*************************************************************************
+** CHANGE ICON DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUICHANGEICON
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUICHANGEICON. All are IN-OUT unless otherwise spec.
+ HGLOBAL hMetaPict; //Current and final image. Source of the
+ //icon is embedded in the metafile itself.
+ CLSID clsid; //IN only: class used to get Default icon
+ TCHAR szIconExe[OLEUI_CCHPATHMAX];
+ int cchIconExe;
+ } OLEUICHANGEICON, *POLEUICHANGEICON, FAR *LPOLEUICHANGEICON;
+
+
+//API prototype
+STDAPI_(UINT) OleUIChangeIcon(LPOLEUICHANGEICON);
+
+
+//Change Icon flags
+#define CIF_SHOWHELP 0x00000001L
+#define CIF_SELECTCURRENT 0x00000002L
+#define CIF_SELECTDEFAULT 0x00000004L
+#define CIF_SELECTFROMFILE 0x00000008L
+#define CIF_USEICONEXE 0x0000000aL
+
+
+//Change Icon specific error codes
+#define OLEUI_CIERR_MUSTHAVECLSID (OLEUI_ERR_STANDARDMAX+0)
+#define OLEUI_CIERR_MUSTHAVECURRENTMETAFILE (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_CIERR_SZICONEXEINVALID (OLEUI_ERR_STANDARDMAX+2)
+
+
+//Change Icon Dialog identifiers
+#define ID_GROUP 120
+#define ID_CURRENT 121
+#define ID_CURRENTICON 122
+#define ID_DEFAULT 123
+#define ID_DEFAULTICON 124
+#define ID_FROMFILE 125
+#define ID_FROMFILEEDIT 126
+#define ID_ICONLIST 127
+#define ID_LABEL 128
+#define ID_LABELEDIT 129
+#define ID_BROWSE 130
+#define ID_RESULTICON 132
+#define ID_RESULTLABEL 133
+
+// Stringtable defines for Change Icon
+#define IDS_CINOICONSINFILE 288
+#define IDS_CIINVALIDFILE 289
+#define IDS_CIFILEACCESS 290
+#define IDS_CIFILESHARE 291
+#define IDS_CIFILEOPENFAIL 292
+
+
+
+/*************************************************************************
+** CONVERT DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUICONVERT
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUICONVERT. All are IN-OUT unless otherwise spec.
+ CLSID clsid; //Class ID sent in to dialog: IN only
+ CLSID clsidConvertDefault; //Class ID to use as convert default: IN only
+ CLSID clsidActivateDefault; //Class ID to use as activate default: IN only
+
+ CLSID clsidNew; //Selected Class ID: OUT only
+ DWORD dvAspect; //IN-OUT, either DVASPECT_CONTENT or
+ //DVASPECT_ICON
+ WORD wFormat; //Original data format
+ BOOL fIsLinkedObject; //IN only; true if object is linked
+ HGLOBAL hMetaPict; //IN-OUT: METAFILEPICT containing iconic aspect.
+ LPTSTR lpszUserType; //IN-OUT: user type name of original class.
+ // We'll do lookup if it's NULL.
+ // This gets freed on exit.
+ BOOL fObjectsIconChanged; // OUT; TRUE if ChangeIcon was called (and not cancelled)
+ LPTSTR lpszDefLabel; //IN-OUT: default label to use for icon.
+ // if NULL, the short user type name
+ // will be used. if the object is a
+ // link, the caller should pass the
+ // DisplayName of the link source
+ // This gets freed on exit.
+
+ UINT cClsidExclude; //IN: No. of CLSIDs in lpClsidExclude
+ LPCLSID lpClsidExclude; //IN: List of CLSIDs to exclude from list
+ } OLEUICONVERT, *POLEUICONVERT, FAR *LPOLEUICONVERT;
+
+
+//API prototype
+STDAPI_(UINT) OleUIConvert(LPOLEUICONVERT);
+
+// Determine if there is at least one class that can Convert or ActivateAs
+// the given clsid.
+STDAPI_(BOOL) OleUICanConvertOrActivateAs(
+ REFCLSID rClsid,
+ BOOL fIsLinkedObject,
+ WORD wFormat
+);
+
+//Convert Dialog flags
+
+// IN only: Shows "HELP" button
+#define CF_SHOWHELPBUTTON 0x00000001L
+
+// IN only: lets you set the convert default object - the one that is
+// selected as default in the convert listbox.
+#define CF_SETCONVERTDEFAULT 0x00000002L
+
+
+// IN only: lets you set the activate default object - the one that is
+// selected as default in the activate listbox.
+
+#define CF_SETACTIVATEDEFAULT 0x00000004L
+
+
+// IN/OUT: Selects the "Convert To" radio button, is set on exit if
+// this button was selected
+#define CF_SELECTCONVERTTO 0x00000008L
+
+// IN/OUT: Selects the "Activate As" radio button, is set on exit if
+// this button was selected
+#define CF_SELECTACTIVATEAS 0x00000010L
+#define CF_DISABLEDISPLAYASICON 0x00000020L
+#define CF_DISABLEACTIVATEAS 0x00000040L
+
+
+//Convert specific error codes
+#define OLEUI_CTERR_CLASSIDINVALID (OLEUI_ERR_STANDARDMAX+1)
+#define OLEUI_CTERR_DVASPECTINVALID (OLEUI_ERR_STANDARDMAX+2)
+#define OLEUI_CTERR_CBFORMATINVALID (OLEUI_ERR_STANDARDMAX+3)
+#define OLEUI_CTERR_HMETAPICTINVALID (OLEUI_ERR_STANDARDMAX+4)
+#define OLEUI_CTERR_STRINGINVALID (OLEUI_ERR_STANDARDMAX+5)
+
+
+//Convert Dialog identifiers
+#define IDCV_OBJECTTYPE 150
+#define IDCV_DISPLAYASICON 152
+#define IDCV_CHANGEICON 153
+#define IDCV_ACTIVATELIST 154
+#define IDCV_CONVERTTO 155
+#define IDCV_ACTIVATEAS 156
+#define IDCV_RESULTTEXT 157
+#define IDCV_CONVERTLIST 158
+#define IDCV_ICON 159
+#define IDCV_ICONLABEL1 160
+#define IDCV_ICONLABEL2 161
+#define IDCV_STXCURTYPE 162
+#define IDCV_GRPRESULT 163
+#define IDCV_STXCONVERTTO 164
+
+// String IDs for Convert dialog
+#define IDS_CVRESULTCONVERTLINK 500
+#define IDS_CVRESULTCONVERTTO 501
+#define IDS_CVRESULTNOCHANGE 502
+#define IDS_CVRESULTDISPLAYASICON 503
+#define IDS_CVRESULTACTIVATEAS 504
+#define IDS_CVRESULTACTIVATEDIFF 505
+
+
+/*************************************************************************
+** BUSY DIALOG
+*************************************************************************/
+
+typedef struct tagOLEUIBUSY
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags ** NOTE ** this dialog has no flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUIBUSY.
+ HTASK hTask; //IN: HTask which is blocking
+ HWND FAR * lphWndDialog; //IN: Dialog's HWND is placed here
+ } OLEUIBUSY, *POLEUIBUSY, FAR *LPOLEUIBUSY;
+
+//API prototype
+STDAPI_(UINT) OleUIBusy(LPOLEUIBUSY);
+
+// Flags for this dialog
+
+// IN only: Disables "Cancel" button
+#define BZ_DISABLECANCELBUTTON 0x00000001L
+
+// IN only: Disables "Switch To..." button
+#define BZ_DISABLESWITCHTOBUTTON 0x00000002L
+
+// IN only: Disables "Retry" button
+#define BZ_DISABLERETRYBUTTON 0x00000004L
+
+// IN only: Generates a "Not Responding" dialog as opposed to the
+// "Busy" dialog. The wording in the text is slightly different, and
+// the "Cancel" button is grayed out if you set this flag.
+#define BZ_NOTRESPONDINGDIALOG 0x00000008L
+
+// Busy specific error/return codes
+#define OLEUI_BZERR_HTASKINVALID (OLEUI_ERR_STANDARDMAX+0)
+
+// SWITCHTOSELECTED is returned when user hit "switch to"
+#define OLEUI_BZ_SWITCHTOSELECTED (OLEUI_ERR_STANDARDMAX+1)
+
+// RETRYSELECTED is returned when user hit "retry"
+#define OLEUI_BZ_RETRYSELECTED (OLEUI_ERR_STANDARDMAX+2)
+
+// CALLUNBLOCKED is returned when call has been unblocked
+#define OLEUI_BZ_CALLUNBLOCKED (OLEUI_ERR_STANDARDMAX+3)
+
+// Busy dialog identifiers
+#define IDBZ_RETRY 600
+#define IDBZ_ICON 601
+#define IDBZ_MESSAGE1 602
+#define IDBZ_SWITCHTO 604
+
+// Busy dialog stringtable defines
+#define IDS_BZRESULTTEXTBUSY 601
+#define IDS_BZRESULTTEXTNOTRESPONDING 602
+
+// Links dialog stringtable defines
+#define IDS_LINK_AUTO 800
+#define IDS_LINK_MANUAL 801
+#define IDS_LINK_UNKNOWN 802
+#define IDS_LINKS 803
+#define IDS_FAILED 804
+#define IDS_CHANGESOURCE 805
+#define IDS_INVALIDSOURCE 806
+#define IDS_ERR_GETLINKSOURCE 807
+#define IDS_ERR_GETLINKUPDATEOPTIONS 808
+#define IDS_ERR_ADDSTRING 809
+#define IDS_CHANGEADDITIONALLINKS 810
+#define IDS_CLOSE 811
+
+
+/*************************************************************************
+** PROMPT USER DIALOGS
+*************************************************************************/
+#define ID_PU_LINKS 900
+#define ID_PU_TEXT 901
+#define ID_PU_CONVERT 902
+#define ID_PU_BROWSE 904
+#define ID_PU_METER 905
+#define ID_PU_PERCENT 906
+#define ID_PU_STOP 907
+
+// used for -1 ids in dialogs:
+#define ID_DUMMY 999
+
+/* inside ole2ui.c */
+#ifdef __cplusplus
+extern "C"
+#endif
+int EXPORT FAR CDECL OleUIPromptUser(int nTemplate, HWND hwndParent, ...);
+
+#define UPDATELINKS_STARTDELAY 2000 // Delay before 1st link updates
+ // to give the user a chance to
+ // dismiss the dialog before any
+ // links update.
+
+STDAPI_(BOOL) OleUIUpdateLinks(
+ LPOLEUILINKCONTAINER lpOleUILinkCntr,
+ HWND hwndParent,
+ LPTSTR lpszTitle,
+ int cLinks);
+
+
+/*************************************************************************
+** OLE OBJECT FEEDBACK EFFECTS
+*************************************************************************/
+
+#define OLEUI_HANDLES_USEINVERSE 0x00000001L
+#define OLEUI_HANDLES_NOBORDER 0x00000002L
+#define OLEUI_HANDLES_INSIDE 0x00000004L
+#define OLEUI_HANDLES_OUTSIDE 0x00000008L
+
+
+#define OLEUI_SHADE_FULLRECT 1
+#define OLEUI_SHADE_BORDERIN 2
+#define OLEUI_SHADE_BORDEROUT 3
+
+/* objfdbk.c function prototypes */
+STDAPI_(void) OleUIDrawHandles(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cSize, BOOL fDraw);
+STDAPI_(void) OleUIDrawShading(LPRECT lpRect, HDC hdc, DWORD dwFlags, UINT cWidth);
+STDAPI_(void) OleUIShowObject(LPCRECT lprc, HDC hdc, BOOL fIsLink);
+
+
+/*************************************************************************
+** Hatch window definitions and prototypes **
+*************************************************************************/
+#define DEFAULT_HATCHBORDER_WIDTH 4
+
+STDAPI_(BOOL) RegisterHatchWindowClass(HINSTANCE hInst);
+STDAPI_(HWND) CreateHatchWindow(HWND hWndParent, HINSTANCE hInst);
+STDAPI_(UINT) GetHatchWidth(HWND hWndHatch);
+STDAPI_(void) GetHatchRect(HWND hWndHatch, LPRECT lpHatchRect);
+STDAPI_(void) SetHatchRect(HWND hWndHatch, LPRECT lprcHatchRect);
+STDAPI_(void) SetHatchWindowSize(
+ HWND hWndHatch,
+ LPRECT lprcIPObjRect,
+ LPRECT lprcClipRect,
+ LPPOINT lpptOffset
+);
+
+
+
+/*************************************************************************
+** VERSION VERIFICATION INFORMATION
+*************************************************************************/
+
+// The following magic number is used to verify that the resources we bind
+// to our EXE are the same "version" as the LIB (or DLL) file which
+// contains these routines. This is not the same as the Version information
+// resource that we place in OLE2UI.RC, this is a special ID that we will
+// have compiled in to our EXE. Upon initialization of OLE2UI, we will
+// look in our resources for an RCDATA called "VERIFICATION" (see OLE2UI.RC),
+// and make sure that the magic number there equals the magic number below.
+
+#define OLEUI_VERSION_MAGIC 0x4D42
+
+#endif //_OLE2UI_H_
diff --git a/private/oleutest/letest/ole2ui/ole2ui.mak b/private/oleutest/letest/ole2ui/ole2ui.mak
new file mode 100644
index 000000000..f8308fa23
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/ole2ui.mak
@@ -0,0 +1,272 @@
+# ============================================================================
+# File: OLE2UI.MAK
+#
+# NMAKE description file to build STATIC version of OLE2.0 User Interface LIB
+#
+# Copyright (C) Microsoft Corporation, 1992-1993. All Rights Reserved.
+# ============================================================================
+#
+# Usage Notes:
+# -----------
+#
+# This makefile is designed to be used in one step. This makefile does
+# NOT use the file called UIMAKE.INI. This makefile builds the OLE2UI.LIB
+# library. It is NOT necessary to build custom versions of the static
+# library version of OLE2UI. Everyone can use the same OLE2UI.LIB library
+# as built by this makefile.
+#
+# NMAKE -F OLE2UI.MAK
+#
+#
+# The following lists a few of the settings in this makefile file which
+# you might change, and what effect those changes might have. For a
+# complete listing of all the available options and how they are used,
+# see the makefile below.
+#
+# MODEL=[S|M|C|L] -- The memory model.
+#
+# ============================================================================
+
+
+# ----------------------------------------------------------------------------
+# U I M A K E . I N I
+# ----------------------------------------------------------------------------
+DOS=1
+
+# Make a static library called OLE2UI.LIB
+DEBUG=0
+MODEL=M
+RESOURCE=RESOURCE
+
+!ifndef REL_DIR
+REL_DIR=c:\ole2samp\release
+!endif
+!ifndef OLERELDIR
+OLEREL_DIR=c:\ole2samp\release
+!endif
+
+!if "$(INSTALL_DIR)"==""
+INSTALL_DIR = $(REL_DIR)
+!endif
+
+# ----------------------------------------------------------------------------
+# O B J E C T F I L E L I S T
+# ----------------------------------------------------------------------------
+
+UI_COBJS = \
+ D^\busy.obj\
+ D^\common.obj\
+ D^\convert.obj\
+ D^\dbgutil.obj\
+ D^\drawicon.obj\
+ D^\hatch.obj\
+ D^\icon.obj\
+ D^\iconbox.obj\
+ D^\insobj.obj\
+ D^\links.obj\
+ D^\msgfiltr.obj\
+ D^\enumfetc.obj\
+ D^\enumstat.obj\
+ D^\objfdbk.obj\
+ D^\ole2ui.obj\
+ D^\olestd.obj\
+ D^\targtdev.obj\
+ D^\oleutl.obj\
+ D^\pastespl.obj\
+ D^\regdb.obj\
+ D^\resimage.obj\
+ D^\utility.obj\
+
+UI_NOPCOBJS = \
+ D^\geticon.obj\
+ D^\dballoc.obj\
+ D^\suminfo.obj\
+ D^\stdpal.obj\
+
+PRECOMPOBJ= $(O)precomp.obj
+
+PRECOMP=$(O)precomp.pch
+
+!if ("$(DEBUG)"=="1")
+MSG=DEBUG Static LIB Version
+LIBNAME=$(MODEL)OLE2UID
+CFLAGS=-c -Od -GA2s -W3 -Zpei -A$(MODEL) -D_DEBUG
+RFLAGS=-D DEBUG
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+OBJ=DEBUGLIB
+LIBOBJS = $(UI_COBJS:D^\=DEBUGLIB^\) $(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\)
+
+!else
+
+MSG=RETAIL Static LIB Version
+LIBNAME=$(MODEL)OLE2UI
+CFLAGS=-c -Os -GA2s -W3 -Zpe -A$(MODEL)
+RFLAGS=
+LFLAGS=/MAP:FULL /LINE /NOD /NOE /SE:300 /NOPACKCODE
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+OBJ=RETAILIB
+LIBOBJS = $(UI_COBJS:D^\=RETAILIB^\) $(UI_NOPCOBJS:D^\=RETAILIB\NOPC^\)
+
+!endif
+
+!if [if not exist $(OBJ)\*. md $(OBJ) >nul]
+!error Object subdirectory $(OBJ)\ could not be created
+!endif
+!if [if not exist $(OBJ)\NOPC\*. md $(OBJ)\NOPC > nul]
+!error non-precompiled header object subdirectory $(OBJ)\NOPC\ could not be created
+!endif
+
+# ----------------------------------------------------------------------------
+# R E S O U R C E L I S T
+# ----------------------------------------------------------------------------
+RES = \
+ busy.h \
+ common.h \
+ convert.h \
+ edlinks.h \
+ geticon.h \
+ icon.h \
+ iconbox.h \
+ insobj.h \
+ msgfiltr.h \
+ enumfetc.h \
+ ole2ui.h \
+ pastespl.h \
+ resimage.h \
+ dballoc.h \
+ suminfo.h \
+ stdpal.h \
+
+
+.SUFFIXES: .c .cpp .obj
+
+O=.\$(OBJ)^\
+
+GOAL: PRELUDE $(LIBNAME).LIB
+
+# ----------------------------------------------------------------------------
+# I N F E R E N C E R U L E S
+# ----------------------------------------------------------------------------
+
+# compile C file without precompiled headers into object directory\NOPC
+# dont compile c files etc for lcoalized builds.
+{}.c{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).c\" -Fo$(O)NOPC\$(@B) $(@B).c
+!endif
+
+# compile C file into object directory
+{}.c{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).c °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).c
+!else
+ $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).c\" -Fo$(O)$(@B) $(@B).c
+!endif
+
+# compile CPP file without precompiled headers into object directory\NOPC
+# dont compile cpp files etc for lcoalized builds.
+{}.cpp{$(O)NOPC\}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS)
+ $(CC) -Fo$(O)NOPC\$(@B) $(@B).cpp
+!else
+ $(CC) $(CFLAGS) -D_FILE_=\"$(*B).cpp\" -Fo$(O)NOPC\$(@B) $(@B).cpp
+!endif
+
+# compile CPP file into object directory
+{}.cpp{$(O)}.obj:
+ @echo °°°°°°°°°°°°°°°°°°°°°°°°° Compiling $(@B).cpp °°°°°°°°°°°°°°°°°°°°°°°°°
+!ifdef DOS
+ SET CL=$(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch
+ $(CC) -Fo$(O)$(@B) $(@B).cpp
+!else
+ $(CC) $(CFLAGS) -Yuole2ui.h -Fp$(O)precomp.pch -D_FILE_=\"$(*B).cpp\" -Fo$(O)$(@B) $(@B).cpp
+!endif
+
+
+# ----------------------------------------------------------------------------
+# D E P E N D F I L E C R E A T I O N
+# ----------------------------------------------------------------------------
+UI_CFILE = $(UI_COBJS:.obj=.c) $(UI_DLLOBJS:.obj=.c)
+UI_NOPCFILE = $(UI_NOPCOBJS:.obj=.c)
+DEPEND: nul
+ @echo Making a NEW dependancy file.
+ mkdep -p $$(O) -s .obj $(UI_CFILE:D^\=) > tmp.tmp
+ sed "s/:/: $$(PRECOMP)/g" < tmp.tmp > depend
+ -del tmp.tmp
+ mkdep -p $$(O)NOPC\ -s .obj $(UI_NOPCFILE:D^\=) >> depend
+ mkdep -p $$(O) -s .pch precomp.c >> depend
+
+# ----------------------------------------------------------------------------
+# W E L C O M E B A N N E R
+# ----------------------------------------------------------------------------
+PRELUDE:
+ @echo ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+ @echo º Makefile for UILibrary º
+ @echo ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
+ @echo $(MSG)
+!ifndef SRCTOK
+ set INCLUDE=$(OLEREL_DIR);$(INCLUDE)
+ set LIB=$(OLEREL_DIR);$(LIB)
+!endif
+
+
+# ----------------------------------------------------------------------------
+# G O A L T A R G E T S
+# ----------------------------------------------------------------------------
+!include "depend"
+
+CLEAN: CleanUp GOAL
+CleanUp:
+ -echo y|del .\$(OBJ)\*.*
+ -del $(LIBNAME).lib
+
+$(O)precomp.pch: precomp.c
+!ifdef DOS
+ SET CL=$(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h
+ $(CC) -Fo$(O)$(@B) precomp.c
+!else
+ $(CC) $(CFLAGS) -Fp$(O)precomp.pch -Ycole2ui.h -D_FILE_=\"precomp.c\" -Fo$(O)$(@B) precomp.c
+!endif
+
+#
+# Build .LIB static library
+#
+
+$(LIBNAME).lib: $(LIBOBJS) $(PRECOMPOBJ)
+ -del $(O)$(LIBNAME).lib
+ lib @<<
+$(O)$(LIBNAME).lib
+y
+$(PRECOMPOBJ: = +) $(LIBOBJS: = +)
+
+<<
+ copy $(O)$(LIBNAME).lib $(LIBNAME).lib
+
+
+# install built library to $(INSTALL_DIR) dir
+install:
+ copy $(LIBNAME).lib $(INSTALL_DIR)
+ copy ole2ui.h $(INSTALL_DIR)
+ copy olestd.h $(INSTALL_DIR)
+ copy msgfiltr.h $(INSTALL_DIR)
+ copy enumfetc.h $(INSTALL_DIR)
+ copy uiclass.h $(INSTALL_DIR)
+
+# EOF ========================================================================
diff --git a/private/oleutest/letest/ole2ui/ole2ui.rc b/private/oleutest/letest/ole2ui/ole2ui.rc
new file mode 100644
index 000000000..469608e3d
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/ole2ui.rc
@@ -0,0 +1,65 @@
+/*
+ * OLE2UI.RC
+ *
+ * Icon, menus, strings, and dialogs for the OLE 2.0 UI Support Library.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#undef PURE
+
+//fix bug when building on daytona 567
+//BUGBUG: this is hacky, we need a better long term solution, the basic
+//problem is that the rpc header file makes rc choke and die
+#define __RPCNDR_H__
+
+#include "ole2ui.h"
+
+#if defined( IBCLS )
+#define SZCLASSICONBOX IBCLS
+#define SZCLASSRESULTIMAGE RICLS
+#endif
+
+/* If "IBCLS" and "RICLS" are NOT defined as command line arguments to the
+ * RC command, then we assume there is a "uiclass.h" file which defines the
+ * two symbols "SZCLASSICONBOX" and "SZCLASSRESULTIMAGE". These need to be
+ * unique strings; they are normally built by composing the name of the
+ * "LIBNAME" or "APPNAME" with the strings "IBCls" and "RICls"
+ * respectively.
+ */
+#if !defined( SZCLASSICONBOX )
+#include "uiclass.h"
+#endif
+
+//Default 'document' icon
+//DefIcon ICON default.ico
+
+//Bitmaps for ResultImage control
+IDB_RESULTSEGA BITMAP egares.bmp
+IDB_RESULTSVGA BITMAP vgares.bmp
+IDB_RESULTSHIRESVGA BITMAP hivgares.bmp
+
+// Version Verification Resource (see OLE2UI.H)
+VERIFICATION RCDATA
+ BEGIN
+ OLEUI_VERSION_MAGIC
+ END
+
+//Include string tables here.
+#include "strings.rc"
+
+//Include each dialog template here.
+#include "insobj.dlg"
+#include "icon.dlg"
+#include "links.dlg"
+#include "pastespl.dlg"
+#include "busy.dlg"
+#include "convert.dlg"
+#include "fileopen.dlg"
+#include "prompt.dlg"
+
+// Only include the version resource if we are compiling the DLL version
+#ifdef DLL_VER
+//Version Information
+#include "OLE2UI.RCV"
+#endif
diff --git a/private/oleutest/letest/ole2ui/olestd.c b/private/oleutest/letest/ole2ui/olestd.c
new file mode 100644
index 000000000..d41a42b8d
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olestd.c
@@ -0,0 +1,3048 @@
+/*************************************************************************
+**
+** OLE 2 Standard Utilities
+**
+** olestd.c
+**
+** This file contains utilities that are useful for most standard
+** OLE 2.0 compound document type applications.
+**
+** (c) Copyright Microsoft Corp. 1992 All Rights Reserved
+**
+*************************************************************************/
+
+// #define NONAMELESSUNION // use strict ANSI standard (for DVOBJ.H)
+
+#define STRICT 1
+#include "ole2ui.h"
+#include <stdlib.h>
+#include <ctype.h>
+#include <shellapi.h>
+#include "regdb.h"
+#include "geticon.h"
+#include "common.h"
+
+OLEDBGDATA
+
+static TCHAR szAssertMemAlloc[] = TEXT("CoGetMalloc failed");
+
+static int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight);
+
+
+/* OleStdSetupAdvises
+** ------------------
+** Setup the standard View advise required by a standard,
+** compound document-oriented container. Such a container relies on
+** Ole to manage the presentation of the Ole object. The container
+** call IViewObject::Draw to render (display) the object.
+**
+** This helper routine performs the following tasks:
+** setup View advise
+** Call IOleObject::SetHostNames
+** Call OleSetContainedObject
+**
+** fCreate should be set to TRUE if the object is being created. if
+** an existing object is being loaded, then fCreate should be FALSE.
+** if it is a creation situation, then the ADVF_PRIMEFIRST flag is
+** used when settinp up the IViewObject::Advise. This will result in
+** the immediate sending of the initial picture.
+**
+** OLE2NOTE: the standard container does NOT need to set up an OLE
+** Advise (IOleObject::Advise). this routine does NOT set up an OLE
+** Advise (a previous version of this function used to setup this
+** advise, but it was not useful).
+*/
+STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect,
+ LPTSTR lpszContainerApp, LPTSTR lpszContainerObj,
+ LPADVISESINK lpAdviseSink, BOOL fCreate)
+{
+ LPVIEWOBJECT lpViewObject;
+ HRESULT hrErr;
+ BOOL fStatus = TRUE;
+#if defined( SPECIAL_CONTAINER )
+ DWORD dwTemp;
+#endif
+
+ hrErr = lpOleObject->lpVtbl->QueryInterface(
+ lpOleObject,
+ &IID_IViewObject,
+ (LPVOID FAR*)&lpViewObject
+ );
+
+ /* Setup View advise */
+ if (hrErr == NOERROR) {
+
+ OLEDBG_BEGIN2(TEXT("IViewObject::SetAdvise called\r\n"))
+ lpViewObject->lpVtbl->SetAdvise(
+ lpViewObject,
+ dwDrawAspect,
+ (fCreate ? ADVF_PRIMEFIRST : 0),
+ lpAdviseSink
+ );
+ OLEDBG_END2
+
+ OleStdRelease((LPUNKNOWN)lpViewObject);
+ } else {
+ fStatus = FALSE;
+ }
+
+#if defined( SPECIAL_CONTAINER )
+ /* Setup OLE advise.
+ ** OLE2NOTE: normally containers do NOT need to setup an OLE
+ ** advise. this advise connection is only useful for the OLE's
+ ** DefHandler and the OleLink object implementation. some
+ ** special container's might need to setup this advise for
+ ** programatic reasons.
+ **
+ ** NOTE: this advise will be torn down automatically by the
+ ** server when we release the object, therefore we do not need
+ ** to store the connection id.
+ */
+ OLEDBG_BEGIN2(TEXT("IOleObject::Advise called\r\n"))
+ hrErr = lpOleObject->lpVtbl->Advise(
+ lpOleObject,
+ lpAdviseSink,
+ (DWORD FAR*)&dwTemp
+ );
+ OLEDBG_END2
+ if (hrErr != NOERROR) fStatus = FALSE;
+#endif
+
+ /* Setup the host names for the OLE object. */
+ OLEDBG_BEGIN2(TEXT("IOleObject::SetHostNames called\r\n"))
+
+ hrErr = CallIOleObjectSetHostNamesA(
+ lpOleObject,
+ lpszContainerApp,
+ lpszContainerObj
+ );
+
+ OLEDBG_END2
+
+ if (hrErr != NOERROR) fStatus = FALSE;
+
+ /* Inform the loadded object's handler/inproc-server that it is in
+ ** its embedding container's process.
+ */
+ OLEDBG_BEGIN2(TEXT("OleSetContainedObject(TRUE) called\r\n"))
+ OleSetContainedObject((LPUNKNOWN)lpOleObject, TRUE);
+ OLEDBG_END2
+
+ return fStatus;
+}
+
+
+/* OleStdSwitchDisplayAspect
+** -------------------------
+** Switch the currently cached display aspect between DVASPECT_ICON
+** and DVASPECT_CONTENT.
+**
+** NOTE: when setting up icon aspect, any currently cached content
+** cache is discarded and any advise connections for content aspect
+** are broken.
+**
+** RETURNS:
+** S_OK -- new display aspect setup successfully
+** E_INVALIDARG -- IOleCache interface is NOT supported (this is
+** required).
+** <other SCODE> -- any SCODE that can be returned by
+** IOleCache::Cache method.
+** NOTE: if an error occurs then the current display aspect and
+** cache contents unchanged.
+*/
+STDAPI OleStdSwitchDisplayAspect(
+ LPOLEOBJECT lpOleObj,
+ LPDWORD lpdwCurAspect,
+ DWORD dwNewAspect,
+ HGLOBAL hMetaPict,
+ BOOL fDeleteOldAspect,
+ BOOL fSetupViewAdvise,
+ LPADVISESINK lpAdviseSink,
+ BOOL FAR* lpfMustUpdate
+)
+{
+ LPOLECACHE lpOleCache = NULL;
+ LPVIEWOBJECT lpViewObj = NULL;
+ LPENUMSTATDATA lpEnumStatData = NULL;
+ STATDATA StatData;
+ FORMATETC FmtEtc;
+ STGMEDIUM Medium;
+ DWORD dwAdvf;
+ DWORD dwNewConnection;
+ DWORD dwOldAspect = *lpdwCurAspect;
+ HRESULT hrErr;
+
+ if (lpfMustUpdate)
+ *lpfMustUpdate = FALSE;
+
+ lpOleCache = (LPOLECACHE)OleStdQueryInterface(
+ (LPUNKNOWN)lpOleObj,&IID_IOleCache);
+
+ // if IOleCache* is NOT available, do nothing
+ if (! lpOleCache)
+ return ResultFromScode(E_INVALIDARG);
+
+ // Setup new cache with the new aspect
+ FmtEtc.cfFormat = (CLIPFORMAT) NULL; // whatever is needed to draw
+ FmtEtc.ptd = NULL;
+ FmtEtc.dwAspect = dwNewAspect;
+ FmtEtc.lindex = -1;
+ FmtEtc.tymed = TYMED_NULL;
+
+ /* OLE2NOTE: if we are setting up Icon aspect with a custom icon
+ ** then we do not want DataAdvise notifications to ever change
+ ** the contents of the data cache. thus we set up a NODATA
+ ** advise connection. otherwise we set up a standard DataAdvise
+ ** connection.
+ */
+ if (dwNewAspect == DVASPECT_ICON && hMetaPict)
+ dwAdvf = ADVF_NODATA;
+ else
+ dwAdvf = ADVF_PRIMEFIRST;
+
+ OLEDBG_BEGIN2(TEXT("IOleCache::Cache called\r\n"))
+ hrErr = lpOleCache->lpVtbl->Cache(
+ lpOleCache,
+ (LPFORMATETC)&FmtEtc,
+ dwAdvf,
+ (LPDWORD)&dwNewConnection
+ );
+ OLEDBG_END2
+
+ if (! SUCCEEDED(hrErr)) {
+ OleDbgOutHResult(TEXT("IOleCache::Cache returned"), hrErr);
+ OleStdRelease((LPUNKNOWN)lpOleCache);
+ return hrErr;
+ }
+
+ *lpdwCurAspect = dwNewAspect;
+
+ /* OLE2NOTE: if we are setting up Icon aspect with a custom icon,
+ ** then stuff the icon into the cache. otherwise the cache must
+ ** be forced to be updated. set the *lpfMustUpdate flag to tell
+ ** caller to force the object to Run so that the cache will be
+ ** updated.
+ */
+ if (dwNewAspect == DVASPECT_ICON && hMetaPict) {
+
+ FmtEtc.cfFormat = CF_METAFILEPICT;
+ FmtEtc.ptd = NULL;
+ FmtEtc.dwAspect = DVASPECT_ICON;
+ FmtEtc.lindex = -1;
+ FmtEtc.tymed = TYMED_MFPICT;
+
+ Medium.tymed = TYMED_MFPICT;
+ Medium.hGlobal = hMetaPict;
+ Medium.pUnkForRelease = NULL;
+
+ OLEDBG_BEGIN2(TEXT("IOleCache::SetData called\r\n"))
+ hrErr = lpOleCache->lpVtbl->SetData(
+ lpOleCache,
+ (LPFORMATETC)&FmtEtc,
+ (LPSTGMEDIUM)&Medium,
+ FALSE /* fRelease */
+ );
+ OLEDBG_END2
+ } else {
+ if (lpfMustUpdate)
+ *lpfMustUpdate = TRUE;
+ }
+
+ if (fSetupViewAdvise && lpAdviseSink) {
+ /* OLE2NOTE: re-establish the ViewAdvise connection */
+ lpViewObj = (LPVIEWOBJECT)OleStdQueryInterface(
+ (LPUNKNOWN)lpOleObj,&IID_IViewObject);
+
+ if (lpViewObj) {
+
+ OLEDBG_BEGIN2(TEXT("IViewObject::SetAdvise called\r\n"))
+ lpViewObj->lpVtbl->SetAdvise(
+ lpViewObj,
+ dwNewAspect,
+ 0,
+ lpAdviseSink
+ );
+ OLEDBG_END2
+
+ OleStdRelease((LPUNKNOWN)lpViewObj);
+ }
+ }
+
+ /* OLE2NOTE: remove any existing caches that are set up for the old
+ ** display aspect. It WOULD be possible to retain the caches set
+ ** up for the old aspect, but this would increase the storage
+ ** space required for the object and possibly require additional
+ ** overhead to maintain the unused cachaes. For these reasons the
+ ** strategy to delete the previous caches is prefered. if it is a
+ ** requirement to quickly switch between Icon and Content
+ ** display, then it would be better to keep both aspect caches.
+ */
+
+ if (fDeleteOldAspect) {
+ OLEDBG_BEGIN2(TEXT("IOleCache::EnumCache called\r\n"))
+ hrErr = lpOleCache->lpVtbl->EnumCache(
+ lpOleCache,
+ (LPENUMSTATDATA FAR*)&lpEnumStatData
+ );
+ OLEDBG_END2
+
+ while(hrErr == NOERROR) {
+ hrErr = lpEnumStatData->lpVtbl->Next(
+ lpEnumStatData,
+ 1,
+ (LPSTATDATA)&StatData,
+ NULL
+ );
+ if (hrErr != NOERROR)
+ break; // DONE! no more caches.
+
+ if (StatData.formatetc.dwAspect == dwOldAspect) {
+
+ // Remove previous cache with old aspect
+ OLEDBG_BEGIN2(TEXT("IOleCache::Uncache called\r\n"))
+ lpOleCache->lpVtbl->Uncache(lpOleCache,StatData.dwConnection);
+ OLEDBG_END2
+ }
+ }
+
+ if (lpEnumStatData) {
+ OleStdVerifyRelease(
+ (LPUNKNOWN)lpEnumStatData,
+ TEXT("OleStdSwitchDisplayAspect: Cache enumerator NOT released")
+ );
+ }
+ }
+
+ if (lpOleCache)
+ OleStdRelease((LPUNKNOWN)lpOleCache);
+
+ return NOERROR;
+}
+
+
+/* OleStdSetIconInCache
+** --------------------
+** SetData a new icon into the existing DVASPECT_ICON cache.
+**
+** RETURNS:
+** HRESULT returned from IOleCache::SetData
+*/
+STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict)
+{
+ LPOLECACHE lpOleCache = NULL;
+ FORMATETC FmtEtc;
+ STGMEDIUM Medium;
+ HRESULT hrErr;
+
+ if (! hMetaPict)
+ return FALSE; // invalid icon
+
+ lpOleCache = (LPOLECACHE)OleStdQueryInterface(
+ (LPUNKNOWN)lpOleObj,&IID_IOleCache);
+ if (! lpOleCache)
+ return FALSE; // if IOleCache* is NOT available, do nothing
+
+ FmtEtc.cfFormat = CF_METAFILEPICT;
+ FmtEtc.ptd = NULL;
+ FmtEtc.dwAspect = DVASPECT_ICON;
+ FmtEtc.lindex = -1;
+ FmtEtc.tymed = TYMED_MFPICT;
+
+ // stuff the icon into the cache.
+ Medium.tymed = TYMED_MFPICT;
+ Medium.hGlobal = hMetaPict;
+ Medium.pUnkForRelease = NULL;
+
+ OLEDBG_BEGIN2(TEXT("IOleCache::SetData called\r\n"))
+ hrErr = lpOleCache->lpVtbl->SetData(
+ lpOleCache,
+ (LPFORMATETC)&FmtEtc,
+ (LPSTGMEDIUM)&Medium,
+ FALSE /* fRelease */
+ );
+ OLEDBG_END2
+
+ OleStdRelease((LPUNKNOWN)lpOleCache);
+
+ return hrErr;
+}
+
+
+
+/* OleStdDoConvert
+** ---------------
+** Do the container-side responsibilities for converting an object.
+** This function would be used in conjunction with the OleUIConvert
+** dialog. If the user selects to convert an object then the
+** container must do the following:
+** 1. unload the object.
+** 2. write the NEW CLSID and NEW user type name
+** string into the storage of the object,
+** BUT write the OLD format tag.
+** 3. force an update of the object to force the actual
+** conversion of the data bits.
+**
+** This function takes care of step 2.
+*/
+STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew)
+{
+ HRESULT error;
+ CLSID clsidOld;
+ CLIPFORMAT cfOld;
+ LPTSTR lpszOld = NULL;
+ TCHAR szNew[OLEUI_CCHKEYMAX];
+
+ if ((error = ReadClassStg(lpStg, &clsidOld)) != NOERROR) {
+ clsidOld = CLSID_NULL;
+ goto errRtn;
+ }
+
+ // read old fmt/old user type; sets out params to NULL on error
+ {
+ LPOLESTR polestr;
+
+ error = ReadFmtUserTypeStg(lpStg, &cfOld, &polestr);
+
+ CopyAndFreeOLESTR(polestr, &lpszOld);
+ }
+
+ OleDbgAssert(error == NOERROR || (cfOld == 0 && lpszOld == NULL));
+
+ // get new user type name; if error, set to NULL string
+ if (OleStdGetUserTypeOfClass(
+ // (LPCLSID)
+ rClsidNew, szNew,sizeof(szNew),NULL /* hKey */) == 0)
+ szNew[0] = TEXT('\0');
+
+ // write class stg
+ if ((error = WriteClassStg(lpStg, rClsidNew)) != NOERROR)
+ goto errRtn;
+
+ // write old fmt/new user type;
+#ifdef UNICODE
+ if ((error = WriteFmtUserTypeStg(lpStg, cfOld, szNew)) != NOERROR)
+ goto errRewriteInfo;
+#else
+ {
+ // Chicago OLE is using UNICODE, so we need to convert the string to
+ // UNICODE.
+ WCHAR szNewT[OLEUI_CCHKEYMAX];
+ mbstowcs(szNewT, szNew, sizeof(szNew));
+ if ((error = WriteFmtUserTypeStg(lpStg, cfOld, szNewT)) != NOERROR)
+ goto errRewriteInfo;
+ }
+#endif
+
+ // set convert bit
+ if ((error = SetConvertStg(lpStg, TRUE)) != NOERROR)
+ goto errRewriteInfo;
+
+ goto okRtn;
+
+errRewriteInfo:
+ (void)WriteClassStg(lpStg, &clsidOld);
+
+ (void)WriteFmtUserTypeStgA(lpStg, cfOld, lpszOld);
+
+errRtn:
+
+okRtn:
+ OleStdFreeString(lpszOld, NULL);
+ return error;
+}
+
+
+/* OleStdGetTreatAsFmtUserType
+** ---------------------------
+** Determine if the application should perform a TreatAs (ActivateAs
+** object or emulation) operation for the object that is stored in
+** the storage.
+**
+** if the CLSID written in the storage is not the same as the
+** application's own CLSID (clsidApp), then a TreatAs operation
+** should take place. if so determine the format the data should be
+** written and the user type name of the object the app should
+** emulate (ie. pretend to be). if this information is not written
+** in the storage then it is looked up in the REGDB. if it can not
+** be found in the REGDB, then the TreatAs operation can NOT be
+** executed.
+**
+** RETURNS: TRUE -- if TreatAs should be performed.
+** valid lpclsid, lplpszType, lpcfFmt to TreatAs are returned
+** (NOTE: lplpszType must be freed by caller)
+** FALSE -- NO TreatAs. lpszType will be NULL.
+** lpclsid = CLSID_NULL; lplpszType = lpcfFmt = NULL;
+*/
+STDAPI_(BOOL) OleStdGetTreatAsFmtUserType(
+ REFCLSID rclsidApp,
+ LPSTORAGE lpStg,
+ CLSID FAR* lpclsid,
+ CLIPFORMAT FAR* lpcfFmt,
+ LPTSTR FAR* lplpszType
+)
+{
+ HRESULT hrErr;
+ HKEY hKey;
+ LONG lRet;
+ UINT lSize;
+ TCHAR szBuf[OLEUI_CCHKEYMAX];
+
+ *lpclsid = CLSID_NULL;
+ *lpcfFmt = 0;
+ *lplpszType = NULL;
+
+ hrErr = ReadClassStg(lpStg, lpclsid);
+ if (hrErr == NOERROR &&
+ ! IsEqualCLSID(lpclsid, &CLSID_NULL) &&
+ ! IsEqualCLSID(lpclsid, rclsidApp)) {
+
+ hrErr = ReadFmtUserTypeStgA(lpStg,(CLIPFORMAT FAR*)lpcfFmt, lplpszType);
+
+ if (hrErr == NOERROR && lplpszType && *lpcfFmt != 0)
+ return TRUE; // Do TreatAs. info was in lpStg.
+
+ /* read info from REGDB
+ ** *lpcfFmt = value of field: CLSID\{...}\DataFormats\DefaultFile
+ ** *lplpszType = value of field: CLSID\{...}
+ */
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+ if (lRet != (LONG)ERROR_SUCCESS)
+ return FALSE;
+ *lpcfFmt = OleStdGetDefaultFileFormatOfClass(lpclsid, hKey);
+ if (*lpcfFmt == 0)
+ return FALSE;
+ lSize = OleStdGetUserTypeOfClass(lpclsid,szBuf,sizeof(szBuf),hKey);
+ if (lSize == 0)
+ return FALSE;
+ *lplpszType = OleStdCopyString(szBuf, NULL);
+ } else {
+ return FALSE; // NO TreatAs
+ }
+}
+
+
+
+/* OleStdDoTreatAsClass
+** --------------------
+** Do the container-side responsibilities for "ActivateAs" (aka.
+** TreatAs) for an object.
+** This function would be used in conjunction with the OleUIConvert
+** dialog. If the user selects to ActivateAs an object then the
+** container must do the following:
+** 1. unload ALL objects of the OLD class that app knows about
+** 2. add the TreatAs tag in the registration database
+** by calling CoTreatAsClass().
+** 3. lazily it can reload the objects; when the objects
+** are reloaded the TreatAs will take effect.
+**
+** This function takes care of step 2.
+*/
+STDAPI OleStdDoTreatAsClass(LPTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew)
+{
+ HRESULT hrErr;
+ LPTSTR lpszCLSID = NULL;
+ LONG lRet;
+ HKEY hKey;
+
+ OLEDBG_BEGIN2(TEXT("CoTreatAsClass called\r\n"))
+ hrErr = CoTreatAsClass(rclsid, rclsidNew);
+ OLEDBG_END2
+
+ if ((hrErr != NOERROR) && lpszUserType) {
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, (LPCTSTR) TEXT("CLSID"),
+ (HKEY FAR *)&hKey);
+ StringFromCLSIDA(rclsid, &lpszCLSID);
+
+ RegSetValue(hKey, lpszCLSID, REG_SZ, lpszUserType,
+ lstrlen(lpszUserType));
+
+ if (lpszCLSID)
+ OleStdFreeString(lpszCLSID, NULL);
+
+ hrErr = CoTreatAsClass(rclsid, rclsidNew);
+ RegCloseKey(hKey);
+ }
+
+ return hrErr;
+}
+
+
+
+/* OleStdIsOleLink
+** ---------------
+** Returns TRUE if the OleObject is infact an OLE link object. this
+** checks if IOleLink interface is supported. if so, the object is a
+** link, otherwise not.
+*/
+STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk)
+{
+ LPOLELINK lpOleLink;
+
+ lpOleLink = (LPOLELINK)OleStdQueryInterface(lpUnk, &IID_IOleLink);
+
+ if (lpOleLink) {
+ OleStdRelease((LPUNKNOWN)lpOleLink);
+ return TRUE;
+ } else
+ return FALSE;
+}
+
+
+/* OleStdQueryInterface
+** --------------------
+** Returns the desired interface pointer if exposed by the given object.
+** Returns NULL if the interface is not available.
+** eg.:
+** lpDataObj = OleStdQueryInterface(lpOleObj, &IID_DataObject);
+*/
+STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid)
+{
+ LPUNKNOWN lpInterface;
+ HRESULT hrErr;
+
+ hrErr = lpUnk->lpVtbl->QueryInterface(
+ lpUnk,
+ riid,
+ (LPVOID FAR*)&lpInterface
+ );
+
+ if (hrErr == NOERROR)
+ return lpInterface;
+ else
+ return NULL;
+}
+
+
+/* OleStdGetData
+** -------------
+** Retrieve data from an IDataObject in a specified format on a
+** global memory block. This function ALWAYS returns a private copy
+** of the data to the caller. if necessary a copy is made of the
+** data (ie. if lpMedium->pUnkForRelease != NULL). The caller assumes
+** ownership of the data block in all cases and must free the data
+** when done with it. The caller may directly free the data handle
+** returned (taking care whether it is a simple HGLOBAL or a HANDLE
+** to a MetafilePict) or the caller may call
+** ReleaseStgMedium(lpMedium). this OLE helper function will do the
+** right thing.
+**
+** PARAMETERS:
+** LPDATAOBJECT lpDataObj -- object on which GetData should be
+** called.
+** CLIPFORMAT cfFormat -- desired clipboard format (eg. CF_TEXT)
+** DVTARGETDEVICE FAR* lpTargetDevice -- target device for which
+** the data should be composed. This may
+** be NULL. NULL can be used whenever the
+** data format is insensitive to target
+** device or when the caller does not care
+** what device is used.
+** LPSTGMEDIUM lpMedium -- ptr to STGMEDIUM struct. the
+** resultant medium from the
+** IDataObject::GetData call is
+** returned.
+**
+** RETURNS:
+** HGLOBAL -- global memory handle of retrieved data block.
+** NULL -- if error.
+*/
+STDAPI_(HGLOBAL) OleStdGetData(
+ LPDATAOBJECT lpDataObj,
+ CLIPFORMAT cfFormat,
+ DVTARGETDEVICE FAR* lpTargetDevice,
+ DWORD dwDrawAspect,
+ LPSTGMEDIUM lpMedium
+)
+{
+ HRESULT hrErr;
+ FORMATETC formatetc;
+ HGLOBAL hGlobal = NULL;
+ HGLOBAL hCopy;
+ LPVOID lp;
+
+ formatetc.cfFormat = cfFormat;
+ formatetc.ptd = lpTargetDevice;
+ formatetc.dwAspect = dwDrawAspect;
+ formatetc.lindex = -1;
+
+ switch (cfFormat) {
+ case CF_METAFILEPICT:
+ formatetc.tymed = TYMED_MFPICT;
+ break;
+
+ case CF_BITMAP:
+ formatetc.tymed = TYMED_GDI;
+ break;
+
+ default:
+ formatetc.tymed = TYMED_HGLOBAL;
+ break;
+ }
+
+ OLEDBG_BEGIN2(TEXT("IDataObject::GetData called\r\n"))
+ hrErr = lpDataObj->lpVtbl->GetData(
+ lpDataObj,
+ (LPFORMATETC)&formatetc,
+ lpMedium
+ );
+ OLEDBG_END2
+
+ if (hrErr != NOERROR)
+ return NULL;
+
+ if ((hGlobal = lpMedium->hGlobal) == NULL)
+ return NULL;
+
+ // Check if hGlobal really points to valid memory
+ if ((lp = GlobalLock(hGlobal)) != NULL) {
+ if (IsBadReadPtr(lp, 1)) {
+ GlobalUnlock(hGlobal);
+ return NULL; // ERROR: memory is NOT valid
+ }
+ GlobalUnlock(hGlobal);
+ }
+
+ if (hGlobal != NULL && lpMedium->pUnkForRelease != NULL) {
+ /* OLE2NOTE: the callee wants to retain ownership of the data.
+ ** this is indicated by passing a non-NULL pUnkForRelease.
+ ** thus, we will make a copy of the data and release the
+ ** callee's copy.
+ */
+
+ hCopy = OleDuplicateData(hGlobal, cfFormat, GHND|GMEM_SHARE);
+ ReleaseStgMedium(lpMedium); // release callee's copy of data
+
+ hGlobal = hCopy;
+ lpMedium->hGlobal = hCopy;
+ lpMedium->pUnkForRelease = NULL;
+ }
+ return hGlobal;
+}
+
+
+/* OleStdMalloc
+** ------------
+** allocate memory using the currently active IMalloc* allocator
+*/
+STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize)
+{
+ LPVOID pout;
+ LPMALLOC pmalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssertSz(0, szAssertMemAlloc);
+ return NULL;
+ }
+
+ pout = (LPVOID)pmalloc->lpVtbl->Alloc(pmalloc, ulSize);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
+ }
+
+ return pout;
+}
+
+
+/* OleStdRealloc
+** -------------
+** re-allocate memory using the currently active IMalloc* allocator
+*/
+STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize)
+{
+ LPVOID pout;
+ LPMALLOC pmalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssertSz(0, szAssertMemAlloc);
+ return NULL;
+ }
+
+ pout = (LPVOID)pmalloc->lpVtbl->Realloc(pmalloc, pmem, ulSize);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
+ }
+
+ return pout;
+}
+
+
+/* OleStdFree
+** ----------
+** free memory using the currently active IMalloc* allocator
+*/
+STDAPI_(void) OleStdFree(LPVOID pmem)
+{
+ LPMALLOC pmalloc;
+
+ if (pmem == NULL)
+ return;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssertSz(0, szAssertMemAlloc);
+ return;
+ }
+
+ pmalloc->lpVtbl->Free(pmalloc, pmem);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
+ }
+}
+
+
+/* OleStdGetSize
+** -------------
+** Get the size of a memory block that was allocated using the
+** currently active IMalloc* allocator.
+*/
+STDAPI_(ULONG) OleStdGetSize(LPVOID pmem)
+{
+ ULONG ulSize;
+ LPMALLOC pmalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssertSz(0, szAssertMemAlloc);
+ return (ULONG)-1;
+ }
+
+ ulSize = pmalloc->lpVtbl->GetSize(pmalloc, pmem);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->lpVtbl->Release(pmalloc);
+ }
+
+ return ulSize;
+}
+
+
+/* OleStdFreeString
+** ----------------
+** Free a string that was allocated with the currently active
+** IMalloc* allocator.
+**
+** if the caller has the current IMalloc* handy, then it can be
+** passed as a argument, otherwise this function will retrieve the
+** active allocator and use it.
+*/
+STDAPI_(void) OleStdFreeString(LPTSTR lpsz, LPMALLOC lpMalloc)
+{
+ BOOL fMustRelease = FALSE;
+
+ if (! lpMalloc) {
+ if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR)
+ return;
+ fMustRelease = TRUE;
+ }
+
+ lpMalloc->lpVtbl->Free(lpMalloc, lpsz);
+
+ if (fMustRelease)
+ lpMalloc->lpVtbl->Release(lpMalloc);
+}
+
+
+/* OleStdCopyString
+** ----------------
+** Copy a string into memory allocated with the currently active
+** IMalloc* allocator.
+**
+** if the caller has the current IMalloc* handy, then it can be
+** passed as a argument, otherwise this function will retrieve the
+** active allocator and use it.
+*/
+STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc, LPMALLOC lpMalloc)
+{
+ LPTSTR lpszDest = NULL;
+ BOOL fMustRelease = FALSE;
+ UINT lSize = lstrlen(lpszSrc);
+
+ if (! lpMalloc) {
+ if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) != NOERROR)
+ return NULL;
+ fMustRelease = TRUE;
+ }
+
+ lpszDest = lpMalloc->lpVtbl->Alloc(lpMalloc, (lSize+1)*sizeof(TCHAR));
+
+ if (lpszDest)
+ lstrcpy(lpszDest, lpszSrc);
+
+ if (fMustRelease)
+ lpMalloc->lpVtbl->Release(lpMalloc);
+ return lpszDest;
+}
+
+
+/*
+ * OleStdCreateStorageOnHGlobal()
+ *
+ * Purpose:
+ * Create a memory based IStorage*.
+ *
+ * OLE2NOTE: if fDeleteOnRelease==TRUE, then the ILockBytes is created
+ * such that it will delete them memory on its last release.
+ * the IStorage on created on top of the ILockBytes in NOT
+ * created with STGM_DELETEONRELEASE. when the IStorage receives
+ * its last release, it will release the ILockBytes which will
+ * in turn free the memory. it is in fact an error to specify
+ * STGM_DELETEONRELEASE in this situation.
+ *
+ * Parameters:
+ * hGlobal -- handle to MEM_SHARE allocated memory. may be NULL and
+ * memory will be automatically allocated.
+ * fDeleteOnRelease -- controls if the memory is freed on the last release.
+ * grfMode -- flags passed to StgCreateDocfileOnILockBytes
+ *
+ * NOTE: if hGlobal is NULL, then a new IStorage is created and
+ * STGM_CREATE flag is passed to StgCreateDocfileOnILockBytes.
+ * if hGlobal is non-NULL, then it is assumed that the hGlobal already
+ * has an IStorage inside it and STGM_CONVERT flag is passed
+ * to StgCreateDocfileOnILockBytes.
+ *
+ * Return Value:
+ * SCODE - S_OK if successful
+ */
+STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal(
+ HANDLE hGlobal,
+ BOOL fDeleteOnRelease,
+ DWORD grfMode
+)
+{
+ DWORD grfCreateMode=grfMode | (hGlobal==NULL ? STGM_CREATE:STGM_CONVERT);
+ HRESULT hrErr;
+ LPLOCKBYTES lpLockBytes = NULL;
+ DWORD reserved = 0;
+ LPSTORAGE lpStg = NULL;
+
+ hrErr = CreateILockBytesOnHGlobal(
+ hGlobal,
+ fDeleteOnRelease,
+ (LPLOCKBYTES FAR*)&lpLockBytes
+ );
+ if (hrErr != NOERROR)
+ return NULL;
+
+ hrErr = StgCreateDocfileOnILockBytes(
+ lpLockBytes,
+ grfCreateMode,
+ reserved,
+ (LPSTORAGE FAR*)&lpStg
+ );
+ if (hrErr != NOERROR) {
+ OleStdRelease((LPUNKNOWN)lpLockBytes);
+ return NULL;
+ }
+ return lpStg;
+}
+
+
+
+/*
+ * OleStdCreateTempStorage()
+ *
+ * Purpose:
+ * Create a temporay IStorage* that will DeleteOnRelease.
+ * this can be either memory based or file based.
+ *
+ * Parameters:
+ * fUseMemory -- controls if memory-based or file-based stg is created
+ * grfMode -- storage mode flags
+ *
+ * Return Value:
+ * LPSTORAGE - if successful, NULL otherwise
+ */
+STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode)
+{
+ LPSTORAGE lpstg;
+ HRESULT hrErr;
+ DWORD reserved = 0;
+
+ if (fUseMemory) {
+ lpstg = OleStdCreateStorageOnHGlobal(
+ NULL, /* auto allocate */
+ TRUE, /* delete on release */
+ grfMode
+ );
+ } else {
+ /* allocate a temp docfile that will delete on last release */
+ hrErr = StgCreateDocfile(
+ NULL,
+ grfMode | STGM_DELETEONRELEASE | STGM_CREATE,
+ reserved,
+ &lpstg
+ );
+ if (hrErr != NOERROR)
+ return NULL;
+ }
+ return lpstg;
+}
+
+
+/* OleStdGetOleObjectData
+** ----------------------
+** Render CF_EMBEDSOURCE/CF_EMBEDDEDOBJECT data on an TYMED_ISTORAGE
+** medium by asking the object to save into the storage.
+** the object must support IPersistStorage.
+**
+** if lpMedium->tymed == TYMED_NULL, then a delete-on-release
+** storage is allocated (either file-based or memory-base depending
+** the value of fUseMemory). this is useful to support an
+** IDataObject::GetData call where the callee must allocate the
+** medium.
+**
+** if lpMedium->tymed == TYMED_ISTORAGE, then the data is writen
+** into the passed in IStorage. this is useful to support an
+** IDataObject::GetDataHere call where the caller has allocated his
+** own IStorage.
+*/
+STDAPI OleStdGetOleObjectData(
+ LPPERSISTSTORAGE lpPStg,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium,
+ BOOL fUseMemory
+)
+{
+ LPSTORAGE lpstg = NULL;
+ DWORD reserved = 0;
+ SCODE sc = S_OK;
+ HRESULT hrErr;
+
+ lpMedium->pUnkForRelease = NULL;
+
+ if (lpMedium->tymed == TYMED_NULL) {
+
+ if (lpformatetc->tymed & TYMED_ISTORAGE) {
+
+ /* allocate a temp docfile that will delete on last release */
+ lpstg = OleStdCreateTempStorage(
+ TRUE /*fUseMemory*/,
+ STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE
+ );
+ if (!lpstg)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ lpMedium->pstg = lpstg;
+ lpMedium->tymed = TYMED_ISTORAGE;
+ lpMedium->pUnkForRelease = NULL;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+ } else if (lpMedium->tymed == TYMED_ISTORAGE) {
+ lpMedium->tymed = TYMED_ISTORAGE;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+
+ // OLE2NOTE: even if OleSave returns an error you should still call
+ // SaveCompleted.
+
+ OLEDBG_BEGIN2(TEXT("OleSave called\r\n"))
+ hrErr = OleSave(lpPStg, lpMedium->pstg, FALSE /* fSameAsLoad */);
+ OLEDBG_END2
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: OleSave returned"), hrErr);
+ sc = GetScode(hrErr);
+ }
+ OLEDBG_BEGIN2(TEXT("IPersistStorage::SaveCompleted called\r\n"))
+ hrErr = lpPStg->lpVtbl->SaveCompleted(lpPStg, NULL);
+ OLEDBG_END2
+
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult(TEXT("WARNING: SaveCompleted returned"),hrErr);
+ if (sc == S_OK)
+ sc = GetScode(hrErr);
+ }
+
+ return ResultFromScode(sc);
+}
+
+
+STDAPI OleStdGetLinkSourceData(
+ LPMONIKER lpmk,
+ LPCLSID lpClsID,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium
+)
+{
+ LPSTREAM lpstm = NULL;
+ DWORD reserved = 0;
+ HRESULT hrErr;
+
+ if (lpMedium->tymed == TYMED_NULL) {
+ if (lpformatetc->tymed & TYMED_ISTREAM) {
+ hrErr = CreateStreamOnHGlobal(
+ NULL, /* auto allocate */
+ TRUE, /* delete on release */
+ (LPSTREAM FAR*)&lpstm
+ );
+ if (hrErr != NOERROR) {
+ lpMedium->pUnkForRelease = NULL;
+ return ResultFromScode(E_OUTOFMEMORY);
+ }
+ lpMedium->pstm = lpstm;
+ lpMedium->tymed = TYMED_ISTREAM;
+ lpMedium->pUnkForRelease = NULL;
+ } else {
+ lpMedium->pUnkForRelease = NULL;
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+ } else {
+ if (lpMedium->tymed == TYMED_ISTREAM) {
+ lpMedium->tymed = TYMED_ISTREAM;
+ lpMedium->pstm = lpMedium->pstm;
+ lpMedium->pUnkForRelease = NULL;
+ } else {
+ lpMedium->pUnkForRelease = NULL;
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+ }
+
+ hrErr = OleSaveToStream((LPPERSISTSTREAM)lpmk, lpMedium->pstm);
+ if (hrErr != NOERROR) return hrErr;
+ return WriteClassStm(lpMedium->pstm, lpClsID);
+}
+
+/*
+ * OleStdGetObjectDescriptorData
+ *
+ * Purpose:
+ * Fills and returns a OBJECTDESCRIPTOR structure.
+ * See OBJECTDESCRIPTOR for more information.
+ *
+ * Parameters:
+ * clsid CLSID CLSID of object being transferred
+ * dwDrawAspect DWORD Display Aspect of object
+ * sizel SIZEL Size of object in HIMETRIC
+ * pointl POINTL Offset from upper-left corner of object where mouse went
+ * down for drag. Meaningful only when drag-drop is used.
+ * dwStatus DWORD OLEMISC flags
+ * lpszFullUserTypeName LPSTR Full User Type Name
+ * lpszSrcOfCopy LPSTR Source of Copy
+ *
+ * Return Value:
+ * HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
+ */
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData(
+ CLSID clsid,
+ DWORD dwDrawAspect,
+ SIZEL sizel,
+ POINTL pointl,
+ DWORD dwStatus,
+ LPTSTR lpszFullUserTypeNameA,
+ LPTSTR lpszSrcOfCopyA
+)
+{
+ HGLOBAL hMem = NULL;
+ IBindCtx FAR *pbc = NULL;
+ LPOBJECTDESCRIPTOR lpOD;
+ DWORD dwObjectDescSize, dwFullUserTypeNameLen, dwSrcOfCopyLen;
+ LPOLESTR lpszFullUserTypeName,
+ lpszSrcOfCopy;
+
+ // convert out strings to UNICODE
+
+ if( lpszSrcOfCopyA )
+ {
+ lpszSrcOfCopy = CreateOLESTR(lpszSrcOfCopyA);
+ }
+
+ lpszFullUserTypeName = CreateOLESTR(lpszFullUserTypeNameA);
+
+ // Get the length of Full User Type Name; Add 1 for the null terminator
+ dwFullUserTypeNameLen = lpszFullUserTypeName ? wcslen(lpszFullUserTypeName)+1 : 0;
+
+ // Get the Source of Copy string and it's length; Add 1 for the null terminator
+ if (lpszSrcOfCopy)
+ dwSrcOfCopyLen = wcslen(lpszSrcOfCopy)+1;
+ else {
+ // No src moniker so use user type name as source string.
+ lpszSrcOfCopy = lpszFullUserTypeName;
+ dwSrcOfCopyLen = dwFullUserTypeNameLen;
+ }
+
+ // Allocate space for OBJECTDESCRIPTOR and the additional string data
+ dwObjectDescSize = sizeof(OBJECTDESCRIPTOR);
+ hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, dwObjectDescSize +
+ (dwFullUserTypeNameLen + dwSrcOfCopyLen)*sizeof(OLECHAR));
+ if (NULL == hMem)
+ goto error;
+
+ lpOD = (LPOBJECTDESCRIPTOR)GlobalLock(hMem);
+
+ // Set the FullUserTypeName offset and copy the string
+ if (lpszFullUserTypeName)
+ {
+ lpOD->dwFullUserTypeName = dwObjectDescSize;
+ wcscpy((LPOLESTR)(((BYTE FAR *)lpOD)+lpOD->dwFullUserTypeName),
+ lpszFullUserTypeName);
+ }
+ else lpOD->dwFullUserTypeName = 0; // zero offset indicates that string is not present
+
+ // Set the SrcOfCopy offset and copy the string
+ if (lpszSrcOfCopy)
+ {
+ lpOD->dwSrcOfCopy = dwObjectDescSize +
+ dwFullUserTypeNameLen*sizeof(OLECHAR);
+ wcscpy((LPOLESTR)(((BYTE FAR *)lpOD)+lpOD->dwSrcOfCopy), lpszSrcOfCopy);
+ }
+ else lpOD->dwSrcOfCopy = 0; // zero offset indicates that string is not present
+
+ // Initialize the rest of the OBJECTDESCRIPTOR
+ lpOD->cbSize = dwObjectDescSize +
+ (dwFullUserTypeNameLen + dwSrcOfCopyLen)*sizeof(OLECHAR);
+ lpOD->clsid = clsid;
+ lpOD->dwDrawAspect = dwDrawAspect;
+ lpOD->sizel = sizel;
+ lpOD->pointl = pointl;
+ lpOD->dwStatus = dwStatus;
+
+ GlobalUnlock(hMem);
+
+ FREEOLESTR(lpszFullUserTypeName);
+ FREEOLESTR(lpszSrcOfCopy);
+
+ return hMem;
+
+error:
+ if (hMem)
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ }
+ return NULL;
+}
+
+/*
+ * OleStdGetObjectDescriptorDataFromOleObject
+ *
+ * Purpose:
+ * Fills and returns a OBJECTDESCRIPTOR structure. Information for the structure is
+ * obtained from an OLEOBJECT.
+ * See OBJECTDESCRIPTOR for more information.
+ *
+ * Parameters:
+ * lpOleObj LPOLEOBJECT OleObject from which ONJECTDESCRIPTOR info
+ * is obtained.
+ * lpszSrcOfCopy LPSTR string to identify source of copy.
+ * May be NULL in which case IOleObject::GetMoniker is called
+ * to get the moniker of the object. if the object is loaded
+ * as part of a data transfer document, then usually
+ * lpOleClientSite==NULL is passed to OleLoad when loading
+ * the object. in this case the IOleObject:GetMoniker call
+ * will always fail (it tries to call back to the object's
+ * client site). in this situation a non-NULL lpszSrcOfCopy
+ * parameter should be passed.
+ * dwDrawAspect DWORD Display Aspect of object
+ * pointl POINTL Offset from upper-left corner of object where
+ * mouse went down for drag. Meaningful only when drag-drop
+ * is used.
+ * lpSizelHim SIZEL (optional) If the object is being scaled in its
+ * container, then the container should pass the extents
+ * that it is using to display the object.
+ * May be NULL if the object is NOT being scaled. in this
+ * case, IViewObject2::GetExtent will be called to get the
+ * extents from the object.
+ *
+ * Return Value:
+ * HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
+ */
+
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ LPTSTR lpszSrcOfCopy,
+ DWORD dwDrawAspect,
+ POINTL pointl,
+ LPSIZEL lpSizelHim
+)
+{
+ CLSID clsid;
+ LPTSTR lpszFullUserTypeName = NULL;
+ LPMONIKER lpSrcMonikerOfCopy = NULL;
+ HGLOBAL hObjDesc;
+ IBindCtx FAR *pbc = NULL;
+ HRESULT hrErr;
+ SIZEL sizelHim;
+ BOOL fFreeSrcOfCopy = FALSE;
+ LPOLELINK lpOleLink = (LPOLELINK)
+ OleStdQueryInterface((LPUNKNOWN)lpOleObj,&IID_IOleLink);
+
+#ifdef OLE201
+ LPVIEWOBJECT2 lpViewObj2 = (LPVIEWOBJECT2)
+ OleStdQueryInterface((LPUNKNOWN)lpOleObj, &IID_IViewObject2);
+#endif
+
+ BOOL fIsLink = (lpOleLink ? TRUE : FALSE);
+ TCHAR szLinkedTypeFmt[80];
+ LPTSTR lpszBuf = NULL;
+ DWORD dwStatus = 0;
+
+ // Get CLSID
+ OLEDBG_BEGIN2(TEXT("IOleObject::GetUserClassID called\r\n"))
+ hrErr = lpOleObj->lpVtbl->GetUserClassID(lpOleObj, &clsid);
+ OLEDBG_END2
+ if (hrErr != NOERROR)
+ clsid = CLSID_NULL;
+
+ // Get FullUserTypeName
+ OLEDBG_BEGIN2(TEXT("IOleObject::GetUserType called\r\n"))
+ {
+ LPOLESTR polestr;
+
+ hrErr = lpOleObj->lpVtbl->GetUserType(
+ lpOleObj,
+ USERCLASSTYPE_FULL,
+ &polestr
+ );
+
+ CopyAndFreeOLESTR(polestr, &lpszFullUserTypeName);
+ }
+
+ OLEDBG_END2
+
+// REVIEW: added IDS_OLE2UILINKEDTYPE to strings.rc
+ /* if object is a link, then expand usertypename to be "Linked %s" */
+ if (fIsLink && lpszFullUserTypeName) {
+ if (0 == LoadString(ghInst, IDS_OLE2UIPASTELINKEDTYPE,
+ (LPTSTR)szLinkedTypeFmt, sizeof(szLinkedTypeFmt)/sizeof(TCHAR)))
+ lstrcpy(szLinkedTypeFmt, (LPTSTR) TEXT("Linked %s"));
+ lpszBuf = OleStdMalloc(
+ (lstrlen(lpszFullUserTypeName)+lstrlen(szLinkedTypeFmt)+1) *
+ sizeof(TCHAR));
+ if (lpszBuf) {
+ wsprintf(lpszBuf, szLinkedTypeFmt, lpszFullUserTypeName);
+ OleStdFreeString(lpszFullUserTypeName, NULL);
+ lpszFullUserTypeName = lpszBuf;
+ }
+ }
+
+ /* Get Source Of Copy
+ ** if the object is an embedding, then get the object's moniker
+ ** if the object is a link, then get the link source moniker
+ */
+ if (fIsLink) {
+
+ OLEDBG_BEGIN2(TEXT("IOleLink::GetSourceDisplayName called\r\n"))
+
+ {
+ LPOLESTR polestr;
+
+ hrErr = lpOleLink->lpVtbl->GetSourceDisplayName(
+ lpOleLink, &polestr );
+
+ CopyAndFreeOLESTR(polestr, &lpszSrcOfCopy);
+ }
+ OLEDBG_END2
+ fFreeSrcOfCopy = TRUE;
+
+ } else {
+
+ if (lpszSrcOfCopy == NULL) {
+ OLEDBG_BEGIN2(TEXT("IOleObject::GetMoniker called\r\n"))
+ hrErr = lpOleObj->lpVtbl->GetMoniker(
+ lpOleObj,
+ OLEGETMONIKER_TEMPFORUSER,
+ OLEWHICHMK_OBJFULL,
+ (LPMONIKER FAR*)&lpSrcMonikerOfCopy
+ );
+ OLEDBG_END2
+ if (hrErr == NOERROR)
+ {
+#ifdef OLE201
+ CreateBindCtx(0, (LPBC FAR*)&pbc);
+#endif
+ CallIMonikerGetDisplayNameA(
+ lpSrcMonikerOfCopy, pbc, NULL, &lpszSrcOfCopy);
+
+ pbc->lpVtbl->Release(pbc);
+ fFreeSrcOfCopy = TRUE;
+ }
+ }
+ }
+
+ // Get SIZEL
+ if (lpSizelHim) {
+ // Use extents passed by the caller
+ sizelHim = *lpSizelHim;
+ } else if (lpViewObj2) {
+ // Get the current extents from the object
+ OLEDBG_BEGIN2(TEXT("IViewObject2::GetExtent called\r\n"))
+ hrErr = lpViewObj2->lpVtbl->GetExtent(
+ lpViewObj2,
+ dwDrawAspect,
+ -1, /*lindex*/
+ NULL, /*ptd*/
+ (LPSIZEL)&sizelHim
+ );
+ OLEDBG_END2
+ if (hrErr != NOERROR)
+ sizelHim.cx = sizelHim.cy = 0;
+ } else {
+ sizelHim.cx = sizelHim.cy = 0;
+ }
+
+ // Get DWSTATUS
+ OLEDBG_BEGIN2(TEXT("IOleObject::GetMiscStatus called\r\n"))
+ hrErr = lpOleObj->lpVtbl->GetMiscStatus(
+ lpOleObj,
+ dwDrawAspect,
+ &dwStatus
+ );
+ OLEDBG_END2
+ if (hrErr != NOERROR)
+ dwStatus = 0;
+
+ // Get OBJECTDESCRIPTOR
+ hObjDesc = OleStdGetObjectDescriptorData(
+ clsid,
+ dwDrawAspect,
+ sizelHim,
+ pointl,
+ dwStatus,
+ lpszFullUserTypeName,
+ lpszSrcOfCopy
+ );
+ if (! hObjDesc)
+ goto error;
+
+ // Clean up
+ if (lpszFullUserTypeName)
+ OleStdFreeString(lpszFullUserTypeName, NULL);
+ if (fFreeSrcOfCopy && lpszSrcOfCopy)
+ OleStdFreeString(lpszSrcOfCopy, NULL);
+ if (lpSrcMonikerOfCopy)
+ OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy);
+ if (lpOleLink)
+ OleStdRelease((LPUNKNOWN)lpOleLink);
+ if (lpViewObj2)
+ OleStdRelease((LPUNKNOWN)lpViewObj2);
+
+ return hObjDesc;
+
+error:
+ if (lpszFullUserTypeName)
+ OleStdFreeString(lpszFullUserTypeName, NULL);
+ if (fFreeSrcOfCopy && lpszSrcOfCopy)
+ OleStdFreeString(lpszSrcOfCopy, NULL);
+ if (lpSrcMonikerOfCopy)
+ OleStdRelease((LPUNKNOWN)lpSrcMonikerOfCopy);
+ if (lpOleLink)
+ OleStdRelease((LPUNKNOWN)lpOleLink);
+ if (lpViewObj2)
+ OleStdRelease((LPUNKNOWN)lpViewObj2);
+
+ return NULL;
+}
+
+/*
+ * OleStdFillObjectDescriptorFromData
+ *
+ * Purpose:
+ * Fills and returns a OBJECTDESCRIPTOR structure. The source object will
+ * offer CF_OBJECTDESCRIPTOR if it is an OLE2 object, CF_OWNERLINK if it
+ * is an OLE1 object, or CF_FILENAME if it has been copied to the clipboard
+ * by FileManager.
+ *
+ * Parameters:
+ * lpDataObject LPDATAOBJECT Source object
+ * lpmedium LPSTGMEDIUM Storage medium
+ * lpcfFmt CLIPFORMAT FAR * Format offered by lpDataObject
+ * (OUT parameter)
+ *
+ * Return Value:
+ * HBGLOBAL Handle to OBJECTDESCRIPTOR structure.
+ */
+
+STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData(
+ LPDATAOBJECT lpDataObject,
+ LPSTGMEDIUM lpmedium,
+ CLIPFORMAT FAR* lpcfFmt
+)
+{
+ CLSID clsid;
+ SIZEL sizelHim;
+ POINTL pointl;
+ LPTSTR lpsz, szFullUserTypeName, szSrcOfCopy, szClassName, szDocName, szItemName;
+ int nClassName, nDocName, nItemName, nFullUserTypeName;
+ LPTSTR szBuf = NULL;
+ HGLOBAL hMem = NULL;
+ HKEY hKey = NULL;
+ LPMALLOC pIMalloc = NULL;
+ DWORD dw = OLEUI_CCHKEYMAX_SIZE;
+ HGLOBAL hObjDesc;
+ HRESULT hrErr;
+
+
+ // GetData CF_OBJECTDESCRIPTOR format from the object on the clipboard.
+ // Only OLE 2 objects on the clipboard will offer CF_OBJECTDESCRIPTOR
+ if (hMem = OleStdGetData(
+ lpDataObject,
+ (CLIPFORMAT) cfObjectDescriptor,
+ NULL,
+ DVASPECT_CONTENT,
+ lpmedium))
+ {
+ *lpcfFmt = cfObjectDescriptor;
+ return hMem; // Don't drop to clean up at the end of this function
+ }
+ // If CF_OBJECTDESCRIPTOR is not available, i.e. if this is not an OLE2 object,
+ // check if this is an OLE 1 object. OLE 1 objects will offer CF_OWNERLINK
+ else if (hMem = OleStdGetData(
+ lpDataObject,
+ (CLIPFORMAT) cfOwnerLink,
+ NULL,
+ DVASPECT_CONTENT,
+ lpmedium))
+ {
+ *lpcfFmt = cfOwnerLink;
+ // CF_OWNERLINK contains null-terminated strings for class name, document name
+ // and item name with two null terminating characters at the end
+ szClassName = (LPTSTR)GlobalLock(hMem);
+ nClassName = lstrlen(szClassName);
+ szDocName = szClassName + nClassName + 1;
+ nDocName = lstrlen(szDocName);
+ szItemName = szDocName + nDocName + 1;
+ nItemName = lstrlen(szItemName);
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+ if (hrErr != NOERROR)
+ goto error;
+
+ // Find FullUserTypeName from Registration database using class name
+ if (RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey) != ERROR_SUCCESS)
+ goto error;
+
+ // Allocate space for szFullUserTypeName & szSrcOfCopy. Maximum length of FullUserTypeName
+ // is OLEUI_CCHKEYMAX_SIZE. SrcOfCopy is constructed by concatenating FullUserTypeName, Document
+ // Name and ItemName separated by spaces.
+ szBuf = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc,
+ (DWORD)2*OLEUI_CCHKEYMAX_SIZE+
+ (nDocName+nItemName+4)*sizeof(TCHAR));
+ if (NULL == szBuf)
+ goto error;
+ szFullUserTypeName = szBuf;
+ szSrcOfCopy = szFullUserTypeName+OLEUI_CCHKEYMAX_SIZE+1;
+
+ // Get FullUserTypeName
+ if (RegQueryValue(hKey, NULL, szFullUserTypeName, &dw) != ERROR_SUCCESS)
+ goto error;
+
+ // Build up SrcOfCopy string from FullUserTypeName, DocumentName & ItemName
+ lpsz = szSrcOfCopy;
+ lstrcpy(lpsz, szFullUserTypeName);
+ nFullUserTypeName = lstrlen(szFullUserTypeName);
+ lpsz[nFullUserTypeName]= TEXT(' ');
+ lpsz += nFullUserTypeName+1;
+ lstrcpy(lpsz, szDocName);
+ lpsz[nDocName] = TEXT(' ');
+ lpsz += nDocName+1;
+ lstrcpy(lpsz, szItemName);
+
+ sizelHim.cx = sizelHim.cy = 0;
+ pointl.x = pointl.y = 0;
+
+ CLSIDFromProgIDA(szClassName, &clsid);
+
+ hObjDesc = OleStdGetObjectDescriptorData(
+ clsid,
+ DVASPECT_CONTENT,
+ sizelHim,
+ pointl,
+ 0,
+ szFullUserTypeName,
+ szSrcOfCopy
+ );
+ if (!hObjDesc)
+ goto error;
+ }
+ // Check if object is CF_FILENAME
+ else if (hMem = OleStdGetData(
+ lpDataObject,
+ (CLIPFORMAT) cfFileName,
+ NULL,
+ DVASPECT_CONTENT,
+ lpmedium))
+ {
+ *lpcfFmt = cfFileName;
+ lpsz = (LPTSTR)GlobalLock(hMem);
+
+ hrErr = GetClassFileA(lpsz, &clsid);
+
+ /* OLE2NOTE: if the file does not have an OLE class
+ ** associated, then use the OLE 1 Packager as the class of
+ ** the object to be created. this is the behavior of
+ ** OleCreateFromData API
+ */
+ if (hrErr != NOERROR)
+ CLSIDFromProgIDA("Package", &clsid);
+ sizelHim.cx = sizelHim.cy = 0;
+ pointl.x = pointl.y = 0;
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+ if (hrErr != NOERROR)
+ goto error;
+ szBuf = (LPTSTR)pIMalloc->lpVtbl->Alloc(pIMalloc, (DWORD)OLEUI_CCHKEYMAX_SIZE);
+ if (NULL == szBuf)
+ goto error;
+
+ OleStdGetUserTypeOfClass(&clsid, szBuf, OLEUI_CCHKEYMAX_SIZE, NULL);
+
+ hObjDesc = OleStdGetObjectDescriptorData(
+ clsid,
+ DVASPECT_CONTENT,
+ sizelHim,
+ pointl,
+ 0,
+ szBuf,
+ lpsz
+ );
+ if (!hObjDesc)
+ goto error;
+ }
+ else goto error;
+
+ // Clean up
+ if (szBuf)
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf);
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (hMem)
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ }
+ if (hKey)
+ RegCloseKey(hKey);
+ return hObjDesc;
+
+error:
+ if (szBuf)
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)szBuf);
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (hMem)
+ {
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ }
+ if (hKey)
+ RegCloseKey(hKey);
+ return NULL;
+}
+
+
+#if defined( OBSOLETE )
+
+/*************************************************************************
+** The following API's have been converted into macros:
+** OleStdQueryOleObjectData
+** OleStdQueryLinkSourceData
+** OleStdQueryObjectDescriptorData
+** OleStdQueryFormatMedium
+** OleStdCopyMetafilePict
+** OleStdGetDropEffect
+**
+** These macros are defined in olestd.h
+*************************************************************************/
+
+STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc)
+{
+ if (lpformatetc->tymed & TYMED_ISTORAGE) {
+ return NOERROR;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+}
+
+
+STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc)
+{
+ if (lpformatetc->tymed & TYMED_ISTREAM) {
+ return NOERROR;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+}
+
+
+STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc)
+{
+ if (lpformatetc->tymed & TYMED_HGLOBAL) {
+ return NOERROR;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+}
+
+
+STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed)
+{
+ if (lpformatetc->tymed & tymed) {
+ return NOERROR;
+ } else {
+ return ResultFromScode(DATA_E_FORMATETC);
+ }
+}
+
+
+/*
+ * OleStdCopyMetafilePict()
+ *
+ * Purpose:
+ * Make an independent copy of a MetafilePict
+ * Parameters:
+ *
+ * Return Value:
+ * TRUE if successful, else FALSE.
+ */
+STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout)
+{
+ HANDLE hpictout;
+ LPMETAFILEPICT ppictin, ppictout;
+
+ if (hpictin == NULL || phpictout == NULL) {
+ OleDbgAssert(hpictin == NULL || phpictout == NULL);
+ return FALSE;
+ }
+
+ *phpictout = NULL;
+
+ if ((ppictin = (LPMETAFILEPICT)GlobalLock(hpictin)) == NULL) {
+ return FALSE;
+ }
+
+ hpictout = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT));
+
+ if (hpictout && (ppictout = (LPMETAFILEPICT)GlobalLock(hpictout))){
+ ppictout->hMF = CopyMetaFile(ppictin->hMF, NULL);
+ ppictout->xExt = ppictin->xExt;
+ ppictout->yExt = ppictin->yExt;
+ ppictout->mm = ppictin->mm;
+ GlobalUnlock(hpictout);
+ }
+
+ *phpictout = hpictout;
+
+ return TRUE;
+
+}
+
+
+/* OleStdGetDropEffect
+** -------------------
+**
+** Convert a keyboard state into a DROPEFFECT.
+**
+** returns the DROPEFFECT value derived from the key state.
+** the following is the standard interpretation:
+** no modifier -- Default Drop (NULL is returned)
+** CTRL -- DROPEFFECT_COPY
+** SHIFT -- DROPEFFECT_MOVE
+** CTRL-SHIFT -- DROPEFFECT_LINK
+**
+** Default Drop: this depends on the type of the target application.
+** this is re-interpretable by each target application. a typical
+** interpretation is if the drag is local to the same document
+** (which is source of the drag) then a MOVE operation is
+** performed. if the drag is not local, then a COPY operation is
+** performed.
+*/
+STDAPI_(DWORD) OleStdGetDropEffect( DWORD grfKeyState )
+{
+
+ if (grfKeyState & MK_CONTROL) {
+
+ if (grfKeyState & MK_SHIFT)
+ return DROPEFFECT_LINK;
+ else
+ return DROPEFFECT_COPY;
+
+ } else if (grfKeyState & MK_SHIFT)
+ return DROPEFFECT_MOVE;
+
+ return 0; // no modifier -- do default operation
+}
+#endif // OBSOLETE
+
+
+/*
+ * OleStdGetMetafilePictFromOleObject()
+ *
+ * Purpose:
+ * Generate a MetafilePict by drawing the OLE object.
+ * Parameters:
+ * lpOleObj LPOLEOBJECT pointer to OLE Object
+ * dwDrawAspect DWORD Display Aspect of object
+ * lpSizelHim SIZEL (optional) If the object is being scaled in its
+ * container, then the container should pass the extents
+ * that it is using to display the object.
+ * May be NULL if the object is NOT being scaled. in this
+ * case, IViewObject2::GetExtent will be called to get the
+ * extents from the object.
+ * ptd TARGETDEVICE FAR* (optional) target device to render
+ * metafile for. May be NULL.
+ *
+ * Return Value:
+ * HANDLE -- handle of allocated METAFILEPICT
+ */
+STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ DWORD dwDrawAspect,
+ LPSIZEL lpSizelHim,
+ DVTARGETDEVICE FAR* ptd
+)
+{
+ LPVIEWOBJECT2 lpViewObj2 = NULL;
+ HDC hDC;
+ HMETAFILE hmf;
+ HANDLE hMetaPict;
+ LPMETAFILEPICT lpPict;
+ RECT rcHim;
+ RECTL rclHim;
+ SIZEL sizelHim;
+ HRESULT hrErr;
+ SIZE size;
+ POINT point;
+
+#ifdef OLE201
+ lpViewObj2 = (LPVIEWOBJECT2)OleStdQueryInterface(
+ (LPUNKNOWN)lpOleObj, &IID_IViewObject2);
+#endif
+
+ if (! lpViewObj2)
+ return NULL;
+
+ // Get SIZEL
+ if (lpSizelHim) {
+ // Use extents passed by the caller
+ sizelHim = *lpSizelHim;
+ } else {
+ // Get the current extents from the object
+ OLEDBG_BEGIN2(TEXT("IViewObject2::GetExtent called\r\n"))
+ hrErr = lpViewObj2->lpVtbl->GetExtent(
+ lpViewObj2,
+ dwDrawAspect,
+ -1, /*lindex*/
+ ptd, /*ptd*/
+ (LPSIZEL)&sizelHim
+ );
+ OLEDBG_END2
+ if (hrErr != NOERROR)
+ sizelHim.cx = sizelHim.cy = 0;
+ }
+
+ hDC = CreateMetaFile(NULL);
+
+ rclHim.left = 0;
+ rclHim.top = 0;
+ rclHim.right = sizelHim.cx;
+ rclHim.bottom = sizelHim.cy;
+
+ rcHim.left = (int)rclHim.left;
+ rcHim.top = (int)rclHim.top;
+ rcHim.right = (int)rclHim.right;
+ rcHim.bottom = (int)rclHim.bottom;
+
+ SetWindowOrgEx(hDC, rcHim.left, rcHim.top, &point);
+ SetWindowExtEx(hDC, rcHim.right-rcHim.left, rcHim.bottom-rcHim.top,&size);
+
+ OLEDBG_BEGIN2(TEXT("IViewObject::Draw called\r\n"))
+ hrErr = lpViewObj2->lpVtbl->Draw(
+ lpViewObj2,
+ dwDrawAspect,
+ -1,
+ NULL,
+ ptd,
+ NULL,
+ hDC,
+ (LPRECTL)&rclHim,
+ (LPRECTL)&rclHim,
+ NULL,
+ 0
+ );
+ OLEDBG_END2
+
+ OleStdRelease((LPUNKNOWN)lpViewObj2);
+ if (hrErr != NOERROR) {
+ OleDbgOutHResult(TEXT("IViewObject::Draw returned"), hrErr);
+ }
+
+ hmf = CloseMetaFile(hDC);
+
+ hMetaPict = GlobalAlloc(GHND|GMEM_SHARE, sizeof(METAFILEPICT));
+
+ if (hMetaPict && (lpPict = (LPMETAFILEPICT)GlobalLock(hMetaPict))){
+ lpPict->hMF = hmf;
+ lpPict->xExt = (int)sizelHim.cx ;
+ lpPict->yExt = (int)sizelHim.cy ;
+ lpPict->mm = MM_ANISOTROPIC;
+ GlobalUnlock(hMetaPict);
+ }
+
+ return hMetaPict;
+}
+
+
+/* Call Release on the object that is expected to go away.
+** if the refcnt of the object did no go to 0 then give a debug message.
+*/
+STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPTSTR lpszMsg)
+{
+ ULONG cRef;
+
+ cRef = lpUnk->lpVtbl->Release(lpUnk);
+
+#if defined( _DEBUG )
+ if (cRef != 0) {
+ TCHAR szBuf[80];
+ if (lpszMsg)
+ MessageBox(NULL, lpszMsg, NULL, MB_ICONEXCLAMATION | MB_OK);
+ wsprintf(
+ (LPTSTR)szBuf,
+ TEXT("refcnt (%ld) != 0 after object (0x%lx) release\n"),
+ cRef,
+ lpUnk
+ );
+ if (lpszMsg)
+ OleDbgOut1(lpszMsg);
+ OleDbgOut1((LPTSTR)szBuf);
+ OleDbgAssertSz(cRef == 0, (LPTSTR)szBuf);
+ } else {
+ TCHAR szBuf[80];
+ wsprintf(
+ (LPTSTR)szBuf,
+ TEXT("refcnt = 0 after object (0x%lx) release\n"), lpUnk
+ );
+ OleDbgOut4((LPTSTR)szBuf);
+ }
+#endif
+ return cRef;
+}
+
+
+/* Call Release on the object that is NOT necessarily expected to go away.
+*/
+STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk)
+{
+ ULONG cRef;
+
+ cRef = lpUnk->lpVtbl->Release(lpUnk);
+
+#if defined( _DEBUG )
+ {
+ TCHAR szBuf[80];
+ wsprintf(
+ (LPTSTR)szBuf,
+ TEXT("refcnt = %ld after object (0x%lx) release\n"),
+ cRef,
+ lpUnk
+ );
+ OleDbgOut4((LPTSTR)szBuf);
+ }
+#endif
+ return cRef;
+}
+
+
+/* OleStdInitVtbl
+** --------------
+**
+** Initialize an interface Vtbl to ensure that there are no NULL
+** function pointers in the Vtbl. All entries in the Vtbl are
+** set to a valid funtion pointer (OleStdNullMethod) that issues
+** debug assert message (message box) and returns E_NOTIMPL if called.
+**
+** NOTE: this funtion does not initialize the Vtbl with usefull
+** function pointers, only valid function pointers to avoid the
+** horrible run-time crash when a call is made through the Vtbl with
+** a NULL function pointer. this API is only necessary when
+** initializing the Vtbl's in C. C++ guarantees that all interface
+** functions (in C++ terms -- pure virtual functions) are implemented.
+*/
+
+STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl)
+{
+ LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl;
+ UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*);
+ UINT i;
+
+ for (i = 0; i < nMethods; i++) {
+ lpFuncPtrArr[i] = OleStdNullMethod;
+ }
+}
+
+
+/* OleStdCheckVtbl
+** ---------------
+**
+** Check if all entries in the Vtbl are properly initialized with
+** valid function pointers. If any entries are either NULL or
+** OleStdNullMethod, then this function returns FALSE. If compiled
+** for _DEBUG this function reports which function pointers are
+** invalid.
+**
+** RETURNS: TRUE if all entries in Vtbl are valid
+** FALSE otherwise.
+*/
+
+STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPTSTR lpszIface)
+{
+ LPVOID FAR* lpFuncPtrArr = (LPVOID FAR*)lpVtbl;
+ UINT nMethods = nSizeOfVtbl/sizeof(VOID FAR*);
+ UINT i;
+ BOOL fStatus = TRUE;
+ int nChar = 0;
+
+ for (i = 0; i < nMethods; i++) {
+ if (lpFuncPtrArr[i] == NULL || lpFuncPtrArr[i] == OleStdNullMethod) {
+#if defined( _DEBUG )
+ TCHAR szBuf[256];
+ wsprintf(szBuf, TEXT("%s::method# %d NOT valid!"), lpszIface, i);
+ OleDbgOut1((LPTSTR)szBuf);
+#endif
+ fStatus = FALSE;
+ }
+ }
+ return fStatus;
+}
+
+
+/* OleStdNullMethod
+** ----------------
+** Dummy method used by OleStdInitVtbl to initialize an interface
+** Vtbl to ensure that there are no NULL function pointers in the
+** Vtbl. All entries in the Vtbl are set to this function. this
+** function issues a debug assert message (message box) and returns
+** E_NOTIMPL if called. If all is done properly, this function will
+** NEVER be called!
+*/
+STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis)
+{
+ MessageBox(
+ NULL,
+ TEXT("ERROR: INTERFACE METHOD NOT IMPLEMENTED!\r\n"),
+ NULL,
+ MB_SYSTEMMODAL | MB_ICONHAND | MB_OK
+ );
+
+ return ResultFromScode(E_NOTIMPL);
+}
+
+
+
+static BOOL GetFileTimes(LPTSTR lpszFileName, FILETIME FAR* pfiletime)
+{
+#ifdef WIN32
+ WIN32_FIND_DATA fd;
+ HANDLE hFind;
+ hFind = FindFirstFile(lpszFileName,&fd);
+ if (hFind == NULL || hFind == INVALID_HANDLE_VALUE) {
+ return FALSE;
+ }
+ FindClose(hFind);
+ *pfiletime = fd.ftLastWriteTime;
+ return TRUE;
+#else // !Win32
+ static char sz[256];
+ static struct _find_t fileinfo;
+
+ LSTRCPYN((LPTSTR)sz, lpszFileName, sizeof(sz)-1);
+ sz[sizeof(sz)-1]= TEXT('\0');
+ AnsiToOem(sz, sz);
+ return (_dos_findfirst(sz,_A_NORMAL|_A_HIDDEN|_A_SUBDIR|_A_SYSTEM,
+ (struct _find_t *)&fileinfo) == 0 &&
+ CoDosDateTimeToFileTime(fileinfo.wr_date,fileinfo.wr_time,pfiletime));
+#endif // Win32
+}
+
+
+
+/* OleStdRegisterAsRunning
+** -----------------------
+** Register a moniker in the RunningObjectTable.
+** if there is an existing registration (*lpdwRegister!=NULL), then
+** first revoke that registration.
+**
+** new dwRegister key is returned via *lpdwRegister parameter.
+*/
+STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister)
+{
+ LPRUNNINGOBJECTTABLE lpROT;
+ HRESULT hrErr;
+ DWORD dwOldRegister = *lpdwRegister;
+
+ OLEDBG_BEGIN2(TEXT("OleStdRegisterAsRunning\r\n"))
+
+ OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n"))
+ hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT);
+ OLEDBG_END2
+
+ if (hrErr == NOERROR) {
+
+ /* register as running if a valid moniker is passed
+ **
+ ** OLE2NOTE: we deliberately register the new moniker BEFORE
+ ** revoking the old moniker just in case the object
+ ** currently has no external locks. if the object has no
+ ** locks then revoking it from the running object table will
+ ** cause the object's StubManager to initiate shutdown of
+ ** the object.
+ */
+ if (lpmkFull) {
+
+ OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Register called\r\n"))
+ lpROT->lpVtbl->Register(lpROT, 0, lpUnk,lpmkFull,lpdwRegister);
+ OLEDBG_END2
+
+#if defined(_DEBUG)
+ {
+ TCHAR szBuf[512];
+ LPTSTR lpszDisplay;
+ LPBC lpbc;
+
+#ifdef OLE201
+ CreateBindCtx(0, (LPBC FAR*)&lpbc);
+#endif
+
+ CallIMonikerGetDisplayNameA(
+ lpmkFull,
+ lpbc,
+ NULL,
+ &lpszDisplay
+ );
+ OleStdRelease((LPUNKNOWN)lpbc);
+ wsprintf(
+ szBuf,
+ TEXT("Moniker '%s' REGISTERED as [0x%lx] in ROT\r\n"),
+ lpszDisplay,
+ *lpdwRegister
+ );
+ OleDbgOut2(szBuf);
+ OleStdFreeString(lpszDisplay, NULL);
+ }
+#endif // _DEBUG
+
+ }
+
+ // if already registered, revoke
+ if (dwOldRegister != 0) {
+
+#if defined(_DEBUG)
+ {
+ TCHAR szBuf[512];
+
+ wsprintf(
+ szBuf,
+ TEXT("Moniker [0x%lx] REVOKED from ROT\r\n"),
+ dwOldRegister
+ );
+ OleDbgOut2(szBuf);
+ }
+#endif // _DEBUG
+
+ OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Revoke called\r\n"))
+ lpROT->lpVtbl->Revoke(lpROT, dwOldRegister);
+ OLEDBG_END2
+ }
+
+ OleStdRelease((LPUNKNOWN)lpROT);
+ } else {
+ OleDbgAssertSz(
+ lpROT != NULL,
+ TEXT("OleStdRegisterAsRunning: GetRunningObjectTable FAILED\r\n")
+ );
+ }
+
+ OLEDBG_END2
+}
+
+
+
+/* OleStdRevokeAsRunning
+** ---------------------
+** Revoke a moniker from the RunningObjectTable if there is an
+** existing registration (*lpdwRegister!=NULL).
+**
+** *lpdwRegister parameter will be set to NULL.
+*/
+STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister)
+{
+ LPRUNNINGOBJECTTABLE lpROT;
+ HRESULT hrErr;
+
+ OLEDBG_BEGIN2(TEXT("OleStdRevokeAsRunning\r\n"))
+
+ // if still registered, then revoke
+ if (*lpdwRegister != 0) {
+
+ OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n"))
+ hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT);
+ OLEDBG_END2
+
+ if (hrErr == NOERROR) {
+
+#if defined(_DEBUG)
+ {
+ TCHAR szBuf[512];
+
+ wsprintf(
+ szBuf,
+ TEXT("Moniker [0x%lx] REVOKED from ROT\r\n"),
+ *lpdwRegister
+ );
+ OleDbgOut2(szBuf);
+ }
+#endif // _DEBUG
+
+ OLEDBG_BEGIN2(TEXT("IRunningObjectTable::Revoke called\r\n"))
+ lpROT->lpVtbl->Revoke(lpROT, *lpdwRegister);
+ OLEDBG_END2
+
+ *lpdwRegister = 0;
+
+ OleStdRelease((LPUNKNOWN)lpROT);
+ } else {
+ OleDbgAssertSz(
+ lpROT != NULL,
+ TEXT("OleStdRevokeAsRunning: GetRunningObjectTable FAILED\r\n")
+ );
+ }
+ }
+ OLEDBG_END2
+}
+
+
+/* OleStdNoteFileChangeTime
+** ------------------------
+** Note the time a File-Based object has been saved in the
+** RunningObjectTable. These change times are used as the basis for
+** IOleObject::IsUpToDate.
+** It is important to set the time of the file-based object
+** following a save operation to exactly the time of the saved file.
+** this helps IOleObject::IsUpToDate to give the correct answer
+** after a file has been saved.
+*/
+STDAPI_(void) OleStdNoteFileChangeTime(LPTSTR lpszFileName, DWORD dwRegister)
+{
+ if (dwRegister != 0) {
+
+ LPRUNNINGOBJECTTABLE lprot;
+ FILETIME filetime;
+
+ if (GetFileTimes(lpszFileName, &filetime) &&
+ GetRunningObjectTable(0,&lprot) == NOERROR)
+ {
+ lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime );
+ lprot->lpVtbl->Release(lprot);
+
+ OleDbgOut2(TEXT("IRunningObjectTable::NoteChangeTime called\r\n"));
+ }
+ }
+}
+
+
+/* OleStdNoteObjectChangeTime
+** --------------------------
+** Set the last change time of an object that is registered in the
+** RunningObjectTable. These change times are used as the basis for
+** IOleObject::IsUpToDate.
+**
+** every time the object sends out a OnDataChange notification, it
+** should update the Time of last change in the ROT.
+**
+** NOTE: this function set the change time to the current time.
+*/
+STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister)
+{
+ if (dwRegister != 0) {
+
+ LPRUNNINGOBJECTTABLE lprot;
+ FILETIME filetime;
+
+ if (GetRunningObjectTable(0,&lprot) == NOERROR)
+ {
+#ifdef OLE201
+ CoFileTimeNow( &filetime );
+ lprot->lpVtbl->NoteChangeTime( lprot, dwRegister, &filetime );
+#endif
+ lprot->lpVtbl->Release(lprot);
+
+ OleDbgOut2(TEXT("IRunningObjectTable::NoteChangeTime called\r\n"));
+ }
+ }
+}
+
+
+/* OleStdCreateTempFileMoniker
+** ---------------------------
+** return the next available FileMoniker that can be used as the
+** name of an untitled document.
+** the FileMoniker is built of the form:
+** <lpszPrefixString><number>
+** eg. "Outline1", "Outline2", etc.
+**
+** The RunningObjectTable (ROT) is consulted to determine if a
+** FileMoniker is in use. If the name is in use then the number is
+** incremented and the ROT is checked again.
+**
+** Parameters:
+** LPSTR lpszPrefixString - prefix used to build the name
+** UINT FAR* lpuUnique - (IN-OUT) last used number.
+** this number is used to make the
+** name unique. on entry, the input
+** number is incremented. on output,
+** the number used is returned. this
+** number should be passed again
+** unchanged on the next call.
+** LPSTR lpszName - (OUT) buffer used to build string.
+** caller must be sure buffer is large
+** enough to hold the generated string.
+** LPMONIKER FAR* lplpmk - (OUT) next unused FileMoniker
+**
+** Returns:
+** void
+**
+** Comments:
+** This function is similar in spirit to the Windows API
+** CreateTempFileName.
+*/
+STDAPI_(void) OleStdCreateTempFileMoniker(
+ LPTSTR lpszPrefixString,
+ UINT FAR* lpuUnique,
+ LPTSTR lpszName,
+ LPMONIKER FAR* lplpmk
+)
+{
+ LPRUNNINGOBJECTTABLE lpROT = NULL;
+ UINT i = (lpuUnique != NULL ? *lpuUnique : 1);
+ HRESULT hrErr;
+
+ wsprintf(lpszName, TEXT("%s%d"), lpszPrefixString, i++);
+
+ CreateFileMonikerA(lpszName, lplpmk);
+
+
+ OLEDBG_BEGIN2(TEXT("GetRunningObjectTable called\r\n"))
+ hrErr = GetRunningObjectTable(0,(LPRUNNINGOBJECTTABLE FAR*)&lpROT);
+ OLEDBG_END2
+
+ if (hrErr == NOERROR) {
+
+ while (1) {
+ if (! *lplpmk)
+ break; // failed to create FileMoniker
+
+ OLEDBG_BEGIN2(TEXT("IRunningObjectTable::IsRunning called\r\n"))
+ hrErr = lpROT->lpVtbl->IsRunning(lpROT,*lplpmk);
+ OLEDBG_END2
+
+ if (hrErr != NOERROR)
+ break; // the Moniker is NOT running; found unused one!
+
+ OleStdVerifyRelease(
+ (LPUNKNOWN)*lplpmk,
+ TEXT("OleStdCreateTempFileMoniker: Moniker NOT released")
+ );
+
+ wsprintf(lpszName, TEXT("%s%d"), lpszPrefixString, i++);
+ CreateFileMonikerA(lpszName, lplpmk);
+ }
+
+ OleStdRelease((LPUNKNOWN)lpROT);
+ }
+
+ if (lpuUnique != NULL)
+ *lpuUnique = i;
+}
+
+
+/* OleStdGetFirstMoniker
+** ---------------------
+** return the first piece of a moniker.
+**
+** NOTE: if the given moniker is not a generic composite moniker,
+** then an AddRef'ed pointer to the given moniker is returned.
+*/
+STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk)
+{
+ LPMONIKER lpmkFirst = NULL;
+ LPENUMMONIKER lpenumMoniker;
+ DWORD dwMksys;
+ HRESULT hrErr;
+
+ if (! lpmk)
+ return NULL;
+
+ if (lpmk->lpVtbl->IsSystemMoniker(lpmk, (LPDWORD)&dwMksys) == NOERROR
+ && dwMksys == MKSYS_GENERICCOMPOSITE) {
+
+ /* OLE2NOTE: the moniker is a GenericCompositeMoniker.
+ ** enumerate the moniker to pull off the first piece.
+ */
+
+ hrErr = lpmk->lpVtbl->Enum(
+ lpmk,
+ TRUE /* fForward */,
+ (LPENUMMONIKER FAR*)&lpenumMoniker
+ );
+ if (hrErr != NOERROR)
+ return NULL; // ERROR: give up!
+
+ hrErr = lpenumMoniker->lpVtbl->Next(
+ lpenumMoniker,
+ 1,
+ (LPMONIKER FAR*)&lpmkFirst,
+ NULL
+ );
+ lpenumMoniker->lpVtbl->Release(lpenumMoniker);
+ return lpmkFirst;
+
+ } else {
+ /* OLE2NOTE: the moniker is NOT a GenericCompositeMoniker.
+ ** return an AddRef'ed pointer to the input moniker.
+ */
+ lpmk->lpVtbl->AddRef(lpmk);
+ return lpmk;
+ }
+}
+
+
+/* OleStdGetLenFilePrefixOfMoniker
+** -------------------------------
+** if the first piece of the Moniker is a FileMoniker, then return
+** the length of the filename string.
+**
+** lpmk pointer to moniker
+**
+** Returns
+** 0 if moniker does NOT start with a FileMoniker
+** uLen string length of filename prefix of the display name
+** retrieved from the given (lpmk) moniker.
+*/
+STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk)
+{
+ LPMONIKER lpmkFirst = NULL;
+ DWORD dwMksys;
+ LPTSTR lpsz = NULL;
+ LPBC lpbc = NULL;
+ ULONG uLen = 0;
+ HRESULT hrErr;
+
+ if (! lpmk)
+ return 0;
+
+ lpmkFirst = OleStdGetFirstMoniker(lpmk);
+ if (lpmkFirst) {
+ if ( (lpmkFirst->lpVtbl->IsSystemMoniker(
+ lpmkFirst, (LPDWORD)&dwMksys) == NOERROR)
+ && dwMksys == MKSYS_FILEMONIKER) {
+
+#ifdef OLE201
+ hrErr = CreateBindCtx(0, (LPBC FAR*)&lpbc);
+#endif
+ if (hrErr == NOERROR) {
+ hrErr = CallIMonikerGetDisplayNameA(lpmkFirst, lpbc, NULL,
+ &lpsz);
+
+ if (hrErr == NOERROR && lpsz != NULL) {
+ uLen = lstrlen(lpsz);
+ OleStdFreeString(lpsz, NULL);
+ }
+ OleStdRelease((LPUNKNOWN)lpbc);
+ }
+ }
+ lpmkFirst->lpVtbl->Release(lpmkFirst);
+ }
+ return uLen;
+}
+
+
+/* OleStdMkParseDisplayName
+** Parse a string into a Moniker by calling the OLE API
+** MkParseDisplayName. if the original link source class was an OLE1
+** class, then attempt the parsing assuming the same class applies.
+**
+** if the class of the previous link source was an OLE1 class,
+** then first attempt to parse a string that it is qualified
+** with the progID associated with the OLE1 class. this more
+** closely matches the semantics of OLE1 where the class of
+** link sources is not expected to change. prefixing the
+** string with "@<ProgID -- OLE1 class name>!" will force the
+** parsing of the string to assume the file is of that
+** class.
+** NOTE: this trick of prepending the string with "@<ProgID>
+** only works for OLE1 classes.
+**
+** PARAMETERS:
+** REFCLSID rClsid -- original class of link source.
+** CLSID_NULL if class is unknown
+** ... other parameters the same as MkParseDisplayName API ...
+**
+** RETURNS
+** NOERROR if string parsed successfully
+** else error code returned by MkParseDisplayName
+*/
+STDAPI OleStdMkParseDisplayName(
+ REFCLSID rClsid,
+ LPBC lpbc,
+ LPTSTR lpszUserName,
+ ULONG FAR* lpchEaten,
+ LPMONIKER FAR* lplpmk
+)
+{
+ HRESULT hrErr;
+
+ if (!IsEqualCLSID(rClsid,&CLSID_NULL) && CoIsOle1Class(rClsid) &&
+ lpszUserName[0] != '@') {
+ LPTSTR lpszBuf;
+ LPTSTR lpszProgID;
+
+ // Prepend "@<ProgID>!" to the input string
+ ProgIDFromCLSIDA(rClsid, &lpszProgID);
+
+ if (lpszProgID == NULL)
+ goto Cont1;
+ lpszBuf = OleStdMalloc(
+ ((ULONG)lstrlen(lpszUserName)+
+#ifdef UNICODE
+ // OLE in Win32 is always UNICODE
+ wcslen(lpszProgID)
+#else
+ lstrlen(lpszProgID)
+#endif
+ +3)*sizeof(TCHAR));
+ if (lpszBuf == NULL) {
+ if (lpszProgID)
+ OleStdFree(lpszProgID);
+ goto Cont1;
+ }
+
+ wsprintf(lpszBuf, TEXT("@%s!%s"), lpszProgID, lpszUserName);
+
+ OLEDBG_BEGIN2(TEXT("MkParseDisplayName called\r\n"))
+
+ hrErr = MkParseDisplayNameA(lpbc, lpszBuf, lpchEaten, lplpmk);
+
+ OLEDBG_END2
+
+ if (lpszProgID)
+ OleStdFree(lpszProgID);
+ if (lpszBuf)
+ OleStdFree(lpszBuf);
+
+ if (hrErr == NOERROR)
+ return NOERROR;
+ }
+
+Cont1:
+ OLEDBG_BEGIN2(TEXT("MkParseDisplayName called\r\n"))
+
+ hrErr = MkParseDisplayNameA(lpbc, lpszUserName, lpchEaten, lplpmk);
+
+ OLEDBG_END2
+
+ return hrErr;
+}
+
+
+/*
+ * OleStdMarkPasteEntryList
+ *
+ * Purpose:
+ * Mark each entry in the PasteEntryList if its format is available from
+ * the source IDataObject*. the dwScratchSpace field of each PasteEntry
+ * is set to TRUE if available, else FALSE.
+ *
+ * Parameters:
+ * LPOLEUIPASTEENTRY array of PasteEntry structures
+ * int count of elements in PasteEntry array
+ * LPDATAOBJECT source IDataObject* pointer
+ *
+ * Return Value:
+ * none
+ */
+STDAPI_(void) OleStdMarkPasteEntryList(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+)
+{
+ LPENUMFORMATETC lpEnumFmtEtc = NULL;
+ #define FORMATETC_MAX 20
+ FORMATETC rgfmtetc[FORMATETC_MAX];
+ int i;
+ HRESULT hrErr;
+ long j, cFetched;
+
+ // Clear all marks
+ for (i = 0; i < cEntries; i++) {
+ lpPriorityList[i].dwScratchSpace = FALSE;
+
+ if (! lpPriorityList[i].fmtetc.cfFormat) {
+ // caller wants this item always considered available
+ // (by specifying a NULL format)
+ lpPriorityList[i].dwScratchSpace = TRUE;
+ } else if (lpPriorityList[i].fmtetc.cfFormat == cfEmbeddedObject
+ || lpPriorityList[i].fmtetc.cfFormat == cfEmbedSource
+ || lpPriorityList[i].fmtetc.cfFormat == cfFileName) {
+
+ // if there is an OLE object format, then handle it
+ // specially by calling OleQueryCreateFromData. the caller
+ // need only specify one object type format.
+ OLEDBG_BEGIN2(TEXT("OleQueryCreateFromData called\r\n"))
+ hrErr = OleQueryCreateFromData(lpSrcDataObj);
+ OLEDBG_END2
+ if(NOERROR == hrErr) {
+ lpPriorityList[i].dwScratchSpace = TRUE;
+ }
+ } else if (lpPriorityList[i].fmtetc.cfFormat == cfLinkSource) {
+
+ // if there is OLE 2.0 LinkSource format, then handle it
+ // specially by calling OleQueryLinkFromData.
+ OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n"))
+ hrErr = OleQueryLinkFromData(lpSrcDataObj);
+ OLEDBG_END2
+ if(NOERROR == hrErr) {
+ lpPriorityList[i].dwScratchSpace = TRUE;
+ }
+ }
+ }
+
+ OLEDBG_BEGIN2(TEXT("IDataObject::EnumFormatEtc called\r\n"))
+ hrErr = lpSrcDataObj->lpVtbl->EnumFormatEtc(
+ lpSrcDataObj,
+ DATADIR_GET,
+ (LPENUMFORMATETC FAR*)&lpEnumFmtEtc
+ );
+ OLEDBG_END2
+
+ if (hrErr != NOERROR)
+ return; // unable to get format enumerator
+
+ // Enumerate the formats offered by the source
+ // Loop over all formats offered by the source
+ cFetched = 0;
+ _fmemset(rgfmtetc,0,sizeof(rgfmtetc[FORMATETC_MAX]) );
+ if (lpEnumFmtEtc->lpVtbl->Next(
+ lpEnumFmtEtc, FORMATETC_MAX, rgfmtetc, &cFetched) == NOERROR
+ || (cFetched > 0 && cFetched <= FORMATETC_MAX) )
+ {
+
+ for (j = 0; j < cFetched; j++)
+ {
+ for (i = 0; i < cEntries; i++)
+ {
+ if (! lpPriorityList[i].dwScratchSpace &&
+ IsCloseFormatEtc(&rgfmtetc[j], &lpPriorityList[i].fmtetc))
+ {
+ lpPriorityList[i].dwScratchSpace = TRUE;
+ }
+ }
+ }
+ } // endif
+
+ // Clean up
+ if (lpEnumFmtEtc)
+ OleStdRelease((LPUNKNOWN)lpEnumFmtEtc);
+}
+
+
+/* OleStdGetPriorityClipboardFormat
+** --------------------------------
+**
+** Retrieve the first clipboard format in a list for which data
+** exists in the source IDataObject*.
+**
+** Returns -1 if no acceptable match is found.
+** index of first acceptable match in the priority list.
+**
+*/
+STDAPI_(int) OleStdGetPriorityClipboardFormat(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+)
+{
+ int i;
+ int nFmtEtc = -1;
+
+ // Mark all entries that the Source provides
+ OleStdMarkPasteEntryList(lpSrcDataObj, lpPriorityList, cEntries);
+
+ // Loop over the target's priority list of formats
+ for (i = 0; i < cEntries; i++)
+ {
+ if (lpPriorityList[i].dwFlags != OLEUIPASTE_PASTEONLY &&
+ !(lpPriorityList[i].dwFlags & OLEUIPASTE_PASTE))
+ continue;
+
+ // get first marked entry
+ if (lpPriorityList[i].dwScratchSpace) {
+ nFmtEtc = i;
+ break; // Found priority format; DONE
+ }
+ }
+
+ return nFmtEtc;
+}
+
+
+/* OleStdIsDuplicateFormat
+** -----------------------
+** Returns TRUE if the lpFmtEtc->cfFormat is found in the array of
+** FormatEtc structures.
+*/
+STDAPI_(BOOL) OleStdIsDuplicateFormat(
+ LPFORMATETC lpFmtEtc,
+ LPFORMATETC arrFmtEtc,
+ int nFmtEtc
+)
+{
+ int i;
+
+ for (i = 0; i < nFmtEtc; i++) {
+ if (IsEqualFORMATETC((*lpFmtEtc), arrFmtEtc[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* OleStdGetItemToken
+ * ------------------
+ *
+ * LPTSTR lpszSrc - Pointer to a source string
+ * LPTSTR lpszDst - Pointer to destination buffer
+ *
+ * Will copy one token from the lpszSrc buffer to the lpszItem buffer.
+ * It considers all alpha-numeric and white space characters as valid
+ * characters for a token. the first non-valid character delimates the
+ * token.
+ *
+ * returns the number of charaters eaten.
+ */
+STDAPI_(ULONG) OleStdGetItemToken(LPTSTR lpszSrc, LPTSTR lpszDst, int nMaxChars)
+{
+ ULONG chEaten = 0L;
+
+ // skip leading delimeter characters
+ while (*lpszSrc && --nMaxChars > 0
+ && ((*lpszSrc==TEXT('/')) || (*lpszSrc==TEXT('\\')) ||
+ (*lpszSrc==TEXT('!')) || (*lpszSrc==TEXT(':')))) {
+ *lpszSrc++;
+ chEaten++;
+ }
+
+ // Extract token string (up to first delimeter char or EOS)
+ while (*lpszSrc && --nMaxChars > 0
+ && !((*lpszSrc==TEXT('/')) || (*lpszSrc==TEXT('\\')) ||
+ (*lpszSrc==TEXT('!')) || (*lpszSrc==TEXT(':')))) {
+ *lpszDst++ = *lpszSrc++;
+ chEaten++;
+ }
+ *lpszDst = TEXT('\0');
+ return chEaten;
+}
+
+
+/*************************************************************************
+** OleStdCreateRootStorage
+** create a root level Storage given a filename that is compatible
+** to be used by a top-level OLE container. if the filename
+** specifies an existing file, then an error is returned.
+** the root storage (Docfile) that is created by this function
+** is suitable to be used to create child storages for embedings.
+** (CreateChildStorage can be used to create child storages.)
+** NOTE: the root-level storage is opened in transacted mode.
+*************************************************************************/
+
+STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode)
+{
+ HRESULT hr;
+ DWORD grfCreateMode = STGM_READWRITE | STGM_TRANSACTED;
+ DWORD reserved = 0;
+ LPSTORAGE lpRootStg;
+ TCHAR szMsg[64];
+
+ // if temp file is being created, enable delete-on-release
+ if (! lpszStgName)
+ grfCreateMode |= STGM_DELETEONRELEASE;
+
+ hr = StgCreateDocfileA(
+ lpszStgName,
+ grfMode | grfCreateMode,
+ reserved,
+ (LPSTORAGE FAR*)&lpRootStg
+ );
+
+ if (hr == NOERROR)
+ return lpRootStg; // existing file successfully opened
+
+ OleDbgOutHResult(TEXT("StgCreateDocfile returned"), hr);
+
+ if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPTSTR)szMsg, 64))
+ return NULL;
+
+ MessageBox(NULL, (LPTSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK);
+ return NULL;
+}
+
+
+/*************************************************************************
+** OleStdOpenRootStorage
+** open a root level Storage given a filename that is compatible
+** to be used by a top-level OLE container. if the file does not
+** exist then an error is returned.
+** the root storage (Docfile) that is opened by this function
+** is suitable to be used to create child storages for embedings.
+** (CreateChildStorage can be used to create child storages.)
+** NOTE: the root-level storage is opened in transacted mode.
+*************************************************************************/
+
+STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPTSTR lpszStgName, DWORD grfMode)
+{
+ HRESULT hr;
+ DWORD reserved = 0;
+ LPSTORAGE lpRootStg;
+ TCHAR szMsg[64];
+
+ if (lpszStgName) {
+ hr = StgOpenStorageA(
+ lpszStgName,
+ NULL,
+ grfMode | STGM_TRANSACTED,
+ NULL,
+ reserved,
+ (LPSTORAGE FAR*)&lpRootStg
+ );
+
+ if (hr == NOERROR)
+ return lpRootStg; // existing file successfully opened
+
+ OleDbgOutHResult(TEXT("StgOpenStorage returned"), hr);
+ }
+
+ if (0 == LoadString(ghInst, IDS_OLESTDNOOPENFILE, szMsg, 64))
+ return NULL;
+
+ MessageBox(NULL, (LPTSTR)szMsg, NULL,MB_ICONEXCLAMATION | MB_OK);
+ return NULL;
+}
+
+
+/*************************************************************************
+** OpenOrCreateRootStorage
+** open a root level Storage given a filename that is compatible
+** to be used by a top-level OLE container. if the filename
+** specifies an existing file, then it is open, otherwise a new file
+** with the given name is created.
+** the root storage (Docfile) that is created by this function
+** is suitable to be used to create child storages for embedings.
+** (CreateChildStorage can be used to create child storages.)
+** NOTE: the root-level storage is opened in transacted mode.
+*************************************************************************/
+
+STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode)
+{
+ HRESULT hrErr;
+ SCODE sc;
+ DWORD reserved = 0;
+ LPSTORAGE lpRootStg;
+ TCHAR szMsg[64];
+
+ if (lpszStgName) {
+
+ hrErr = StgOpenStorageA(
+ lpszStgName,
+ NULL,
+ grfMode | STGM_READWRITE | STGM_TRANSACTED,
+ NULL,
+ reserved,
+ (LPSTORAGE FAR*)&lpRootStg
+ );
+
+ if (hrErr == NOERROR)
+ return lpRootStg; // existing file successfully opened
+
+ OleDbgOutHResult(TEXT("StgOpenStorage returned"), hrErr);
+ sc = GetScode(hrErr);
+
+ if (sc!=STG_E_FILENOTFOUND && sc!=STG_E_FILEALREADYEXISTS) {
+ return NULL;
+ }
+ }
+
+ /* if file did not already exist, try to create a new one */
+ hrErr = StgCreateDocfileA(
+ lpszStgName,
+ grfMode | STGM_READWRITE | STGM_TRANSACTED,
+ reserved,
+ (LPSTORAGE FAR*)&lpRootStg
+ );
+
+ if (hrErr == NOERROR)
+ return lpRootStg; // existing file successfully opened
+
+ OleDbgOutHResult(TEXT("StgCreateDocfile returned"), hrErr);
+
+ if (0 == LoadString(ghInst, IDS_OLESTDNOCREATEFILE, (LPTSTR)szMsg, 64))
+ return NULL;
+
+ MessageBox(NULL, (LPTSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK);
+ return NULL;
+}
+
+
+/*
+** OleStdCreateChildStorage
+** create a child Storage inside the given lpStg that is compatible
+** to be used by an embedded OLE object. the return value from this
+** function can be passed to OleCreateXXX functions.
+** NOTE: the child storage is opened in transacted mode.
+*/
+STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName)
+{
+ if (lpStg != NULL) {
+ LPSTORAGE lpChildStg;
+ DWORD grfMode = (STGM_READWRITE | STGM_TRANSACTED |
+ STGM_SHARE_EXCLUSIVE);
+ DWORD reserved = 0;
+
+ HRESULT hrErr = CallIStorageCreateStorageA(
+ lpStg,
+ lpszStgName,
+ grfMode,
+ reserved,
+ reserved,
+ (LPSTORAGE FAR*)&lpChildStg
+ );
+
+ if (hrErr == NOERROR)
+ return lpChildStg;
+
+ OleDbgOutHResult(TEXT("lpStg->lpVtbl->CreateStorage returned"), hrErr);
+ }
+ return NULL;
+}
+
+
+/*
+** OleStdOpenChildStorage
+** open a child Storage inside the given lpStg that is compatible
+** to be used by an embedded OLE object. the return value from this
+** function can be passed to OleLoad function.
+** NOTE: the child storage is opened in transacted mode.
+*/
+STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName, DWORD grfMode)
+{
+ LPSTORAGE lpChildStg;
+ LPSTORAGE lpstgPriority = NULL;
+ DWORD reserved = 0;
+ HRESULT hrErr;
+
+ if (lpStg != NULL) {
+
+ hrErr = CallIStorageOpenStorageA(
+ lpStg,
+ lpszStgName,
+ lpstgPriority,
+ grfMode | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE,
+ NULL,
+ reserved,
+ (LPSTORAGE FAR*)&lpChildStg
+ );
+
+ if (hrErr == NOERROR)
+ return lpChildStg;
+
+ OleDbgOutHResult(TEXT("lpStg->lpVtbl->OpenStorage returned"), hrErr);
+ }
+ return NULL;
+}
+
+
+/* OleStdCommitStorage
+** -------------------
+** Commit the changes to the given IStorage*. This routine can be
+** called on either a root-level storage as used by an OLE-Container
+** or by a child storage as used by an embedded object.
+**
+** This routine first attempts to perform this commit in a safe
+** manner. if this fails it then attempts to do the commit in a less
+** robust manner (STGC_OVERWRITE).
+*/
+STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg)
+{
+ HRESULT hrErr;
+
+ // make the changes permanent
+ hrErr = lpStg->lpVtbl->Commit(lpStg, 0);
+
+ if (GetScode(hrErr) == STG_E_MEDIUMFULL) {
+ // try to commit changes in less robust manner.
+ OleDbgOut(TEXT("Warning: commiting with STGC_OVERWRITE specified\n"));
+ hrErr = lpStg->lpVtbl->Commit(lpStg, STGC_OVERWRITE);
+ }
+
+ if (hrErr != NOERROR)
+ {
+ TCHAR szMsg[64];
+
+ if (0 == LoadString(ghInst, IDS_OLESTDDISKFULL, (LPTSTR)szMsg, 64))
+ return FALSE;
+
+ MessageBox(NULL, (LPTSTR)szMsg, NULL, MB_ICONEXCLAMATION | MB_OK);
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+}
+
+
+/* OleStdDestroyAllElements
+** ------------------------
+** Destroy all elements within an open storage. this is subject
+** to the current transaction.
+*/
+STDAPI OleStdDestroyAllElements(LPSTORAGE lpStg)
+{
+ IEnumSTATSTG FAR* lpEnum;
+ STATSTG sstg;
+ HRESULT hrErr;
+
+ hrErr = lpStg->lpVtbl->EnumElements(
+ lpStg, 0, NULL, 0, (IEnumSTATSTG FAR* FAR*)&lpEnum);
+
+ if (hrErr != NOERROR)
+ return hrErr;
+
+ while (1) {
+ if (lpEnum->lpVtbl->Next(lpEnum, 1, &sstg, NULL) != NOERROR)
+ break;
+ lpStg->lpVtbl->DestroyElement(lpStg, sstg.pwcsName);
+ OleStdFree(sstg.pwcsName);
+ }
+ lpEnum->lpVtbl->Release(lpEnum);
+ return NOERROR;
+}
+
+// returns 1 for a close match
+// (all fields match exactly except the tymed which simply overlaps)
+// 0 for no match
+
+int IsCloseFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight)
+{
+ if (pFetcLeft->cfFormat != pFetcRight->cfFormat)
+ return 0;
+ else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd))
+ return 0;
+ if (pFetcLeft->dwAspect != pFetcRight->dwAspect)
+ return 0;
+ return((pFetcLeft->tymed | pFetcRight->tymed) != 0);
+}
+
+
diff --git a/private/oleutest/letest/ole2ui/olestd.h b/private/oleutest/letest/ole2ui/olestd.h
new file mode 100644
index 000000000..7ca92fcbf
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olestd.h
@@ -0,0 +1,852 @@
+/*************************************************************************
+**
+** OLE 2.0 Standard Utilities
+**
+** olestd.h
+**
+** This file contains file contains data structure defintions,
+** function prototypes, constants, etc. for the common OLE 2.0
+** utilities.
+** These utilities include the following:
+** Debuging Assert/Verify macros
+** HIMETRIC conversion routines
+** reference counting debug support
+** OleStd API's for common compound-document app support
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#if !defined( _OLESTD_H_ )
+#define _OLESTD_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING OLESTD.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+#if defined( __TURBOC__ ) || defined( WIN32 )
+#define _based(a)
+#endif
+
+#ifndef RC_INVOKED
+#include <dos.h> // needed for filetime
+#endif /* RC_INVOKED */
+
+#include <commdlg.h> // needed for LPPRINTDLG
+#include <shellapi.h> // needed for HKEY
+
+// String table defines...
+#define IDS_OLESTDNOCREATEFILE 700
+#define IDS_OLESTDNOOPENFILE 701
+#define IDS_OLESTDDISKFULL 702
+
+
+/*
+ * Some C interface declaration stuff
+ */
+
+#if ! defined(__cplusplus)
+typedef struct tagINTERFACEIMPL {
+ IUnknownVtbl FAR* lpVtbl;
+ LPVOID lpBack;
+ int cRef; // interface specific ref count.
+} INTERFACEIMPL, FAR* LPINTERFACEIMPL;
+
+#define INIT_INTERFACEIMPL(lpIFace, pVtbl, pBack) \
+ ((lpIFace)->lpVtbl = pVtbl, \
+ ((LPINTERFACEIMPL)(lpIFace))->lpBack = (LPVOID)pBack, \
+ ((LPINTERFACEIMPL)(lpIFace))->cRef = 0 \
+ )
+
+#if defined( _DEBUG )
+#define OleDbgQueryInterfaceMethod(lpUnk) \
+ ((lpUnk) != NULL ? ((LPINTERFACEIMPL)(lpUnk))->cRef++ : 0)
+#define OleDbgAddRefMethod(lpThis, iface) \
+ ((LPINTERFACEIMPL)(lpThis))->cRef++
+
+#if _DEBUGLEVEL >= 2
+#define OleDbgReleaseMethod(lpThis, iface) \
+ (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \
+ OleDbgOut("\t" iface "* RELEASED (cRef == 0)\r\n"),1 : \
+ (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \
+ ( \
+ DebugBreak(), \
+ OleDbgOut( \
+ "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \
+ ),1 : \
+ 1)
+
+#else // if _DEBUGLEVEL < 2
+#define OleDbgReleaseMethod(lpThis, iface) \
+ (--((LPINTERFACEIMPL)(lpThis))->cRef == 0 ? \
+ 1 : \
+ (((LPINTERFACEIMPL)(lpThis))->cRef < 0) ? \
+ ( \
+ OleDbgOut( \
+ "\tERROR: " iface "* RELEASED TOO MANY TIMES\r\n") \
+ ),1 : \
+ 1)
+
+#endif // if _DEBUGLEVEL < 2
+
+#else // ! defined (_DEBUG)
+
+#define OleDbgQueryInterfaceMethod(lpUnk)
+#define OleDbgAddRefMethod(lpThis, iface)
+#define OleDbgReleaseMethod(lpThis, iface)
+
+#endif // if defined( _DEBUG )
+
+#endif // ! defined(__cplusplus)
+
+/*
+ * Some docfiles stuff
+ */
+
+#define STGM_DFRALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_DENY_WRITE)
+#define STGM_DFALL (STGM_READWRITE | STGM_TRANSACTED | STGM_SHARE_EXCLUSIVE)
+#define STGM_SALL (STGM_READWRITE | STGM_SHARE_EXCLUSIVE)
+
+/*
+ * Some moniker stuff
+ */
+
+// Delimeter used to separate ItemMoniker pieces of a composite moniker
+#if defined( _MAC )
+#define OLESTDDELIM ":"
+#else
+#define OLESTDDELIM TEXT("\\")
+#endif
+
+/*
+ * Some Concurrency stuff
+ */
+
+/* standard Delay (in msec) to wait before retrying an LRPC call.
+** this value is returned from IMessageFilter::RetryRejectedCall
+*/
+#define OLESTDRETRYDELAY (DWORD)5000
+
+/* Cancel the pending outgoing LRPC call.
+** this value is returned from IMessageFilter::RetryRejectedCall
+*/
+#define OLESTDCANCELRETRY (DWORD)-1
+
+/*
+ * Some Icon support stuff.
+ *
+ * The following API's are now OBSOLETE because equivalent API's have been
+ * added to the OLE2.DLL library
+ * GetIconOfFile superceeded by OleGetIconOfFile
+ * GetIconOfClass superceeded by OleGetIconOfClass
+ * OleUIMetafilePictFromIconAndLabel
+ * superceeded by OleMetafilePictFromIconAndLabel
+ *
+ * The following macros are defined for backward compatibility with previous
+ * versions of the OLE2UI library. It is recommended that the new Ole* API's
+ * should be used instead.
+ */
+#define GetIconOfFile(hInst, lpszFileName, fUseFileAsLabel) \
+ OleGetIconOfFileA(lpszFileName, fUseFileAsLabel)
+
+#define GetIconOfClass(hInst, rclsid, lpszLabel, fUseTypeAsLabel) \
+ OleGetIconOfClassA(rclsid, lpszLabel, fUseTypeAsLabel)
+
+#define OleUIMetafilePictFromIconAndLabel(hIcon,pszLabel,pszSourceFile,iIcon)\
+ OleMetafilePictFromIconAndLabelA(hIcon, pszLabel, pszSourceFile, iIcon)
+
+
+/*
+ * Some Clipboard Copy/Paste & Drag/Drop support stuff
+ */
+
+//Macro to set all FormatEtc fields
+#define SETFORMATETC(fe, cf, asp, td, med, li) \
+ ((fe).cfFormat=cf, \
+ (fe).dwAspect=asp, \
+ (fe).ptd=td, \
+ (fe).tymed=med, \
+ (fe).lindex=li)
+
+//Macro to set interesting FormatEtc fields defaulting the others.
+#define SETDEFAULTFORMATETC(fe, cf, med) \
+ ((fe).cfFormat=cf, \
+ (fe).dwAspect=DVASPECT_CONTENT, \
+ (fe).ptd=NULL, \
+ (fe).tymed=med, \
+ (fe).lindex=-1)
+
+// Macro to test if two FormatEtc structures are an exact match
+#define IsEqualFORMATETC(fe1, fe2) \
+ (OleStdCompareFormatEtc(&(fe1), &(fe2))==0)
+
+// Clipboard format strings
+#define CF_EMBEDSOURCE TEXT("Embed Source")
+#define CF_EMBEDDEDOBJECT TEXT("Embedded Object")
+#define CF_LINKSOURCE TEXT("Link Source")
+#define CF_CUSTOMLINKSOURCE TEXT("Custom Link Source")
+#define CF_OBJECTDESCRIPTOR TEXT("Object Descriptor")
+#define CF_LINKSRCDESCRIPTOR TEXT("Link Source Descriptor")
+#define CF_OWNERLINK TEXT("OwnerLink")
+#define CF_FILENAME TEXT("FileName")
+
+#define OleStdQueryOleObjectData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_ISTORAGE) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryLinkSourceData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_ISTREAM) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryObjectDescriptorData(lpformatetc) \
+ (((lpformatetc)->tymed & TYMED_HGLOBAL) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+#define OleStdQueryFormatMedium(lpformatetc, tymd) \
+ (((lpformatetc)->tymed & tymd) ? \
+ NOERROR : ResultFromScode(DV_E_FORMATETC))
+
+// Make an independent copy of a MetafilePict
+#define OleStdCopyMetafilePict(hpictin, phpictout) \
+ (*(phpictout) = OleDuplicateData(hpictin,CF_METAFILEPICT,GHND|GMEM_SHARE))
+
+
+// REVIEW: these need to be added to OLE2.H
+#if !defined( DD_DEFSCROLLINTERVAL )
+#define DD_DEFSCROLLINTERVAL 50
+#endif
+
+#if !defined( DD_DEFDRAGDELAY )
+#define DD_DEFDRAGDELAY 200
+#endif
+
+#if !defined( DD_DEFDRAGMINDIST )
+#define DD_DEFDRAGMINDIST 2
+#endif
+
+
+/* OleStdGetDropEffect
+** -------------------
+**
+** Convert a keyboard state into a DROPEFFECT.
+**
+** returns the DROPEFFECT value derived from the key state.
+** the following is the standard interpretation:
+** no modifier -- Default Drop (NULL is returned)
+** CTRL -- DROPEFFECT_COPY
+** SHIFT -- DROPEFFECT_MOVE
+** CTRL-SHIFT -- DROPEFFECT_LINK
+**
+** Default Drop: this depends on the type of the target application.
+** this is re-interpretable by each target application. a typical
+** interpretation is if the drag is local to the same document
+** (which is source of the drag) then a MOVE operation is
+** performed. if the drag is not local, then a COPY operation is
+** performed.
+*/
+#define OleStdGetDropEffect(grfKeyState) \
+ ( (grfKeyState & MK_CONTROL) ? \
+ ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_LINK : DROPEFFECT_COPY ) : \
+ ( (grfKeyState & MK_SHIFT) ? DROPEFFECT_MOVE : 0 ) )
+
+
+/* The OLEUIPASTEFLAG enumeration is used by the OLEUIPASTEENTRY structure.
+ *
+ * OLEUIPASTE_ENABLEICON If the container does not specify this flag for the entry in the
+ * OLEUIPASTEENTRY array passed as input to OleUIPasteSpecial, the DisplayAsIcon button will be
+ * unchecked and disabled when the the user selects the format that corresponds to the entry.
+ *
+ * OLEUIPASTE_PASTEONLY Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting only.
+ * OLEUIPASTE_PASTE Indicates that the entry in the OLEUIPASTEENTRY array is valid for pasting. It
+ * may also be valid for linking if any of the following linking flags are specified.
+ *
+ * If the entry in the OLEUIPASTEENTRY array is valid for linking, the following flags indicate which link
+ * types are acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values.
+ * These values correspond as follows to the array of link types passed to OleUIPasteSpecial:
+ * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0]
+ * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1]
+ * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2]
+ * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3]
+ * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4]
+ * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5]
+ * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6]
+ * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7]
+ *
+ * where,
+ * UINT arrLinkTypes[8] is an array of registered clipboard formats for linking. A maximium of 8 link
+ * types are allowed.
+ */
+
+typedef enum tagOLEUIPASTEFLAG
+{
+ OLEUIPASTE_ENABLEICON = 2048, // enable display as icon
+ OLEUIPASTE_PASTEONLY = 0,
+ OLEUIPASTE_PASTE = 512,
+ OLEUIPASTE_LINKANYTYPE = 1024,
+ OLEUIPASTE_LINKTYPE1 = 1,
+ OLEUIPASTE_LINKTYPE2 = 2,
+ OLEUIPASTE_LINKTYPE3 = 4,
+ OLEUIPASTE_LINKTYPE4 = 8,
+ OLEUIPASTE_LINKTYPE5 = 16,
+ OLEUIPASTE_LINKTYPE6 = 32,
+ OLEUIPASTE_LINKTYPE7 = 64,
+ OLEUIPASTE_LINKTYPE8 = 128
+} OLEUIPASTEFLAG;
+
+/*
+ * PasteEntry structure
+ * --------------------
+ * An array of OLEUIPASTEENTRY entries is specified for the PasteSpecial dialog
+ * box. Each entry includes a FORMATETC which specifies the formats that are
+ * acceptable, a string that is to represent the format in the dialog's list
+ * box, a string to customize the result text of the dialog and a set of flags
+ * from the OLEUIPASTEFLAG enumeration. The flags indicate if the entry is
+ * valid for pasting only, linking only or both pasting and linking. If the
+ * entry is valid for linking, the flags indicate which link types are
+ * acceptable by OR'ing together the appropriate OLEUIPASTE_LINKTYPE<#> values.
+ * These values correspond to the array of link types as follows:
+ * OLEUIPASTE_LINKTYPE1=arrLinkTypes[0]
+ * OLEUIPASTE_LINKTYPE2=arrLinkTypes[1]
+ * OLEUIPASTE_LINKTYPE3=arrLinkTypes[2]
+ * OLEUIPASTE_LINKTYPE4=arrLinkTypes[3]
+ * OLEUIPASTE_LINKTYPE5=arrLinkTypes[4]
+ * OLEUIPASTE_LINKTYPE6=arrLinkTypes[5]
+ * OLEUIPASTE_LINKTYPE7=arrLinkTypes[6]
+ * OLEUIPASTE_LINKTYPE8=arrLinkTypes[7]
+ * UINT arrLinkTypes[8]; is an array of registered clipboard formats
+ * for linking. A maximium of 8 link types are allowed.
+ */
+
+typedef struct tagOLEUIPASTEENTRY
+{
+ FORMATETC fmtetc; // Format that is acceptable. The paste
+ // dialog checks if this format is
+ // offered by the object on the
+ // clipboard and if so offers it for
+ // selection to the user.
+ LPCTSTR lpstrFormatName; // String that represents the format to the user. Any %s
+ // in this string is replaced by the FullUserTypeName
+ // of the object on the clipboard and the resulting string
+ // is placed in the list box of the dialog. Atmost
+ // one %s is allowed. The presence or absence of %s indicates
+ // if the result text is to indicate that data is
+ // being pasted or that an object that can be activated by
+ // an application is being pasted. If %s is
+ // present, the result-text says that an object is being pasted.
+ // Otherwise it says that data is being pasted.
+ LPCTSTR lpstrResultText; // String to customize the result text of the dialog when
+ // the user selects the format correspoding to this
+ // entry. Any %s in this string is replaced by the the application
+ // name or FullUserTypeName of the object on
+ // the clipboard. Atmost one %s is allowed.
+ DWORD dwFlags; // Values from OLEUIPASTEFLAG enum
+ DWORD dwScratchSpace; // Scratch space available to be used
+ // by routines which loop through an
+ // IEnumFORMATETC* to mark if the
+ // PasteEntry format is available.
+ // this field CAN be left uninitialized.
+} OLEUIPASTEENTRY, *POLEUIPASTEENTRY, FAR *LPOLEUIPASTEENTRY;
+
+#define OLESTDDROP_NONE 0
+#define OLESTDDROP_DEFAULT 1
+#define OLESTDDROP_NONDEFAULT 2
+
+
+/*
+ * Some misc stuff
+ */
+
+#define EMBEDDINGFLAG "Embedding" // Cmd line switch for launching a srvr
+
+#define HIMETRIC_PER_INCH 2540 // number HIMETRIC units per inch
+#define PTS_PER_INCH 72 // number points (font size) per inch
+
+#define MAP_PIX_TO_LOGHIM(x,ppli) MulDiv(HIMETRIC_PER_INCH, (x), (ppli))
+#define MAP_LOGHIM_TO_PIX(x,ppli) MulDiv((ppli), (x), HIMETRIC_PER_INCH)
+
+// Returns TRUE if all fields of the two Rect's are equal, else FALSE.
+#define AreRectsEqual(lprc1, lprc2) \
+ (((lprc1->top == lprc2->top) && \
+ (lprc1->left == lprc2->left) && \
+ (lprc1->right == lprc2->right) && \
+ (lprc1->bottom == lprc2->bottom)) ? TRUE : FALSE)
+
+/* lstrcpyn is defined to be able to handle UNICODE string
+ * The third parameter here is the number of CHARACTERS that are
+ * to be copied.
+ */
+#define LSTRCPYN(lpdst, lpsrc, cch) \
+(\
+ (lpdst)[(cch)-1] = '\0', \
+ (cch>1 ? lstrcpyn(lpdst, lpsrc, (cch)-1) : 0)\
+)
+
+
+/****** DEBUG Stuff *****************************************************/
+
+#ifdef _DEBUG
+
+#if !defined( _DBGTRACE )
+#define _DEBUGLEVEL 2
+#else
+#define _DEBUGLEVEL _DBGTRACE
+#endif
+
+
+#if defined( NOASSERT )
+
+#define OLEDBGASSERTDATA
+#define OleDbgAssert(a)
+#define OleDbgAssertSz(a, b)
+#define OleDbgVerify(a)
+#define OleDbgVerifySz(a, b)
+
+#else // ! NOASSERT
+
+STDAPI FnAssert(LPSTR lpstrExpr, LPSTR lpstrMsg, LPSTR lpstrFileName, UINT iLine);
+
+#define OLEDBGASSERTDATA \
+ static char _based(_segname("_CODE")) _szAssertFile[]= TEXT(__FILE__);
+
+#define OleDbgAssert(a) \
+ (!(a) ? FnAssert(#a, NULL, _szAssertFile, __LINE__) : (HRESULT)1)
+
+#define OleDbgAssertSz(a, b) \
+ (!(a) ? FnAssert(#a, b, _szAssertFile, __LINE__) : (HRESULT)1)
+
+#define OleDbgVerify(a) \
+ OleDbgAssert(a)
+
+#define OleDbgVerifySz(a, b) \
+ OleDbgAssertSz(a, b)
+
+#endif // ! NOASSERT
+
+#ifdef DLL_VER
+#define OLEDBGDATA_MAIN(szPrefix) \
+ TCHAR NEAR g_szDbgPrefix[] = szPrefix; \
+ OLEDBGASSERTDATA
+#define OLEDBGDATA \
+ extern TCHAR NEAR g_szDbgPrefix[]; \
+ OLEDBGASSERTDATA
+#else
+#define OLEDBGDATA_MAIN(szPrefix) \
+ TCHAR g_szDbgPrefix[] = szPrefix; \
+ OLEDBGASSERTDATA
+#define OLEDBGDATA \
+ extern TCHAR g_szDbgPrefix[]; \
+ OLEDBGASSERTDATA
+#endif
+
+#define OLEDBG_BEGIN(lpsz) \
+ OleDbgPrintAlways(g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END \
+ OleDbgPrintAlways(g_szDbgPrefix,TEXT("End\r\n"),-1);
+
+#define OleDbgOut(lpsz) \
+ OleDbgPrintAlways(g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix(lpsz) \
+ OleDbgPrintAlways(TEXT(""),lpsz,0)
+
+#define OleDbgOutRefCnt(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCntAlways(g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect(lpsz,lpRect) \
+ OleDbgPrintRectAlways(g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOutHResult(lpsz,hr) \
+ OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,GetScode(hr))
+
+#define OleDbgOutScode(lpsz,sc) \
+ OleDbgPrintScodeAlways(g_szDbgPrefix,lpsz,sc)
+
+#define OleDbgOut1(lpsz) \
+ OleDbgPrint(1,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix1(lpsz) \
+ OleDbgPrint(1,TEXT(""),lpsz,0)
+
+#define OLEDBG_BEGIN1(lpsz) \
+ OleDbgPrint(1,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END1 \
+ OleDbgPrint(1,g_szDbgPrefix,TEXT("End\r\n"),-1);
+
+#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(1,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect1(lpsz,lpRect) \
+ OleDbgPrintRect(1,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut2(lpsz) \
+ OleDbgPrint(2,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix2(lpsz) \
+ OleDbgPrint(2,TEXT(""),lpsz,0)
+
+#define OLEDBG_BEGIN2(lpsz) \
+ OleDbgPrint(2,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END2 \
+ OleDbgPrint(2,g_szDbgPrefix, TEXT("End\r\n"),-1);
+
+#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(2,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect2(lpsz,lpRect) \
+ OleDbgPrintRect(2,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut3(lpsz) \
+ OleDbgPrint(3,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix3(lpsz) \
+ OleDbgPrint(3,TEXT(""),lpsz,0)
+
+#define OLEDBG_BEGIN3(lpsz) \
+ OleDbgPrint(3,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END3 \
+ OleDbgPrint(3,g_szDbgPrefix,TEXT("End\r\n"),-1);
+
+#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(3,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect3(lpsz,lpRect) \
+ OleDbgPrintRect(3,g_szDbgPrefix,lpsz,lpRect)
+
+#define OleDbgOut4(lpsz) \
+ OleDbgPrint(4,g_szDbgPrefix,lpsz,0)
+
+#define OleDbgOutNoPrefix4(lpsz) \
+ OleDbgPrint(4,TEXT(""),lpsz,0)
+
+#define OLEDBG_BEGIN4(lpsz) \
+ OleDbgPrint(4,g_szDbgPrefix,lpsz,1);
+
+#define OLEDBG_END4 \
+ OleDbgPrint(4,g_szDbgPrefix,TEXT("End\r\n"),-1);
+
+#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt) \
+ OleDbgPrintRefCnt(4,g_szDbgPrefix,lpsz,lpObj,(ULONG)refcnt)
+
+#define OleDbgOutRect4(lpsz,lpRect) \
+ OleDbgPrintRect(4,g_szDbgPrefix,lpsz,lpRect)
+
+#else // !_DEBUG
+
+#define OLEDBGDATA_MAIN(szPrefix)
+#define OLEDBGDATA
+#define OleDbgAssert(a)
+#define OleDbgAssertSz(a, b)
+#define OleDbgVerify(a) (a)
+#define OleDbgVerifySz(a, b) (a)
+#define OleDbgOutHResult(lpsz,hr)
+#define OleDbgOutScode(lpsz,sc)
+#define OLEDBG_BEGIN(lpsz)
+#define OLEDBG_END
+#define OleDbgOut(lpsz)
+#define OleDbgOut1(lpsz)
+#define OleDbgOut2(lpsz)
+#define OleDbgOut3(lpsz)
+#define OleDbgOut4(lpsz)
+#define OleDbgOutNoPrefix(lpsz)
+#define OleDbgOutNoPrefix1(lpsz)
+#define OleDbgOutNoPrefix2(lpsz)
+#define OleDbgOutNoPrefix3(lpsz)
+#define OleDbgOutNoPrefix4(lpsz)
+#define OLEDBG_BEGIN1(lpsz)
+#define OLEDBG_BEGIN2(lpsz)
+#define OLEDBG_BEGIN3(lpsz)
+#define OLEDBG_BEGIN4(lpsz)
+#define OLEDBG_END1
+#define OLEDBG_END2
+#define OLEDBG_END3
+#define OLEDBG_END4
+#define OleDbgOutRefCnt(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt1(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt2(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt3(lpsz,lpObj,refcnt)
+#define OleDbgOutRefCnt4(lpsz,lpObj,refcnt)
+#define OleDbgOutRect(lpsz,lpRect)
+#define OleDbgOutRect1(lpsz,lpRect)
+#define OleDbgOutRect2(lpsz,lpRect)
+#define OleDbgOutRect3(lpsz,lpRect)
+#define OleDbgOutRect4(lpsz,lpRect)
+
+#endif // _DEBUG
+
+
+/*************************************************************************
+** Function prototypes
+*************************************************************************/
+
+
+//OLESTD.C
+STDAPI_(int) SetDCToAnisotropic(HDC hDC, LPRECT lprcPhysical, LPRECT lprcLogical, LPRECT lprcWindowOld, LPRECT lprcViewportOld);
+STDAPI_(int) SetDCToDrawInHimetricRect(HDC, LPRECT, LPRECT, LPRECT, LPRECT);
+STDAPI_(int) ResetOrigDC(HDC, int, LPRECT, LPRECT);
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+STDAPI_(void) XformRectInPixelsToHimetric(HDC, LPRECT, LPRECT);
+STDAPI_(void) XformRectInHimetricToPixels(HDC, LPRECT, LPRECT);
+STDAPI_(void) XformSizeInPixelsToHimetric(HDC, LPSIZEL, LPSIZEL);
+STDAPI_(void) XformSizeInHimetricToPixels(HDC, LPSIZEL, LPSIZEL);
+STDAPI_(int) XformWidthInHimetricToPixels(HDC, int);
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC, int);
+STDAPI_(int) XformHeightInHimetricToPixels(HDC, int);
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC, int);
+
+STDAPI_(void) ParseCmdLine(LPSTR, BOOL FAR *, LPSTR);
+
+STDAPI_(BOOL) OleStdIsOleLink(LPUNKNOWN lpUnk);
+STDAPI_(LPUNKNOWN) OleStdQueryInterface(LPUNKNOWN lpUnk, REFIID riid);
+STDAPI_(LPSTORAGE) OleStdCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdOpenRootStorage(LPTSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdOpenOrCreateRootStorage(LPTSTR lpszStgName, DWORD grfMode);
+STDAPI_(LPSTORAGE) OleStdCreateChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName);
+STDAPI_(LPSTORAGE) OleStdOpenChildStorage(LPSTORAGE lpStg, LPTSTR lpszStgName, DWORD grfMode);
+STDAPI_(BOOL) OleStdCommitStorage(LPSTORAGE lpStg);
+STDAPI OleStdDestroyAllElements(LPSTORAGE lpStg);
+
+STDAPI_(LPSTORAGE) OleStdCreateStorageOnHGlobal(
+ HANDLE hGlobal,
+ BOOL fDeleteOnRelease,
+ DWORD dwgrfMode
+);
+STDAPI_(LPSTORAGE) OleStdCreateTempStorage(BOOL fUseMemory, DWORD grfMode);
+STDAPI OleStdDoConvert(LPSTORAGE lpStg, REFCLSID rClsidNew);
+STDAPI_(BOOL) OleStdGetTreatAsFmtUserType(
+ REFCLSID rClsidApp,
+ LPSTORAGE lpStg,
+ CLSID FAR* lpclsid,
+ CLIPFORMAT FAR* lpcfFmt,
+ LPTSTR FAR* lplpszType
+);
+STDAPI OleStdDoTreatAsClass(LPTSTR lpszUserType, REFCLSID rclsid, REFCLSID rclsidNew);
+STDAPI_(BOOL) OleStdSetupAdvises(LPOLEOBJECT lpOleObject, DWORD dwDrawAspect,
+ LPTSTR lpszContainerApp, LPTSTR lpszContainerObj,
+ LPADVISESINK lpAdviseSink, BOOL fCreate);
+STDAPI OleStdSwitchDisplayAspect(
+ LPOLEOBJECT lpOleObj,
+ LPDWORD lpdwCurAspect,
+ DWORD dwNewAspect,
+ HGLOBAL hMetaPict,
+ BOOL fDeleteOldAspect,
+ BOOL fSetupViewAdvise,
+ LPADVISESINK lpAdviseSink,
+ BOOL FAR* lpfMustUpdate
+);
+STDAPI OleStdSetIconInCache(LPOLEOBJECT lpOleObj, HGLOBAL hMetaPict);
+STDAPI_(HGLOBAL) OleStdGetData(
+ LPDATAOBJECT lpDataObj,
+ CLIPFORMAT cfFormat,
+ DVTARGETDEVICE FAR* lpTargetDevice,
+ DWORD dwAspect,
+ LPSTGMEDIUM lpMedium
+);
+STDAPI_(void) OleStdMarkPasteEntryList(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+);
+STDAPI_(int) OleStdGetPriorityClipboardFormat(
+ LPDATAOBJECT lpSrcDataObj,
+ LPOLEUIPASTEENTRY lpPriorityList,
+ int cEntries
+);
+STDAPI_(BOOL) OleStdIsDuplicateFormat(
+ LPFORMATETC lpFmtEtc,
+ LPFORMATETC arrFmtEtc,
+ int nFmtEtc
+);
+STDAPI_(void) OleStdRegisterAsRunning(LPUNKNOWN lpUnk, LPMONIKER lpmkFull, DWORD FAR* lpdwRegister);
+STDAPI_(void) OleStdRevokeAsRunning(DWORD FAR* lpdwRegister);
+STDAPI_(void) OleStdNoteFileChangeTime(LPTSTR lpszFileName, DWORD dwRegister);
+STDAPI_(void) OleStdNoteObjectChangeTime(DWORD dwRegister);
+STDAPI OleStdGetOleObjectData(
+ LPPERSISTSTORAGE lpPStg,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium,
+ BOOL fUseMemory
+);
+STDAPI OleStdGetLinkSourceData(
+ LPMONIKER lpmk,
+ LPCLSID lpClsID,
+ LPFORMATETC lpformatetc,
+ LPSTGMEDIUM lpMedium
+);
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorData(
+ CLSID clsid,
+ DWORD dwAspect,
+ SIZEL sizel,
+ POINTL pointl,
+ DWORD dwStatus,
+ LPTSTR lpszFullUserTypeName,
+ LPTSTR lpszSrcOfCopy
+);
+STDAPI_(HGLOBAL) OleStdGetObjectDescriptorDataFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ LPTSTR lpszSrcOfCopy,
+ DWORD dwAspect,
+ POINTL pointl,
+ LPSIZEL lpSizelHim
+);
+STDAPI_(HGLOBAL) OleStdFillObjectDescriptorFromData(
+ LPDATAOBJECT lpDataObject,
+ LPSTGMEDIUM lpmedium,
+ CLIPFORMAT FAR* lpcfFmt
+);
+STDAPI_(HANDLE) OleStdGetMetafilePictFromOleObject(
+ LPOLEOBJECT lpOleObj,
+ DWORD dwDrawAspect,
+ LPSIZEL lpSizelHim,
+ DVTARGETDEVICE FAR* ptd
+);
+
+STDAPI_(void) OleStdCreateTempFileMoniker(LPTSTR lpszPrefixString, UINT FAR* lpuUnique, LPTSTR lpszName, LPMONIKER FAR* lplpmk);
+STDAPI_(LPMONIKER) OleStdGetFirstMoniker(LPMONIKER lpmk);
+STDAPI_(ULONG) OleStdGetLenFilePrefixOfMoniker(LPMONIKER lpmk);
+STDAPI OleStdMkParseDisplayName(
+ REFCLSID rClsid,
+ LPBC lpbc,
+ LPTSTR lpszUserName,
+ ULONG FAR* lpchEaten,
+ LPMONIKER FAR* lplpmk
+);
+STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize);
+STDAPI_(LPVOID) OleStdRealloc(LPVOID pmem, ULONG ulSize);
+STDAPI_(void) OleStdFree(LPVOID pmem);
+STDAPI_(ULONG) OleStdGetSize(LPVOID pmem);
+STDAPI_(void) OleStdFreeString(LPTSTR lpsz, LPMALLOC lpMalloc);
+STDAPI_(LPTSTR) OleStdCopyString(LPTSTR lpszSrc, LPMALLOC lpMalloc);
+STDAPI_(ULONG) OleStdGetItemToken(LPTSTR lpszSrc, LPTSTR lpszDst,int nMaxChars);
+
+STDAPI_(UINT) OleStdIconLabelTextOut(HDC hDC,
+ HFONT hFont,
+ int nXStart,
+ int nYStart,
+ UINT fuOptions,
+ RECT FAR * lpRect,
+ LPTSTR lpszString,
+ UINT cchString,
+ int FAR * lpDX);
+
+// registration database query functions
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPTSTR lpszAuxUserType,
+ int cch,
+ HKEY hKey);
+
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid,
+ LPTSTR lpszUserType,
+ UINT cch,
+ HKEY hKey);
+
+STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID, HKEY, DWORD FAR *);
+STDAPI_(CLIPFORMAT) OleStdGetDefaultFileFormatOfClass(
+ REFCLSID rclsid,
+ HKEY hKey
+);
+
+STDAPI_(void) OleStdInitVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl);
+STDMETHODIMP OleStdNullMethod(LPUNKNOWN lpThis);
+STDAPI_(BOOL) OleStdCheckVtbl(LPVOID lpVtbl, UINT nSizeOfVtbl, LPTSTR lpszIface);
+STDAPI_(ULONG) OleStdVerifyRelease(LPUNKNOWN lpUnk, LPTSTR lpszMsg);
+STDAPI_(ULONG) OleStdRelease(LPUNKNOWN lpUnk);
+
+STDAPI_(HDC) OleStdCreateDC(DVTARGETDEVICE FAR* ptd);
+STDAPI_(HDC) OleStdCreateIC(DVTARGETDEVICE FAR* ptd);
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCreateTargetDevice(LPPRINTDLG lpPrintDlg);
+STDAPI_(BOOL) OleStdDeleteTargetDevice(DVTARGETDEVICE FAR* ptd);
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc);
+STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc);
+STDAPI_(int) OleStdCompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight);
+STDAPI_(BOOL) OleStdCompareTargetDevice
+ (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight);
+
+
+STDAPI_(void) OleDbgPrint(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ int nIndent
+);
+STDAPI_(void) OleDbgPrintAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, int nIndent);
+STDAPI_(void) OleDbgSetDbgLevel(int nDbgLvl);
+STDAPI_(int) OleDbgGetDbgLevel( void );
+STDAPI_(void) OleDbgIndent(int n);
+STDAPI_(void) OleDbgPrintRefCnt(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+);
+STDAPI_(void) OleDbgPrintRefCntAlways(
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPVOID lpObj,
+ ULONG refcnt
+);
+STDAPI_(void) OleDbgPrintRect(
+ int nDbgLvl,
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPRECT lpRect
+);
+STDAPI_(void) OleDbgPrintRectAlways(
+ LPTSTR lpszPrefix,
+ LPTSTR lpszMsg,
+ LPRECT lpRect
+);
+STDAPI_(void) OleDbgPrintScodeAlways(LPTSTR lpszPrefix, LPTSTR lpszMsg, SCODE sc);
+
+// debug implementation of the IMalloc interface.
+STDAPI OleStdCreateDbAlloc(ULONG reserved, IMalloc FAR* FAR* ppmalloc);
+
+
+STDAPI_(LPENUMFORMATETC)
+ OleStdEnumFmtEtc_Create(ULONG nCount, LPFORMATETC lpEtc);
+
+STDAPI_(LPENUMSTATDATA)
+ OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStat);
+
+STDAPI_(BOOL)
+ OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc);
+
+STDAPI_(HPALETTE)
+ OleStdCreateStandardPalette(void);
+
+#if defined( OBSOLETE )
+
+/*************************************************************************
+** The following API's have been converted into macros:
+** OleStdQueryOleObjectData
+** OleStdQueryLinkSourceData
+** OleStdQueryObjectDescriptorData
+** OleStdQueryFormatMedium
+** OleStdCopyMetafilePict
+** AreRectsEqual
+** OleStdGetDropEffect
+**
+** These macros are defined above
+*************************************************************************/
+STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2);
+STDAPI_(BOOL) OleStdCopyMetafilePict(HANDLE hpictin, HANDLE FAR* phpictout);
+STDAPI OleStdQueryOleObjectData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryLinkSourceData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryObjectDescriptorData(LPFORMATETC lpformatetc);
+STDAPI OleStdQueryFormatMedium(LPFORMATETC lpformatetc, TYMED tymed);
+STDAPI_(DWORD) OleStdGetDropEffect ( DWORD grfKeyState );
+#endif // OBSOLETE
+
+
+#endif // _OLESTD_H_
+
diff --git a/private/oleutest/letest/ole2ui/olestr.c b/private/oleutest/letest/ole2ui/olestr.c
new file mode 100644
index 000000000..e7e8e93fa
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olestr.c
@@ -0,0 +1,32 @@
+void CopyAndFreeOLESTR(LPOLESTR polestr, char **ppszOut)
+{
+ // See if there is any work
+ if (polestr == NULL)
+ {
+ if (ppszOut != NULL)
+ {
+ // Output string requested so set it to NULL.
+ *ppszOut = NULL;
+ }
+
+ return;
+ }
+
+ // Get the public memory allocator
+
+ if (pszOut)
+ {
+ // Copy of string converted to ANSI is requested
+ }
+
+ // Free the original string
+}
+
+LPOLESTR CreateOLESTR(char *pszIn)
+{
+ // Get the public memory allocator
+
+ // Allocate the string
+
+ // Convert the string
+}
diff --git a/private/oleutest/letest/ole2ui/olestr.h b/private/oleutest/letest/ole2ui/olestr.h
new file mode 100644
index 000000000..a9c282930
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olestr.h
@@ -0,0 +1,21 @@
+#ifndef _OLESTR_H_
+#define _OLESTR_H_
+
+void CopyAndFreeOLESTR(LPOLESTR polestr, char **pszOut);
+
+void CopyAndFreeSTR(LPSTR polestr, LPOLESTR *pszOut);
+
+LPOLESTR CreateOLESTR(const char *pszIn);
+LPSTR CreateSTR(LPCOLESTR pszIn);
+
+#define CREATEOLESTR(x, y) LPOLESTR x = CreateOLESTR(y);
+
+#define CREATESTR(x, y) LPSTR x = CreateSTR(y);
+
+#define FREEOLESTR(x) CopyAndFreeOLESTR(x, NULL);
+
+#define FREESTR(x) CopyAndFreeSTR(x, NULL);
+
+
+
+#endif // _OLESTR_H_
diff --git a/private/oleutest/letest/ole2ui/olethunk.c b/private/oleutest/letest/ole2ui/olethunk.c
new file mode 100644
index 000000000..a69c3102d
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olethunk.c
@@ -0,0 +1,649 @@
+#include <windows.h>
+#include <ole2.h>
+#include "olethunk.h"
+
+STDAPI_(LPVOID) OleStdMalloc(ULONG ulSize);
+
+STDAPI_(void) OleStdFree(LPVOID pmem);
+
+
+STDAPI_(void) CopyAndFreeOLESTR(LPOLESTR polestr, LPSTR *ppszOut)
+{
+ // See if there is any work
+ if (polestr == NULL)
+ {
+ if (ppszOut != NULL)
+ {
+ // Output string requested so set it to NULL.
+ *ppszOut = NULL;
+ }
+
+ return;
+ }
+
+ if (ppszOut)
+ {
+ // Copy of string converted to ANSI is requested
+ int len = wcslen(polestr) + 1;
+ *ppszOut = OleStdMalloc(len);
+
+ if (*ppszOut)
+ {
+ wcstombs(*ppszOut, polestr, len);
+ }
+ }
+
+ // Free the original string
+ OleStdFree(polestr);
+}
+
+
+
+
+STDAPI_(void) CopyAndFreeSTR(LPSTR pstr, LPOLESTR *ppolestrOut)
+{
+ // See if there is any work
+ if (pstr == NULL)
+ {
+ if (ppolestrOut != NULL)
+ {
+ // Output string requested so set it to NULL.
+ *ppolestrOut = NULL;
+ }
+
+ return;
+ }
+
+ if (ppolestrOut)
+ {
+ // Copy of string converted to ANSI is requested
+ int len = strlen(pstr) + 1;
+ *ppolestrOut = OleStdMalloc(len * sizeof(WCHAR));
+
+ if (*ppolestrOut)
+ {
+ mbstowcs(*ppolestrOut, pstr, len);
+ }
+ }
+
+ // Free the original string
+ OleStdFree(pstr);
+}
+
+
+
+STDAPI_(LPOLESTR) CreateOLESTR(LPCSTR pszIn)
+{
+ // Return NULL if there was no string input
+ LPOLESTR polestr = NULL;
+
+ if (pszIn != NULL)
+ {
+ // Calculate size of string to allocate
+ int len = strlen(pszIn) + 1;
+
+ // Allocate the string
+ polestr = (LPOLESTR) OleStdMalloc(len * sizeof(OLECHAR));
+
+ // Convert the string
+ if (polestr)
+ {
+ mbstowcs(polestr, pszIn, len);
+ }
+ }
+
+ return polestr;
+}
+
+
+
+STDAPI_(LPSTR) CreateSTR(LPCOLESTR polestrIn)
+{
+ // Return NULL if there was no string input
+ LPSTR pstr = NULL;
+
+ if (polestrIn != NULL)
+ {
+ // Calculate size of string to allocate
+ int len = wcslen(polestrIn) + 1;
+
+ // Allocate the string
+ pstr = (PSTR) OleStdMalloc(len);
+
+ // Convert the string
+ if (pstr)
+ {
+ wcstombs(pstr, polestrIn, len);
+ }
+ }
+
+ return pstr;
+}
+
+
+
+
+STDAPI_(void) CLSIDFromStringA(LPSTR pszClass, LPCLSID pclsid)
+{
+ CREATEOLESTR(polestr, pszClass)
+
+ CLSIDFromString(polestr, pclsid);
+
+ FREEOLESTR(polestr)
+}
+
+
+
+STDAPI CreateFileMonikerA(LPSTR lpszPathName, LPMONIKER FAR* ppmk)
+{
+ CREATEOLESTR(polestr, lpszPathName)
+
+ HRESULT hr = CreateFileMoniker(polestr, ppmk);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI CreateItemMonikerA(
+ LPSTR lpszDelim,
+ LPSTR lpszItem,
+ LPMONIKER FAR* ppmk)
+{
+ CREATEOLESTR(polestrDelim, lpszDelim)
+ CREATEOLESTR(polestrItem, lpszItem)
+
+ HRESULT hr = CreateItemMoniker(polestrDelim, polestrItem, ppmk);
+
+ FREEOLESTR(polestrDelim)
+ FREEOLESTR(polestrItem)
+
+ return hr;
+}
+
+
+
+STDAPI_(HGLOBAL) OleGetIconOfClassA(
+ REFCLSID rclsid,
+ LPSTR lpszLabel,
+ BOOL fUseTypeAsLabel)
+{
+ CREATEOLESTR(polestr, lpszLabel)
+
+ HGLOBAL hglobal = OleGetIconOfClass(rclsid, polestr, fUseTypeAsLabel);
+
+ FREEOLESTR(polestr)
+
+ return hglobal;
+}
+
+
+
+STDAPI_(HGLOBAL) OleGetIconOfFileA(LPSTR lpszPath, BOOL fUseFileAsLabel)
+{
+ CREATEOLESTR(polestr, lpszPath)
+
+ HGLOBAL hMetaPict = OleGetIconOfFile(polestr, fUseFileAsLabel);
+
+ FREEOLESTR(polestr)
+
+ return hMetaPict;
+}
+
+
+
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabelA(
+ HICON hIcon,
+ LPSTR lpszLabel,
+ LPSTR lpszSourceFile,
+ UINT iIconIndex)
+{
+ CREATEOLESTR(polestrLabel, lpszLabel)
+ CREATEOLESTR(polestrSourceFile, lpszSourceFile)
+
+ HGLOBAL hglobal = OleMetafilePictFromIconAndLabel(hIcon, polestrLabel,
+ polestrSourceFile, iIconIndex);
+
+ FREEOLESTR(polestrLabel)
+ FREEOLESTR(polestrSourceFile)
+
+ return hglobal;
+}
+
+
+
+
+STDAPI GetClassFileA(LPCSTR szFilename, CLSID FAR* pclsid)
+{
+ CREATEOLESTR(polestr, szFilename)
+
+ HRESULT hr = GetClassFile(polestr, pclsid);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI CLSIDFromProgIDA(LPCSTR lpszProgID, LPCLSID lpclsid)
+{
+ CREATEOLESTR(polestr, lpszProgID)
+
+ HRESULT hr = CLSIDFromProgID(polestr, lpclsid);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+STDAPI MkParseDisplayNameA(
+ LPBC pbc,
+ LPSTR szUserName,
+ ULONG FAR * pchEaten,
+ LPMONIKER FAR * ppmk)
+{
+ CREATEOLESTR(polestr, szUserName)
+
+ HRESULT hr = MkParseDisplayName(pbc, polestr, pchEaten, ppmk);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+STDAPI OleCreateLinkToFileA(
+ LPCSTR lpszFileName,
+ REFIID riid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ CREATEOLESTR(polestr, lpszFileName)
+
+ HRESULT hr = OleCreateLinkToFile(polestr, riid, renderopt, lpFormatEtc,
+ pClientSite, pStg, ppvObj);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+STDAPI OleCreateFromFileA(
+ REFCLSID rclsid,
+ LPCSTR lpszFileName,
+ REFIID riid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg,
+ LPVOID FAR* ppvObj)
+{
+ CREATEOLESTR(polestr, lpszFileName)
+
+ HRESULT hr = OleCreateFromFile(rclsid, polestr, riid, renderopt,
+ lpFormatEtc, pClientSite, pStg, ppvObj);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI OleRegGetUserTypeA(
+ REFCLSID clsid,
+ DWORD dwFormOfType,
+ LPSTR FAR* ppszUserType)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = OleRegGetUserType(clsid, dwFormOfType, &polestr);
+
+ CopyAndFreeOLESTR(polestr, ppszUserType);
+
+ return hr;
+}
+
+
+
+STDAPI ProgIDFromCLSIDA(REFCLSID clsid, LPSTR FAR* lplpszProgID)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = ProgIDFromCLSID(clsid, &polestr);
+
+ CopyAndFreeOLESTR(polestr, lplpszProgID);
+
+ return hr;
+}
+
+
+
+STDAPI ReadFmtUserTypeStgA(
+ LPSTORAGE pstg,
+ CLIPFORMAT FAR* pcf,
+ LPSTR FAR* lplpszUserType)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = ReadFmtUserTypeStg(pstg, pcf, &polestr);
+
+ CopyAndFreeOLESTR(polestr, lplpszUserType);
+
+ return hr;
+}
+
+
+
+
+
+
+STDAPI StgCreateDocfileA(
+ LPCSTR lpszName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ HRESULT hr;
+ LPOLESTR polestr = NULL;
+
+ if (lpszName != NULL)
+ {
+ polestr = CreateOLESTR(lpszName);
+ }
+
+ hr = StgCreateDocfile(polestr, grfMode, reserved, ppstgOpen);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+STDAPI StgOpenStorageA(
+ LPCSTR lpszName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen)
+{
+ CREATEOLESTR(polestr, lpszName)
+
+ HRESULT hr = StgOpenStorage(polestr, pstgPriority, grfMode, snbExclude,
+ reserved, ppstgOpen);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI StgSetTimesA(
+ LPSTR lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime)
+{
+ CREATEOLESTR(polestr, lpszName)
+
+ HRESULT hr = StgSetTimes(polestr, pctime, patime, pmtime);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+STDAPI_(void) StringFromCLSIDA(REFCLSID rclsid, LPSTR *lplpszCLSID)
+{
+ LPOLESTR polestr;
+
+ StringFromCLSID(rclsid, &polestr);
+
+ CopyAndFreeOLESTR(polestr, lplpszCLSID);
+}
+
+
+STDAPI WriteFmtUserTypeStgA(
+ LPSTORAGE lpStg,
+ CLIPFORMAT cf,
+ LPSTR lpszUserType)
+{
+ CREATEOLESTR(polestr, lpszUserType)
+
+ HRESULT hr = WriteFmtUserTypeStg(lpStg, cf, polestr);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+
+
+
+STDAPI CallIMonikerGetDisplayNameA(
+ LPMONIKER lpmk,
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ LPSTR *ppszDisplayName)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = lpmk->lpVtbl->GetDisplayName(lpmk, pbc, NULL,
+ &polestr);
+
+ CopyAndFreeOLESTR(polestr, ppszDisplayName);
+
+ return hr;
+}
+
+
+
+STDAPI CallIOleInPlaceUIWindowSetActiveObjectA(
+ IOleInPlaceUIWindow FAR *lpthis,
+ IOleInPlaceActiveObject *pActiveObject,
+ LPCSTR pszObjName)
+{
+ CREATEOLESTR(polestr, pszObjName)
+
+ HRESULT hr = lpthis->lpVtbl->SetActiveObject(lpthis, pActiveObject,
+ polestr);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI CallIOleInPlaceFrameSetStatusTextA(
+ IOleInPlaceFrame *poleinplc,
+ LPCSTR pszStatusText)
+{
+ CREATEOLESTR(polestr, pszStatusText)
+
+ HRESULT hr = poleinplc->lpVtbl->SetStatusText(poleinplc, polestr);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+STDAPI CallIOleLinkGetSourceDisplayNameA(
+ IOleLink FAR *polelink,
+ LPSTR *ppszDisplayName)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = polelink->lpVtbl->GetSourceDisplayName(polelink, &polestr);
+
+ CopyAndFreeOLESTR(polestr, ppszDisplayName);
+
+ return hr;
+}
+
+
+
+STDAPI CallIOleLinkSetSourceDisplayNameA(
+ IOleLink FAR *polelink,
+ LPCSTR pszStatusText)
+{
+ CREATEOLESTR(polestr, pszStatusText)
+
+ HRESULT hr = polelink->lpVtbl->SetSourceDisplayName(polelink, polestr);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+
+
+STDAPI CallIOleObjectGetUserTypeA(
+ LPOLEOBJECT lpOleObject,
+ DWORD dwFormOfType,
+ LPSTR *ppszUserType)
+{
+ LPOLESTR polestr;
+
+ HRESULT hr = lpOleObject->lpVtbl->GetUserType(lpOleObject,
+ dwFormOfType, &polestr);
+
+ CopyAndFreeOLESTR(polestr, ppszUserType);
+
+ return hr;
+}
+
+
+
+STDAPI CallIOleObjectSetHostNamesA(
+ LPOLEOBJECT lpOleObject,
+ LPCSTR szContainerApp,
+ LPCSTR szContainerObj)
+{
+ CREATEOLESTR(polestrApp, szContainerApp)
+ CREATEOLESTR(polestrObj, szContainerObj)
+
+ HRESULT hr = lpOleObject->lpVtbl->SetHostNames(lpOleObject, polestrApp,
+ polestrObj);
+
+ FREEOLESTR(polestrApp)
+ FREEOLESTR(polestrObj)
+
+ return hr;
+}
+
+STDAPI CallIStorageDestroyElementA(
+ LPSTORAGE lpStg,
+ LPSTR pszName)
+{
+ CREATEOLESTR(polestr, pszName)
+
+ HRESULT hr = lpStg->lpVtbl->DestroyElement(lpStg, polestr);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI CallIStorageCreateStorageA(
+ LPSTORAGE lpStg,
+ const char *pszName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ DWORD reserved2,
+ IStorage **ppstg)
+{
+ CREATEOLESTR(polestr, pszName)
+
+ HRESULT hr = lpStg->lpVtbl->CreateStorage(lpStg, polestr, grfMode,
+ dwStgFmt, reserved2, ppstg);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+
+STDAPI CallIStorageOpenStorageA(
+ LPSTORAGE lpStg,
+ const char *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg)
+{
+ CREATEOLESTR(polestr, pszName)
+
+ HRESULT hr = lpStg->lpVtbl->OpenStorage(lpStg, polestr, pstgPriority,
+ grfMode, snbExclude, reserved, ppstg);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+
+STDAPI CallIStorageCreateStreamA(
+ LPSTORAGE lpStg,
+ LPSTR pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ CREATEOLESTR(polestr, pszName)
+
+ HRESULT hr = lpStg->lpVtbl->CreateStream(lpStg, polestr,
+ grfMode, reserved1, reserved2, ppstm);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
+
+STDAPI CallIStorageOpenStreamA(
+ LPSTORAGE lpStg,
+ LPSTR pszName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm)
+{
+ CREATEOLESTR(polestr, pszName)
+
+ HRESULT hr = lpStg->lpVtbl->OpenStream(lpStg, polestr, reserved1,
+ grfMode, reserved2, ppstm);
+
+ FREEOLESTR(polestr)
+
+ return hr;
+}
diff --git a/private/oleutest/letest/ole2ui/olethunk.h b/private/oleutest/letest/ole2ui/olethunk.h
new file mode 100644
index 000000000..ed47a62da
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/olethunk.h
@@ -0,0 +1,193 @@
+#ifndef _OLETHUNK_H_
+#define _OLETHUNK_H_
+
+//
+// String Conversion Helpers
+//
+STDAPI_(void) CopyAndFreeOLESTR(LPOLESTR polestr, char **pszOut);
+
+STDAPI_(void) CopyAndFreeSTR(LPSTR polestr, LPOLESTR *pszOut);
+
+STDAPI_(LPOLESTR) CreateOLESTR(const char *pszIn);
+
+STDAPI_(LPSTR) CreateSTR(LPCOLESTR pszIn);
+
+#define CREATEOLESTR(x, y) LPOLESTR x = CreateOLESTR(y);
+
+#define CREATESTR(x, y) LPSTR x = CreateSTR(y);
+
+#define FREEOLESTR(x) CopyAndFreeOLESTR(x, NULL);
+
+#define FREESTR(x) CopyAndFreeSTR(x, NULL);
+
+//
+// OLE API Thunks
+//
+STDAPI_(void) CLSIDFromStringA(LPSTR pszClass, LPCLSID pclsid);
+
+STDAPI CLSIDFromProgIDA(LPCSTR lpszProgID, LPCLSID lpclsid);
+
+STDAPI CreateFileMonikerA(LPSTR lpszPathName, LPMONIKER FAR* ppmk);
+
+STDAPI CreateItemMonikerA(
+ LPSTR lpszDelim,
+ LPSTR lpszItem,
+ LPMONIKER FAR* ppmk);
+
+STDAPI GetClassFileA(LPCSTR szFilename, CLSID FAR* pclsid);
+
+STDAPI MkParseDisplayNameA(
+ LPBC pbc,
+ LPSTR szUserName,
+ ULONG FAR * pchEaten,
+ LPMONIKER FAR * ppmk);
+
+STDAPI OleCreateFromFileA(
+ REFCLSID rclsid,
+ LPCSTR lpszFileName,
+ REFIID riid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI OleCreateLinkToFileA(
+ LPCSTR lpszFileName,
+ REFIID riid,
+ DWORD renderopt,
+ LPFORMATETC lpFormatEtc,
+ LPOLECLIENTSITE pClientSite,
+ LPSTORAGE pStg,
+ LPVOID FAR* ppvObj);
+
+STDAPI_(HGLOBAL) OleGetIconOfClassA(
+ REFCLSID rclsid,
+ LPSTR lpszLabel,
+ BOOL fUseTypeAsLabel);
+
+STDAPI_(HGLOBAL) OleGetIconOfFileA(LPSTR lpszPath, BOOL fUseFileAsLabel);
+
+STDAPI_(HGLOBAL) OleMetafilePictFromIconAndLabelA(
+ HICON hIcon,
+ LPSTR lpszLabel,
+ LPSTR lpszSourceFile,
+ UINT iIconIndex);
+
+STDAPI OleRegGetUserTypeA(
+ REFCLSID clsid,
+ DWORD dwFormOfType,
+ LPSTR FAR* pszUserType);
+
+STDAPI ProgIDFromCLSIDA(REFCLSID clsid, LPSTR FAR* lplpszProgID);
+
+STDAPI ReadFmtUserTypeStgA(
+ LPSTORAGE pstg,
+ CLIPFORMAT FAR* pcf,
+ LPSTR FAR* lplpszUserType);
+
+STDAPI StgCreateDocfileA(
+ LPCSTR pwcsName,
+ DWORD grfMode,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+
+STDAPI StgOpenStorageA(
+ LPCSTR pwcsName,
+ IStorage FAR *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage FAR * FAR *ppstgOpen);
+
+STDAPI StgSetTimesA(
+ LPSTR lpszName,
+ FILETIME const FAR* pctime,
+ FILETIME const FAR* patime,
+ FILETIME const FAR* pmtime);
+
+
+STDAPI_(void) StringFromCLSIDA(REFCLSID rclsid, LPSTR *lplpszCLSID);
+
+STDAPI WriteFmtUserTypeStgA(
+ LPSTORAGE pstg,
+ CLIPFORMAT cf,
+ LPSTR lpszUserType);
+
+
+
+//
+// Method Thunks
+//
+STDAPI CallIMonikerGetDisplayNameA(
+ LPMONIKER lpmk,
+ IBindCtx *pbc,
+ IMoniker *pmkToLeft,
+ LPSTR *ppszDisplayName);
+
+STDAPI CallIOleLinkGetSourceDisplayNameA(
+ IOleLink FAR *polelink,
+ LPSTR *ppszDisplayName);
+
+STDAPI CallIOleLinkSetSourceDisplayNameA(
+ IOleLink FAR *polelink,
+ LPCSTR pszStatusText);
+
+STDAPI CallIOleInPlaceFrameSetStatusTextA(
+ IOleInPlaceFrame *poleinplc,
+ LPCSTR pszStatusText);
+
+STDAPI CallIOleInPlaceUIWindowSetActiveObjectA(
+ IOleInPlaceUIWindow FAR *lpthis,
+ IOleInPlaceActiveObject *pActiveObject,
+ LPCSTR pszObjName);
+
+STDAPI CallIOleObjectGetUserTypeA(
+ LPOLEOBJECT lpOleObject,
+ DWORD dwFormOfType,
+ LPSTR *pszUserType);
+
+STDAPI CallIOleObjectSetHostNamesA(
+ LPOLEOBJECT lpOleObject,
+ LPCSTR szContainerApp,
+ LPCSTR szContainerObj);
+
+STDAPI CallIStorageCreateStorageA(
+ LPSTORAGE lpStg,
+ const char *pwcsName,
+ DWORD grfMode,
+ DWORD dwStgFmt,
+ DWORD reserved2,
+ IStorage **ppstg);
+
+STDAPI CallIStorageDestroyElementA(
+ LPSTORAGE lpStg,
+ LPSTR pszName);
+
+STDAPI CallIStorageOpenStorageA(
+ LPSTORAGE lpStg,
+ const char *pszName,
+ IStorage *pstgPriority,
+ DWORD grfMode,
+ SNB snbExclude,
+ DWORD reserved,
+ IStorage **ppstg);
+
+STDAPI CallIStorageCreateStreamA(
+ LPSTORAGE lpStg,
+ LPSTR pszName,
+ DWORD grfMode,
+ DWORD reserved1,
+ DWORD reserved2,
+ IStream **ppstm);
+
+STDAPI CallIStorageOpenStreamA(
+ LPSTORAGE lpStg,
+ LPSTR pszName,
+ void *reserved1,
+ DWORD grfMode,
+ DWORD reserved2,
+ IStream **ppstm);
+
+
+#endif // _OLETHUNK_H_
diff --git a/private/oleutest/letest/ole2ui/oleutl.c b/private/oleutest/letest/ole2ui/oleutl.c
new file mode 100644
index 000000000..9c968cefd
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/oleutl.c
@@ -0,0 +1,660 @@
+/*
+ * OLEUTL.C
+ *
+ * Miscellaneous utility functions for OLE 2.0 Applications:
+ *
+ * Function Purpose
+ * -------------------------------------------------------------------
+ * SetDCToDrawInHimetricRect Sets up an HIMETRIC mapping mode in a DC.
+ * ResetOrigDC Performs the opposite of
+ * SetDCToDrawInHimetricRect
+ * XformWidthInPixelsToHimetric Converts an int width into HiMetric units
+ * XformWidthInHimetricToPixels Converts an int width from HiMetric units
+ * XformHeightInPixelsToHimetric Converts an int height into HiMetric units
+ * XformHeightInHimetricToPixels Converts an int height from HiMetric units
+ * XformRectInPixelsToHimetric Converts a rect into HiMetric units
+ * XformRectInHimetricToPixels Converts a rect from HiMetric units
+ * XformSizeInPixelsToHimetric Converts a SIZEL into HiMetric units
+ * XformSizeInHimetricToPixels Converts a SIZEL from HiMetric units
+ * AreRectsEqual Compares to Rect's
+ *
+ * ParseCmdLine Determines if -Embedding exists
+ * OpenOrCreateRootStorage Creates a root docfile for OLE storage
+ * CommitStorage Commits all changes in a docfile
+ * CreateChildStorage Creates child storage in another storage
+ * OpenChildStorage Opens child storage in another storage
+ *
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#define STRICT 1
+#include "ole2ui.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+//Internal function to this module. No need for UNICODE in this function
+static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst);
+
+
+/*
+ * SetDCToAnisotropic
+ *
+ * Purpose:
+ * Setup the correspondence between the rect in device unit (Viewport) and
+ * the rect in logical unit (Window) so that the proper scaling of
+ * coordinate systems will be calculated. set up both the Viewport and
+ * the window as follows:
+ *
+ * 1) ------------------ ( 2
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * 3) ------------------ ( 4
+ *
+ * Origin = P3
+ * X extent = P2x - P3x
+ * Y extent = P2y - P3y
+ *
+ * Parameters:
+ * hDC HDC to affect
+ * lprcPhysical LPRECT containing the physical (device) extents of DC
+ * lprcLogical LPRECT containing the logical extents
+ * lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC
+ * lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC
+ *
+ * Return Value:
+ * int The original mapping mode of the DC.
+ */
+
+STDAPI_(int) SetDCToAnisotropic(
+ HDC hDC,
+ LPRECT lprcPhysical, LPRECT lprcLogical,
+ LPRECT lprcWindowOld, LPRECT lprcViewportOld)
+{
+ int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC);
+
+ SetWindowOrgEx(hDC, lprcLogical->left, lprcLogical->bottom, (LPPOINT)&lprcWindowOld->left);
+ SetWindowExtEx(hDC, (lprcLogical->right-lprcLogical->left), (lprcLogical->top-lprcLogical->bottom), (LPSIZE)&lprcWindowOld->right);
+ SetViewportOrgEx(hDC, lprcPhysical->left, lprcPhysical->bottom, (LPPOINT)&lprcViewportOld->left);
+ SetViewportExtEx(hDC, (lprcPhysical->right-lprcPhysical->left), (lprcPhysical->top-lprcPhysical->bottom), (LPSIZE)&lprcViewportOld->right);
+
+ return nMapModeOld;
+}
+
+
+/*
+ * SetDCToDrawInHimetricRect
+ *
+ * Purpose:
+ * Setup the correspondence between the rect in pixels (Viewport) and
+ * the rect in HIMETRIC (Window) so that the proper scaling of
+ * coordinate systems will be calculated. set up both the Viewport and
+ * the window as follows:
+ *
+ * 1) ------------------ ( 2
+ * | |
+ * | |
+ * | |
+ * | |
+ * | |
+ * 3) ------------------ ( 4
+ *
+ * Origin = P3
+ * X extent = P2x - P3x
+ * Y extent = P2y - P3y
+ *
+ * Parameters:
+ * hDC HDC to affect
+ * lprcPix LPRECT containing the pixel extents of DC
+ * lprcHiMetric LPRECT to receive the himetric extents
+ * lprcWindowOld LPRECT in which to preserve the window for ResetOrigDC
+ * lprcViewportOld LPRECT in which to preserver the viewport for ResetOrigDC
+ *
+ * Return Value:
+ * int The original mapping mode of the DC.
+ */
+STDAPI_(int) SetDCToDrawInHimetricRect(
+ HDC hDC,
+ LPRECT lprcPix, LPRECT lprcHiMetric,
+ LPRECT lprcWindowOld, LPRECT lprcViewportOld)
+ {
+ int nMapModeOld=SetMapMode(hDC, MM_ANISOTROPIC);
+ BOOL fSystemDC =FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ XformRectInPixelsToHimetric(hDC, lprcPix, lprcHiMetric);
+
+ SetWindowOrgEx(hDC, lprcHiMetric->left, lprcHiMetric->bottom, (LPPOINT)&lprcWindowOld->left);
+ SetWindowExtEx(hDC, (lprcHiMetric->right-lprcHiMetric->left), (lprcHiMetric->top-lprcHiMetric->bottom), (LPSIZE)&lprcWindowOld->right);
+ SetViewportOrgEx(hDC, lprcPix->left, lprcPix->bottom, (LPPOINT)&lprcViewportOld->left);
+ SetViewportExtEx(hDC, (lprcPix->right-lprcPix->left), (lprcPix->top-lprcPix->bottom), (LPSIZE)&lprcViewportOld->right);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return nMapModeOld;
+ }
+
+
+
+/*
+ * ResetOrigDC
+ *
+ * Purpose:
+ * Restores a DC set to draw in himetric from SetDCToDrawInHimetricRect.
+ *
+ * Parameters:
+ * hDC HDC to restore
+ * nMapModeOld int original mapping mode of hDC
+ * lprcWindowOld LPRECT filled in SetDCToDrawInHimetricRect
+ * lprcViewportOld LPRECT filled in SetDCToDrawInHimetricRect
+ *
+ * Return Value:
+ * int Same as nMapModeOld.
+ */
+
+STDAPI_(int) ResetOrigDC(
+ HDC hDC, int nMapModeOld,
+ LPRECT lprcWindowOld, LPRECT lprcViewportOld)
+ {
+ POINT pOld;
+
+ SetMapMode(hDC, nMapModeOld);
+
+ SetWindowOrgEx(hDC, lprcWindowOld->left, lprcWindowOld->top, (LPPOINT)&pOld);
+ SetWindowExtEx(hDC, lprcWindowOld->right, lprcWindowOld->bottom, (LPSIZE)&pOld);
+ SetViewportOrgEx(hDC, lprcViewportOld->left, lprcViewportOld->top, (LPPOINT)&pOld);
+ SetViewportExtEx(hDC, lprcViewportOld->right, lprcViewportOld->bottom, (LPSIZE)&pOld);
+
+ return nMapModeOld;
+ }
+
+
+
+/*
+ * XformWidthInPixelsToHimetric
+ * XformWidthInHimetricToPixels
+ * XformHeightInPixelsToHimetric
+ * XformHeightInHimetricToPixels
+ *
+ * Functions to convert an int between a device coordinate system and
+ * logical HiMetric units.
+ *
+ * Parameters:
+ * hDC HDC providing reference to the pixel mapping. If
+ * NULL, a screen DC is used.
+ *
+ * Size Functions:
+ * lpSizeSrc LPSIZEL providing the structure to convert. This
+ * contains pixels in XformSizeInPixelsToHimetric and
+ * logical HiMetric units in the complement function.
+ * lpSizeDst LPSIZEL providing the structure to receive converted
+ * units. This contains pixels in
+ * XformSizeInPixelsToHimetric and logical HiMetric
+ * units in the complement function.
+ *
+ * Width Functions:
+ * iWidth int containing the value to convert.
+ *
+ * Return Value:
+ * Size Functions: None
+ * Width Functions: Converted value of the input parameters.
+ *
+ * NOTE:
+ * When displaying on the screen, Window apps display everything enlarged
+ * from its actual size so that it is easier to read. For example, if an
+ * app wants to display a 1in. horizontal line, that when printed is
+ * actually a 1in. line on the printed page, then it will display the line
+ * on the screen physically larger than 1in. This is described as a line
+ * that is "logically" 1in. along the display width. Windows maintains as
+ * part of the device-specific information about a given display device:
+ * LOGPIXELSX -- no. of pixels per logical in along the display width
+ * LOGPIXELSY -- no. of pixels per logical in along the display height
+ *
+ * The following formula converts a distance in pixels into its equivalent
+ * logical HIMETRIC units:
+ *
+ * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
+ * -------------------------------
+ * PIXELS_PER_LOGICAL_IN
+ *
+ */
+STDAPI_(int) XformWidthInPixelsToHimetric(HDC hDC, int iWidthInPix)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iWidthInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ //We got pixel units, convert them to logical HIMETRIC along the display
+ iWidthInHiMetric = MAP_PIX_TO_LOGHIM(iWidthInPix, iXppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iWidthInHiMetric;
+ }
+
+
+STDAPI_(int) XformWidthInHimetricToPixels(HDC hDC, int iWidthInHiMetric)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iWidthInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+
+ //We got logical HIMETRIC along the display, convert them to pixel units
+ iWidthInPix = MAP_LOGHIM_TO_PIX(iWidthInHiMetric, iXppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iWidthInPix;
+ }
+
+
+STDAPI_(int) XformHeightInPixelsToHimetric(HDC hDC, int iHeightInPix)
+ {
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInHiMetric;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //* We got pixel units, convert them to logical HIMETRIC along the display
+ iHeightInHiMetric = MAP_PIX_TO_LOGHIM(iHeightInPix, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iHeightInHiMetric;
+ }
+
+
+STDAPI_(int) XformHeightInHimetricToPixels(HDC hDC, int iHeightInHiMetric)
+ {
+ int iYppli; //Pixels per logical inch along height
+ int iHeightInPix;
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //* We got logical HIMETRIC along the display, convert them to pixel units
+ iHeightInPix = MAP_LOGHIM_TO_PIX(iHeightInHiMetric, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return iHeightInPix;
+ }
+
+
+
+/*
+ * XformRectInPixelsToHimetric
+ * XformRectInHimetricToPixels
+ *
+ * Purpose:
+ * Convert a rectangle between pixels of a given hDC and HIMETRIC units
+ * as manipulated in OLE. If the hDC is NULL, then a screen DC is used
+ * and assumes the MM_TEXT mapping mode.
+ *
+ * Parameters:
+ * hDC HDC providing reference to the pixel mapping. If
+ * NULL, a screen DC is used.
+ * lprcSrc LPRECT providing the rectangle to convert. This
+ * contains pixels in XformRectInPixelsToHimetric and
+ * logical HiMetric units in the complement function.
+ * lprcDst LPRECT providing the rectangle to receive converted units.
+ * This contains pixels in XformRectInPixelsToHimetric and
+ * logical HiMetric units in the complement function.
+ *
+ * Return Value:
+ * None
+ *
+ * NOTE:
+ * When displaying on the screen, Window apps display everything enlarged
+ * from its actual size so that it is easier to read. For example, if an
+ * app wants to display a 1in. horizontal line, that when printed is
+ * actually a 1in. line on the printed page, then it will display the line
+ * on the screen physically larger than 1in. This is described as a line
+ * that is "logically" 1in. along the display width. Windows maintains as
+ * part of the device-specific information about a given display device:
+ * LOGPIXELSX -- no. of pixels per logical in along the display width
+ * LOGPIXELSY -- no. of pixels per logical in along the display height
+ *
+ * The following formula converts a distance in pixels into its equivalent
+ * logical HIMETRIC units:
+ *
+ * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
+ * -------------------------------
+ * PIXELS_PER_LOGICAL_IN
+ *
+ * Rect in Pixels (MM_TEXT):
+ *
+ * 0---------- X
+ * |
+ * | 1) ------------------ ( 2 P1 = (rc.left, rc.top)
+ * | | | P2 = (rc.right, rc.top)
+ * | | | P3 = (rc.left, rc.bottom)
+ * | | | P4 = (rc.right, rc.bottom)
+ * | |
+ * Y | |
+ * 3) ------------------ ( 4
+ *
+ * NOTE: Origin = (P1x, P1y)
+ * X extent = P4x - P1x
+ * Y extent = P4y - P1y
+ *
+ *
+ * Rect in Himetric (MM_HIMETRIC):
+ *
+ *
+ * 1) ------------------ ( 2 P1 = (rc.left, rc.top)
+ * Y | | P2 = (rc.right, rc.top)
+ * | | P3 = (rc.left, rc.bottom)
+ * | | | P4 = (rc.right, rc.bottom)
+ * | | |
+ * | | |
+ * | 3) ------------------ ( 4
+ * |
+ * 0---------- X
+ *
+ * NOTE: Origin = (P3x, P3y)
+ * X extent = P2x - P3x
+ * Y extent = P2y - P3y
+ *
+ *
+ */
+
+STDAPI_(void) XformRectInPixelsToHimetric(
+ HDC hDC, LPRECT lprcPix, LPRECT lprcHiMetric)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iYppli; //Pixels per logical inch along height
+ int iXextInPix=(lprcPix->right-lprcPix->left);
+ int iYextInPix=(lprcPix->bottom-lprcPix->top);
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //We got pixel units, convert them to logical HIMETRIC along the display
+ lprcHiMetric->right = MAP_PIX_TO_LOGHIM(iXextInPix, iXppli);
+ lprcHiMetric->top = MAP_PIX_TO_LOGHIM(iYextInPix, iYppli);
+
+ lprcHiMetric->left = 0;
+ lprcHiMetric->bottom = 0;
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return;
+ }
+
+
+
+STDAPI_(void) XformRectInHimetricToPixels(
+ HDC hDC, LPRECT lprcHiMetric, LPRECT lprcPix)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iYppli; //Pixels per logical inch along height
+ int iXextInHiMetric=(lprcHiMetric->right-lprcHiMetric->left);
+ int iYextInHiMetric=(lprcHiMetric->bottom-lprcHiMetric->top);
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //We got pixel units, convert them to logical HIMETRIC along the display
+ lprcPix->right = MAP_LOGHIM_TO_PIX(iXextInHiMetric, iXppli);
+ lprcPix->top = MAP_LOGHIM_TO_PIX(iYextInHiMetric, iYppli);
+
+ lprcPix->left = 0;
+ lprcPix->bottom= 0;
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return;
+ }
+
+
+
+
+/*
+ * XformSizeInPixelsToHimetric
+ * XformSizeInHimetricToPixels
+ *
+ * Functions to convert a SIZEL structure (Size functions) or
+ * an int (Width functions) between a device coordinate system and
+ * logical HiMetric units.
+ *
+ * Parameters:
+ * hDC HDC providing reference to the pixel mapping. If
+ * NULL, a screen DC is used.
+ *
+ * Size Functions:
+ * lpSizeSrc LPSIZEL providing the structure to convert. This
+ * contains pixels in XformSizeInPixelsToHimetric and
+ * logical HiMetric units in the complement function.
+ * lpSizeDst LPSIZEL providing the structure to receive converted
+ * units. This contains pixels in
+ * XformSizeInPixelsToHimetric and logical HiMetric
+ * units in the complement function.
+ *
+ * Width Functions:
+ * iWidth int containing the value to convert.
+ *
+ * Return Value:
+ * Size Functions: None
+ * Width Functions: Converted value of the input parameters.
+ *
+ * NOTE:
+ * When displaying on the screen, Window apps display everything enlarged
+ * from its actual size so that it is easier to read. For example, if an
+ * app wants to display a 1in. horizontal line, that when printed is
+ * actually a 1in. line on the printed page, then it will display the line
+ * on the screen physically larger than 1in. This is described as a line
+ * that is "logically" 1in. along the display width. Windows maintains as
+ * part of the device-specific information about a given display device:
+ * LOGPIXELSX -- no. of pixels per logical in along the display width
+ * LOGPIXELSY -- no. of pixels per logical in along the display height
+ *
+ * The following formula converts a distance in pixels into its equivalent
+ * logical HIMETRIC units:
+ *
+ * DistInHiMetric = (HIMETRIC_PER_INCH * DistInPix)
+ * -------------------------------
+ * PIXELS_PER_LOGICAL_IN
+ *
+ */
+
+STDAPI_(void) XformSizeInPixelsToHimetric(
+ HDC hDC, LPSIZEL lpSizeInPix, LPSIZEL lpSizeInHiMetric)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iYppli; //Pixels per logical inch along height
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //We got pixel units, convert them to logical HIMETRIC along the display
+ lpSizeInHiMetric->cx = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cx, iXppli);
+ lpSizeInHiMetric->cy = (long)MAP_PIX_TO_LOGHIM((int)lpSizeInPix->cy, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return;
+ }
+
+
+STDAPI_(void) XformSizeInHimetricToPixels(
+ HDC hDC, LPSIZEL lpSizeInHiMetric, LPSIZEL lpSizeInPix)
+ {
+ int iXppli; //Pixels per logical inch along width
+ int iYppli; //Pixels per logical inch along height
+ BOOL fSystemDC=FALSE;
+
+ if (NULL==hDC || GetDeviceCaps(hDC, LOGPIXELSX) == 0)
+ {
+ hDC=GetDC(NULL);
+ fSystemDC=TRUE;
+ }
+
+ iXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+ iYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+
+ //We got logical HIMETRIC along the display, convert them to pixel units
+ lpSizeInPix->cx = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cx, iXppli);
+ lpSizeInPix->cy = (long)MAP_LOGHIM_TO_PIX((int)lpSizeInHiMetric->cy, iYppli);
+
+ if (fSystemDC)
+ ReleaseDC(NULL, hDC);
+
+ return;
+ }
+
+
+#if defined( OBSOLETE )
+// This function has been converted to a macro
+
+/* AreRectsEqual
+** -------------
+*/
+STDAPI_(BOOL) AreRectsEqual(LPRECT lprc1, LPRECT lprc2)
+{
+ if ((lprc1->top == lprc2->top) &&
+ (lprc1->left == lprc2->left) &&
+ (lprc1->right == lprc2->right) &&
+ (lprc1->bottom == lprc2->bottom))
+ return TRUE;
+
+ return FALSE;
+}
+#endif // OBSOLETE
+
+
+/*
+ * ParseCmdLine
+ *
+ * Parses the Windows command line which was passed to WinMain.
+ * This function determines if the -Embedding switch has been given.
+ *
+ */
+
+STDAPI_(void) ParseCmdLine(
+ LPSTR lpszLine,
+ BOOL FAR* lpfEmbedFlag,
+ LPSTR szFileName)
+{
+ int i=0;
+ CHAR szBuf[256];
+
+ if(lpfEmbedFlag)
+ *lpfEmbedFlag = FALSE;
+ szFileName[0]='\0'; // NULL string
+
+ // skip blanks
+ while(isspace(*lpszLine)) lpszLine++;
+
+ if(!*lpszLine) // No filename or options, so start a fresh document.
+ return;
+
+ // Check for "-Embedding" or "/Embedding" and set fEmbedding.
+ if(lpfEmbedFlag && (*lpszLine == '-' || *lpszLine == '/')) {
+ lpszLine++;
+ lpszLine = GetWord(lpszLine, szBuf);
+ *lpfEmbedFlag = (BOOL) !strcmp(szBuf, EMBEDDINGFLAG);
+ }
+
+ // skip blanks
+ while(isspace(*lpszLine)) lpszLine++;
+
+ // set szFileName to argument
+ while(lpszLine[i]) {
+ szFileName[i]=lpszLine[i];
+ i++;
+ }
+ szFileName[i]='\0';
+}
+
+
+/* GetWord
+ * -------
+ *
+ * LPSTR lpszSrc - Pointer to a source string
+ * LPSTR lpszDst - Pointer to destination buffer
+ *
+ * Will copy one space-terminated or null-terminated word from the source
+ * string to the destination buffer.
+ * returns: pointer to next character following the word.
+ */
+static LPSTR GetWord(LPSTR lpszSrc, LPSTR lpszDst)
+{
+ while (*lpszSrc && !isspace(*lpszSrc))
+ *lpszDst++ = *lpszSrc++;
+
+ *lpszDst = '\0';
+ return lpszSrc;
+}
+
+
+
+
+
diff --git a/private/oleutest/letest/ole2ui/outlui.d32 b/private/oleutest/letest/ole2ui/outlui.d32
new file mode 100644
index 000000000..502d0b598
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/outlui.d32
@@ -0,0 +1,138 @@
+;;
+;; ole2ui.def
+;;
+;; Definition file for ole2ui.dll
+;;
+;; (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
+;;
+;;
+
+CODE MOVEABLE DISCARDABLE
+DATA MOVEABLE SINGLE
+
+HEAPSIZE 16392
+
+EXPORTS WEP @1 RESIDENTNAME
+;;
+;; NOTE: DO NOT PLACE ANY EXPORTS HERE -- USE THE
+;; __export KEYWORD INSTEAD.
+
+SetDCToAnisotropic
+SetDCToDrawInHimetricRect
+ResetOrigDC
+XformRectInPixelsToHimetric
+XformRectInHimetricToPixels
+XformSizeInPixelsToHimetric
+XformSizeInHimetricToPixels
+XformWidthInHimetricToPixels
+XformWidthInPixelsToHimetric
+XformHeightInHimetricToPixels
+XformHeightInPixelsToHimetric
+AreRectsEqual
+ParseCmdLine
+OleStdIsOleLink
+OleStdQueryInterface
+OleStdCreateRootStorage
+OleStdOpenRootStorage
+OleStdOpenOrCreateRootStorage
+OleStdCreateChildStorage
+OleStdOpenChildStorage
+OleStdCommitStorage
+OleStdCreateStorageOnHGlobal
+OleStdCreateTempStorage
+OleStdDoConvert
+OleStdGetTreatAsFmtUserType
+OleStdDoTreatAsClass
+OleStdSetupAdvises
+OleStdSwitchDisplayAspect
+OleStdSetIconInCache
+OleStdGetData
+OleStdMarkPasteEntryList
+OleStdGetPriorityClipboardFormat
+OleStdIsDuplicateFormat
+OleStdRegisterAsRunning
+OleStdRevokeAsRunning
+OleStdNoteFileChangeTime
+OleStdNoteObjectChangeTime
+OleStdGetOleObjectData
+OleStdGetLinkSourceData
+OleStdGetObjectDescriptorData
+OleStdGetObjectDescriptorDataFromOleObject
+OleStdFillObjectDescriptorFromData
+OleStdCopyMetafilePict
+OleStdGetMetafilePictFromOleObject
+OleStdQueryOleObjectData
+OleStdQueryLinkSourceData
+OleStdQueryObjectDescriptorData
+OleStdQueryFormatMedium
+OleStdGetDropEffect
+OleStdCreateTempFileMoniker
+OleStdGetFirstMoniker
+OleStdGetLenFilePrefixOfMoniker
+OleStdMalloc
+OleStdRealloc
+OleStdFree
+OleStdGetSize
+OleStdFreeString
+OleStdCopyString
+OleStdGetItemToken
+OleStdInitVtbl
+OleStdCheckVtbl
+OleStdVerifyRelease
+OleStdRelease
+OleStdCreateDC
+OleStdCreateIC
+OleStdCreateTargetDevice
+OleStdDeleteTargetDevice
+OleStdCopyTargetDevice
+OleStdCopyFormatEtc
+OleDbgPrint
+OleDbgPrintAlways
+OleDbgSetDbgLevel
+OleDbgGetDbgLevel
+OleDbgIndent
+OleDbgPrintRefCnt
+OleDbgPrintRefCntAlways
+OleDbgPrintRect
+OleDbgPrintRectAlways
+OleDbgPrintScodeAlways
+OleUIInitialize
+OleUIUnInitialize
+OleUIAddVerbMenu
+OleUIMetafilePictFromIconAndLabel
+OleUIMetafilePictIconFree
+OleUIMetafilePictIconDraw
+OleUIMetafilePictExtractLabel
+OleUIMetafilePictExtractIcon
+OleUIMetafilePictExtractIconSource
+OleUIInsertObject
+OleUIPasteSpecial
+OleUIEditLinks
+OleUIChangeIcon
+OleUIConvert
+OleUIBusy
+OleUIUpdateLinks
+OleUIDrawHandles
+OleUIDrawShading
+OleUIShowObject
+RegisterHatchWindowClass
+CreateHatchWindow
+GetHatchWidth
+GetHatchRect
+SetHatchRect
+SetHatchWindowSize
+OleUIPromptUser
+OleStdEnumFmtEtc_Create
+GetIconOfFile
+GetIconOfClass
+OleStdGetAuxUserType
+OleStdGetUserTypeOfClass
+OleStdIconLabelTextOut
+OleStdMsgFilter_Create
+OleStdMsgFilter_SetInComingCallStatus
+OleStdMsgFilter_GetInComingCallStatus
+OleStdMsgFilter_EnableBusyDialog
+OleStdMsgFilter_EnableNotRespondingDialog
+OleStdMsgFilter_SetParentWindow
+OleStdGetMiscStatusOfClass
+OleStdGetDefaultFileFormatOfClass
diff --git a/private/oleutest/letest/ole2ui/pastespl.c b/private/oleutest/letest/ole2ui/pastespl.c
new file mode 100644
index 000000000..0cf086cf1
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/pastespl.c
@@ -0,0 +1,1713 @@
+/*
+ * PASTESPL.C
+ *
+ * Implements the OleUIPasteSpecial function which invokes the complete
+ * Paste Special dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Rights Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "pastespl.h"
+#include "common.h"
+#include "utility.h"
+#include "resimage.h"
+#include "iconbox.h"
+#include "geticon.h"
+#include "icon.h"
+#include "regdb.h"
+#include <stdlib.h>
+
+OLEDBGDATA
+
+/*
+ * OleUIPasteSpecial
+ *
+ * Purpose:
+ * Invokes the standard OLE Paste Special dialog box which allows the user
+ * to select the format of the clipboard object to be pasted or paste linked.
+ *
+ * Parameters:
+ * lpPS LPOLEUIPasteSpecial pointing to the in-out structure
+ * for this dialog.
+ *
+ * Return Value:
+ * UINT One of the following codes or one of the standard error codes (OLEUI_ERR_*)
+ * defined in OLE2UI.H, indicating success or error:
+ * OLEUI_OK User selected OK
+ * OLEUI_CANCEL User cancelled the dialog
+ * OLEUI_IOERR_SRCDATAOBJECTINVALID lpSrcDataObject field of OLEUIPASTESPECIAL invalid
+ * OLEUI_IOERR_ARRPASTEENTRIESINVALID arrPasteEntries field of OLEUIPASTESPECIAL invalid
+ * OLEUI_IOERR_ARRLINKTYPESINVALID arrLinkTypes field of OLEUIPASTESPECIAL invalid
+ * OLEUI_PSERR_CLIPBOARDCHANGED Clipboard contents changed while dialog was up
+ */
+
+STDAPI_(UINT) OleUIPasteSpecial(LPOLEUIPASTESPECIAL lpPS)
+{
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lpPS, sizeof(OLEUIPASTESPECIAL)
+ , &hMemDlg);
+
+ if (uRet != OLEUI_SUCCESS)
+ return uRet;
+
+ //Validate PasteSpecial specific fields
+ if (NULL == lpPS->lpSrcDataObj || IsBadReadPtr(lpPS->lpSrcDataObj, sizeof(IDataObject)))
+ uRet = OLEUI_IOERR_SRCDATAOBJECTINVALID;
+ if (NULL == lpPS->arrPasteEntries || IsBadReadPtr(lpPS->arrPasteEntries, sizeof(OLEUIPASTEENTRY)))
+ uRet = OLEUI_IOERR_ARRPASTEENTRIESINVALID;
+ if (NULL != lpPS->arrLinkTypes && IsBadReadPtr(lpPS->arrLinkTypes, sizeof(UINT)))
+ uRet = OLEUI_IOERR_ARRLINKTYPESINVALID;
+
+ if (0!=lpPS->cClsidExclude)
+ {
+ if (NULL!=lpPS->lpClsidExclude && IsBadReadPtr(lpPS->lpClsidExclude
+ , lpPS->cClsidExclude*sizeof(CLSID)))
+ uRet=OLEUI_IOERR_LPCLSIDEXCLUDEINVALID;
+ }
+
+ if (uRet >= OLEUI_ERR_STANDARDMIN)
+ {
+ if (NULL != hMemDlg)
+ FreeResource(hMemDlg);
+ return uRet;
+ }
+
+ //Now that we've validated everything, we can invoke the dialog.
+ uRet = UStandardInvocation(PasteSpecialDialogProc, (LPOLEUISTANDARD)lpPS
+ , hMemDlg, MAKEINTRESOURCE(IDD_PASTESPECIAL));
+
+ /*
+ * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
+ */
+
+ return uRet;
+}
+
+
+/*
+ * PasteSpecialDialogProc
+ *
+ * Purpose:
+ * Implements the OLE Paste Special dialog as invoked through the
+ * OleUIPasteSpecial function.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ */
+
+BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+{
+ LPOLEUIPASTESPECIAL lpOPS;
+ LPPASTESPECIAL lpPS;
+ BOOL fHook=FALSE;
+ HCURSOR hCursorOld;
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ lpPS=(LPPASTESPECIAL)LpvStandardEntry(hDlg, iMsg, wParam, lParam, &fHook);
+
+ //If the hook processed the message, we're done.
+ if (0!=fHook)
+ return fHook;
+
+ // Process help message from Change Icon
+ if (iMsg == uMsgHelp)
+ {
+ PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp, wParam, lParam);
+ return FALSE;
+ }
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ HWND hwndNextViewer;
+
+ // Free the icon/icon-title metafile corresponding to Paste/PasteList option which is not selected
+ if (lpPS->fLink)
+ OleUIMetafilePictIconFree(lpPS->hMetaPictOD);
+ else OleUIMetafilePictIconFree(lpPS->hMetaPictLSD);
+
+ // Free data associated with each list box entry
+ FreeListData(GetDlgItem(hDlg, ID_PS_PASTELIST));
+ FreeListData(GetDlgItem(hDlg, ID_PS_PASTELINKLIST));
+
+ //Free any specific allocations before calling StandardCleanup
+ if (lpPS->hObjDesc) GlobalFree(lpPS->hObjDesc);
+ if (lpPS->hLinkSrcDesc) GlobalFree(lpPS->hLinkSrcDesc);
+ if (lpPS->hBuff) GlobalFree(lpPS->hBuff);
+
+ // Change the clipboard notification chain
+ hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
+ if (hwndNextViewer != HWND_BROADCAST)
+ {
+ SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
+ ChangeClipboardChain(hDlg, hwndNextViewer);
+ }
+ RemoveProp(hDlg, NEXTCBVIEWER);
+
+ StandardCleanup(lpPS, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ hCursorOld = HourGlassOn();
+ FPasteSpecialInit(hDlg, wParam, lParam);
+ HourGlassOff(hCursorOld);
+ return FALSE;
+
+ case WM_DRAWCLIPBOARD:
+ {
+ HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
+ HWND hDlg_ChgIcon;
+
+ if (hwndNextViewer == HWND_BROADCAST)
+ break;
+
+ if (hwndNextViewer)
+ {
+ SendMessage(hwndNextViewer, iMsg, wParam, lParam);
+ // Refresh next viewer in case it got modified
+ // by the SendMessage() (likely if multiple
+ // PasteSpecial dialogs are up simultaneously)
+ hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
+ }
+ SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
+ ChangeClipboardChain(hDlg, hwndNextViewer);
+
+ /* OLE2NOTE: if the ChangeIcon dialog is currently up, then
+ ** we need to defer bringing down PasteSpecial dialog
+ ** until after ChangeIcon dialog returns. if the
+ ** ChangeIcon dialog is NOT up, then we can bring down
+ ** the PasteSpecial dialog immediately.
+ */
+ if ((hDlg_ChgIcon=(HWND)GetProp(hDlg,PROP_HWND_CHGICONDLG))!=NULL)
+ {
+ // ChangeIcon dialog is UP
+ lpPS->fClipboardChanged = TRUE;
+ } else {
+ // ChangeIcon dialog is NOT up
+
+ // Free icon and icon title metafile
+ SendDlgItemMessage(
+ hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
+
+ SendMessage(
+ hDlg, uMsgEndDialog, OLEUI_PSERR_CLIPBOARDCHANGED,0L);
+ }
+ break;
+ }
+
+ case WM_CHANGECBCHAIN:
+ {
+ HWND hwndNextViewer = GetProp(hDlg, NEXTCBVIEWER);
+
+ if (wParam == (WORD)hwndNextViewer)
+ SetProp(hDlg, NEXTCBVIEWER, (hwndNextViewer = (HWND)LOWORD(lParam)));
+ else if (hwndNextViewer && hwndNextViewer != HWND_BROADCAST)
+ SendMessage(hwndNextViewer, iMsg, wParam, lParam);
+ break;
+ }
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case ID_PS_PASTE:
+ FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
+ break;
+
+ case ID_PS_PASTELINK:
+ FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
+ break;
+
+ case ID_PS_DISPLAYLIST:
+ switch (wCode)
+ {
+ case LBN_SELCHANGE:
+ ChangeListSelection(hDlg, lpPS, hWndMsg);
+ break;
+
+ case LBN_DBLCLK:
+ // Same as pressing OK
+ SendCommand(hDlg, IDOK, BN_CLICKED, hWndMsg);
+ break;
+ }
+ break;
+
+ case ID_PS_DISPLAYASICON:
+ ToggleDisplayAsIcon(hDlg, lpPS);
+ break;
+
+ case ID_PS_CHANGEICON:
+ ChangeIcon(hDlg, lpPS);
+ if (lpPS->fClipboardChanged) {
+ // Free icon and icon title metafile
+ SendDlgItemMessage(
+ hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE,0,0L);
+ SendMessage(
+ hDlg, uMsgEndDialog,
+ OLEUI_PSERR_CLIPBOARDCHANGED, 0L);
+ }
+ break;
+
+ case IDOK:
+ {
+ BOOL fDestAspectIcon =
+ ((lpPS->dwFlags & PSF_CHECKDISPLAYASICON) ?
+ TRUE : FALSE);
+ lpOPS = lpPS->lpOPS;
+ // Return current flags
+ lpOPS->dwFlags = lpPS->dwFlags;
+ // Return index of arrPasteEntries[] corresponding to format selected by user
+ lpOPS->nSelectedIndex = lpPS->nSelectedIndex;
+ // Return if user selected Paste or PasteLink
+ lpOPS->fLink = lpPS->fLink;
+
+ /* if user selected same ASPECT as displayed in the
+ ** source, then sizel passed in the
+ ** ObjectDescriptor/LinkSrcDescriptor is
+ ** applicable. otherwise, the sizel does not apply.
+ */
+ if (lpPS->fLink) {
+ if (lpPS->fSrcAspectIconLSD == fDestAspectIcon)
+ lpOPS->sizel = lpPS->sizelLSD;
+ else
+ lpOPS->sizel.cx = lpOPS->sizel.cy = 0;
+ } else {
+ if (lpPS->fSrcAspectIconOD == fDestAspectIcon)
+ lpOPS->sizel = lpPS->sizelOD;
+ else
+ lpOPS->sizel.cx = lpOPS->sizel.cy = 0;
+ }
+ // Return metafile with icon and icon title that the user selected
+ lpOPS->hMetaPict=(HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY,
+ IBXM_IMAGEGET, 0, 0L);
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ break;
+ }
+ case IDCANCEL:
+ // Free icon and icon title metafile
+ SendDlgItemMessage(
+ hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEFREE, 0, 0L);
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+
+ case ID_OLEUIHELP:
+ PostMessage(lpPS->lpOPS->hWndOwner, uMsgHelp,
+ (WPARAM)hDlg, MAKELPARAM(IDD_PASTESPECIAL, 0));
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+
+/*
+ * FPasteSpecialInit
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the Paste Special dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL FPasteSpecialInit(HWND hDlg, WPARAM wParam, LPARAM lParam)
+{
+ LPPASTESPECIAL lpPS;
+ LPOLEUIPASTESPECIAL lpOPS;
+ HFONT hFont;
+ BOOL fPasteAvailable, fPasteLinkAvailable;
+ STGMEDIUM medium;
+ LPOBJECTDESCRIPTOR lpOD;
+ LPLINKSRCDESCRIPTOR lpLSD;
+ int n;
+ CLIPFORMAT cfFormat;
+
+ // Copy the structure at lParam into our instance memory.
+ lpPS = (LPPASTESPECIAL)LpvStandardInit(hDlg, sizeof(PASTESPECIAL), TRUE, &hFont);
+
+ // PvStandardInit sent a termination to us already.
+ if (NULL == lpPS)
+ return FALSE;
+
+ lpOPS=(LPOLEUIPASTESPECIAL)lParam;
+
+ // Copy other information from lpOPS that we might modify.
+ lpPS->lpOPS = lpOPS;
+ lpPS->dwFlags = lpOPS->dwFlags;
+
+ // Initialize user selections in the Paste and PasteLink listboxes
+ lpPS->nPasteListCurSel = 0;
+ lpPS->nPasteLinkListCurSel = 0;
+
+ // If we got a font, send it to the necessary controls.
+ if (NULL!=hFont)
+ {
+ SendDlgItemMessage(hDlg, ID_PS_SOURCETEXT, WM_SETFONT, (WPARAM)hFont, 0L);
+ SendDlgItemMessage(hDlg, ID_PS_RESULTTEXT, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+ // Hide the help button if required
+ if (!(lpPS->lpOPS->dwFlags & PSF_SHOWHELP))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+ // Hide all DisplayAsIcon related controls if it should be disabled
+ if ( lpPS->dwFlags & PSF_DISABLEDISPLAYASICON ) {
+ StandardShowDlgItem(hDlg, ID_PS_DISPLAYASICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
+ }
+
+ // PSF_CHECKDISPLAYASICON is an OUT flag. Clear it if has been set on the way in.
+ lpPS->dwFlags = lpPS->dwFlags & ~PSF_CHECKDISPLAYASICON;
+
+ // Change the caption if required
+ if (NULL != lpOPS->lpszCaption)
+ SetWindowText(hDlg, lpOPS->lpszCaption);
+
+ // Load 'Unknown Source' and 'Unknown Type' strings
+ n = LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpPS->szUnknownType, PS_UNKNOWNSTRLEN);
+ if (n)
+ n = LoadString(ghInst, IDS_PSUNKNOWNSRC, lpPS->szUnknownSource, PS_UNKNOWNSTRLEN);
+ if (!n)
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
+ return FALSE;
+ }
+ lpPS->szAppName[0]=TEXT('\0');
+
+ // GetData CF_OBJECTDESCRIPTOR. If the object on the clipboard in an OLE1 object (offering CF_OWNERLINK)
+ // or has been copied to clipboard by FileMaager (offering CF_FILENAME), an OBJECTDESCRIPTOR will be
+ // created will be created from CF_OWNERLINK or CF_FILENAME. See OBJECTDESCRIPTOR for more info.
+
+ if (lpPS->hObjDesc = OleStdFillObjectDescriptorFromData(lpOPS->lpSrcDataObj, &medium, &cfFormat))
+ {
+ lpOD = GlobalLock(lpPS->hObjDesc);
+
+ // Get FullUserTypeName, SourceOfCopy and CLSID
+ if (lpOD->dwFullUserTypeName)
+ lpPS->szFullUserTypeNameOD = (LPTSTR)lpOD+lpOD->dwFullUserTypeName;
+ else lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
+
+ if (lpOD->dwSrcOfCopy)
+ {
+ lpPS->szSourceOfDataOD = (LPTSTR)lpOD+lpOD->dwSrcOfCopy;
+ // If CF_FILENAME was offered, source of copy is a path name. Fit the path to the
+ // static control that will display it.
+ if (cfFormat == cfFileName)
+ lpPS->szSourceOfDataOD = ChopText(GetDlgItem(hDlg, ID_PS_SOURCETEXT), 0, lpPS->szSourceOfDataOD);
+ }
+ else lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
+
+ lpPS->clsidOD = lpOD->clsid;
+ lpPS->sizelOD = lpOD->sizel;
+
+ // Does source specify DVASPECT_ICON?
+ if (lpOD->dwDrawAspect & DVASPECT_ICON)
+ lpPS->fSrcAspectIconOD = TRUE;
+ else lpPS->fSrcAspectIconOD = FALSE;
+
+ // Does source specify OLEMISC_ONLYICONIC?
+ if (lpOD->dwStatus & OLEMISC_ONLYICONIC)
+ lpPS->fSrcOnlyIconicOD = TRUE;
+ else lpPS->fSrcOnlyIconicOD = FALSE;
+
+ // Get application name of source from auxusertype3 in the registration database
+ if (0==OleStdGetAuxUserType(&lpPS->clsidOD, 3, lpPS->szAppName, OLEUI_CCHKEYMAX_SIZE, NULL))
+ {
+ // Use "the application which created it" as the name of the application
+ if (0==LoadString(ghInst, IDS_PSUNKNOWNAPP, lpPS->szAppName, PS_UNKNOWNSTRLEN))
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_LOADSTRING, 0L);
+ return FALSE;
+ }
+ }
+
+ // Retrieve an icon from the object
+ if (lpPS->fSrcAspectIconOD)
+ {
+ lpPS->hMetaPictOD = OleStdGetData(
+ lpOPS->lpSrcDataObj,
+ (CLIPFORMAT) CF_METAFILEPICT,
+ NULL,
+ DVASPECT_ICON,
+ &medium
+ );
+
+ }
+ // If object does not offer icon, obtain it from the CLSID
+ if (NULL == lpPS->hMetaPictOD)
+ {
+#ifdef OLE201
+ lpPS->hMetaPictOD = GetIconOfClass(
+ ghInst,
+ &lpPS->clsidOD,
+ NULL,
+ TRUE); // Use the short user type name (auxusertype3)
+#endif
+ lpPS->hMetaPictOD = NULL;
+
+
+ }
+ }
+
+ // Does object offer CF_LINKSRCDESCRIPTOR?
+ if (lpPS->hLinkSrcDesc = OleStdGetData(
+ lpOPS->lpSrcDataObj,
+ (CLIPFORMAT) cfLinkSrcDescriptor,
+ NULL,
+ DVASPECT_CONTENT,
+ &medium))
+ {
+ // Get FullUserTypeName, SourceOfCopy and CLSID
+ lpLSD = GlobalLock(lpPS->hLinkSrcDesc);
+ if (lpLSD->dwFullUserTypeName)
+ lpPS->szFullUserTypeNameLSD = (LPTSTR)lpLSD+lpLSD->dwFullUserTypeName;
+ else lpPS->szFullUserTypeNameLSD = lpPS->szUnknownType;
+
+ if (lpLSD->dwSrcOfCopy)
+ lpPS->szSourceOfDataLSD = (LPTSTR)lpLSD+lpLSD->dwSrcOfCopy;
+ else lpPS->szSourceOfDataLSD = lpPS->szUnknownSource;
+
+ // if no ObjectDescriptor, then use LinkSourceDescriptor source string
+ if (!lpPS->hObjDesc)
+ lpPS->szSourceOfDataOD = lpPS->szSourceOfDataLSD;
+
+ lpPS->clsidLSD = lpLSD->clsid;
+ lpPS->sizelLSD = lpLSD->sizel;
+
+ // Does source specify DVASPECT_ICON?
+ if (lpLSD->dwDrawAspect & DVASPECT_ICON)
+ lpPS->fSrcAspectIconLSD = TRUE;
+ else lpPS->fSrcAspectIconLSD = FALSE;
+
+ // Does source specify OLEMISC_ONLYICONIC?
+ if (lpLSD->dwStatus & OLEMISC_ONLYICONIC)
+ lpPS->fSrcOnlyIconicLSD = TRUE;
+ else lpPS->fSrcOnlyIconicLSD = FALSE;
+
+ // Retrieve an icon from the object
+ if (lpPS->fSrcAspectIconLSD)
+ {
+ lpPS->hMetaPictLSD = OleStdGetData(
+ lpOPS->lpSrcDataObj,
+ CF_METAFILEPICT,
+ NULL,
+ DVASPECT_ICON,
+ &medium
+ );
+
+ }
+ // If object does not offer icon, obtain it from the CLSID
+ if (NULL == lpPS->hMetaPictLSD)
+ {
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ HWND hIconWnd;
+ RECT IconRect;
+ int nWidth;
+ LPTSTR lpszLabel;
+
+ hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
+
+ GetClientRect(hIconWnd, &IconRect);
+
+ nWidth = ((IconRect.right-IconRect.left) * 3) / 2; // width is 1.5 times width of iconbox
+
+ LSTRCPYN(szLabel, lpPS->szSourceOfDataLSD, OLEUI_CCHLABELMAX);
+ szLabel[OLEUI_CCHLABELMAX-1] = TEXT('\0');
+
+ lpszLabel = ChopText(hIconWnd, nWidth, (LPTSTR)szLabel);
+
+#ifdef OLE201
+ lpPS->hMetaPictLSD = GetIconOfClass(
+ ghInst,
+ &lpPS->clsidLSD,
+ lpszLabel, /* use chopped source string as label */
+ FALSE /* not applicable */
+ );
+#endif
+ lpPS->hMetaPictLSD = NULL;
+
+ }
+ }
+ else if (lpPS->hObjDesc) // Does not offer CF_LINKSRCDESCRIPTOR but offers CF_OBJECTDESCRIPTOR
+ {
+ // Copy the values of OBJECTDESCRIPTOR
+ lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD;
+ lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD;
+ lpPS->clsidLSD = lpPS->clsidOD;
+ lpPS->sizelLSD = lpPS->sizelOD;
+ lpPS->fSrcAspectIconLSD = lpPS->fSrcAspectIconOD;
+ lpPS->fSrcOnlyIconicLSD = lpPS->fSrcOnlyIconicOD;
+
+ // Don't copy the hMetaPict; instead get a separate copy
+ if (lpPS->fSrcAspectIconLSD)
+ {
+ lpPS->hMetaPictLSD = OleStdGetData(
+ lpOPS->lpSrcDataObj,
+ CF_METAFILEPICT,
+ NULL,
+ DVASPECT_ICON,
+ &medium
+ );
+ }
+ if (NULL == lpPS->hMetaPictLSD)
+ {
+ TCHAR szLabel[OLEUI_CCHLABELMAX];
+ HWND hIconWnd;
+ RECT IconRect;
+ int nWidth;
+ LPTSTR lpszLabel;
+
+ hIconWnd = GetDlgItem(hDlg, ID_PS_ICONDISPLAY);
+
+ GetClientRect(hIconWnd, &IconRect);
+
+ nWidth = ((IconRect.right-IconRect.left) * 3) / 2; // width is 1.5 times width of iconbox
+
+ LSTRCPYN(szLabel, lpPS->szSourceOfDataLSD, OLEUI_CCHLABELMAX);
+ szLabel[OLEUI_CCHLABELMAX-1] = TEXT('\0');
+
+ lpszLabel = ChopText(hIconWnd, nWidth, (LPTSTR)szLabel);
+
+#ifdef OLE201
+ lpPS->hMetaPictLSD = GetIconOfClass(
+ ghInst,
+ &lpPS->clsidLSD,
+ lpszLabel, /* Use chopped source string as label */
+ FALSE /* Not applicable */
+ );
+#endif
+ lpPS->hMetaPictLSD = NULL;
+
+ }
+ }
+
+ // Not an OLE object
+ if (lpPS->hObjDesc == NULL && lpPS->hLinkSrcDesc == NULL)
+ {
+ lpPS->szFullUserTypeNameLSD = lpPS->szFullUserTypeNameOD = lpPS->szUnknownType;
+ lpPS->szSourceOfDataLSD = lpPS->szSourceOfDataOD = lpPS->szUnknownSource;
+ lpPS->hMetaPictLSD = lpPS->hMetaPictOD = NULL;
+ }
+
+ // Allocate scratch memory to construct item names in the paste and pastelink listboxes
+ lpPS->hBuff = AllocateScratchMem(lpPS);
+ if (lpPS->hBuff == NULL)
+ {
+ PostMessage(hDlg, uMsgEndDialog, OLEUI_ERR_GLOBALMEMALLOC, 0L);
+ return FALSE;
+ }
+
+ // Select the Paste Link Button if specified. Otherwise select
+ // Paste Button by default
+ if (lpPS->dwFlags & PSF_SELECTPASTELINK)
+ lpPS->dwFlags = (lpPS->dwFlags & ~PSF_SELECTPASTE) | PSF_SELECTPASTELINK;
+ else
+ lpPS->dwFlags =(lpPS->dwFlags & ~PSF_SELECTPASTELINK) | PSF_SELECTPASTE;
+
+ // Mark which PasteEntry formats are available from source data object
+ OleStdMarkPasteEntryList(
+ lpOPS->lpSrcDataObj,lpOPS->arrPasteEntries,lpOPS->cPasteEntries);
+
+ // Check if items are available to be pasted
+ fPasteAvailable = FFillPasteList(hDlg, lpPS);
+ if (!fPasteAvailable)
+ {
+ lpPS->dwFlags &= ~PSF_SELECTPASTE;
+ EnableWindow(GetDlgItem(hDlg, ID_PS_PASTE), FALSE);
+ }
+
+ // Check if items are available to be paste-linked
+ fPasteLinkAvailable = FFillPasteLinkList(hDlg, lpPS);
+ if (!fPasteLinkAvailable)
+ {
+ lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
+ EnableWindow(GetDlgItem(hDlg, ID_PS_PASTELINK), FALSE);
+ }
+
+ // If one of Paste or PasteLink is disabled, select the other one
+ // regardless of what the input flags say
+ if (fPasteAvailable && !fPasteLinkAvailable)
+ lpPS->dwFlags |= PSF_SELECTPASTE;
+ if (fPasteLinkAvailable && !fPasteAvailable)
+ lpPS->dwFlags |= PSF_SELECTPASTELINK;
+
+ if (lpPS->dwFlags & PSF_SELECTPASTE)
+ {
+ // FTogglePaste will set the PSF_SELECTPASTE flag, so clear it.
+ lpPS->dwFlags &= ~PSF_SELECTPASTE;
+ CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTE);
+ FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTE);
+ }
+ else if (lpPS->dwFlags & PSF_SELECTPASTELINK)
+ {
+ // FTogglePaste will set the PSF_SELECTPASTELINK flag, so clear it.
+ lpPS->dwFlags &= ~PSF_SELECTPASTELINK;
+ CheckRadioButton(hDlg, ID_PS_PASTE, ID_PS_PASTELINK, ID_PS_PASTELINK);
+ FTogglePasteType(hDlg, lpPS, PSF_SELECTPASTELINK);
+ }
+ else // Items are not available to be be Pasted or Paste-Linked
+ {
+ // Enable or disable DisplayAsIcon and set the result text and image
+ EnableDisplayAsIcon(hDlg, lpPS);
+ SetPasteSpecialHelpResults(hDlg, lpPS);
+ }
+
+ // Give initial focus to the list box
+ SetFocus(GetDlgItem(hDlg, ID_PS_DISPLAYLIST));
+
+ // Set property to handle clipboard change notifications
+ SetProp(hDlg, NEXTCBVIEWER, HWND_BROADCAST);
+ SetProp(hDlg, NEXTCBVIEWER, SetClipboardViewer(hDlg));
+
+ lpPS->fClipboardChanged = FALSE;
+
+ /*
+ * PERFORM OTHER INITIALIZATION HERE.
+ */
+
+ // Call the hook with lCustData in lParam
+ UStandardHook(lpPS, hDlg, WM_INITDIALOG, wParam, lpOPS->lCustData);
+ return TRUE;
+}
+
+/*
+ * FTogglePasteType
+ *
+ * Purpose:
+ * Toggles between Paste and Paste Link. The Paste list and PasteLink
+ * list are always invisible. The Display List is filled from either
+ * the Paste list or the PasteLink list depending on which Paste radio
+ * button is selected.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ * dwOption Paste or PasteSpecial option
+ *
+ * Return Value:
+ * BOOL Returns TRUE if the option has already been selected.
+ * Otherwise the option is selected and FALSE is returned
+ */
+
+BOOL FTogglePasteType(HWND hDlg, LPPASTESPECIAL lpPS, DWORD dwOption)
+{
+ DWORD dwTemp;
+ HWND hList, hListDisplay;
+ DWORD dwData;
+ int i, nItems;
+ LPTSTR lpsz;
+
+ // Skip all this if the button is already selected
+ if (lpPS->dwFlags & dwOption)
+ return TRUE;
+
+ dwTemp = PSF_SELECTPASTE | PSF_SELECTPASTELINK;
+ lpPS->dwFlags = (lpPS->dwFlags & ~dwTemp) | dwOption;
+
+ // Hide IconDisplay. This prevents flashing if the icon display is changed
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
+
+ hListDisplay = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
+
+ // If Paste was selected
+ if (lpPS->dwFlags & PSF_SELECTPASTE)
+ {
+ // Set the Source of the object in the clipboard
+ SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataOD);
+
+ // If an icon is available
+ if (lpPS->hMetaPictOD)
+ // Set the icon display
+ SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
+ (WPARAM)lpPS->hMetaPictOD, 0L);
+
+
+ hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
+ // We are switching from PasteLink to Paste. Remember current selection
+ // in PasteLink list so it can be restored.
+ lpPS->nPasteLinkListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
+ if (lpPS->nPasteLinkListCurSel == LB_ERR)
+ lpPS->nPasteLinkListCurSel = 0;
+ // Remember if user selected Paste or PasteLink
+ lpPS->fLink = FALSE;
+ }
+ else // If PasteLink was selected
+ {
+ // Set the Source of the object in the clipboard
+ SetDlgItemText(hDlg, ID_PS_SOURCETEXT, lpPS->szSourceOfDataLSD);
+
+ // If an icon is available
+ if (lpPS->hMetaPictLSD)
+ // Set the icon display
+ SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET,
+ (WPARAM)lpPS->hMetaPictLSD, 0L);
+
+
+ hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
+ // We are switching from Paste to PasteLink. Remember current selection
+ // in Paste list so it can be restored.
+ lpPS->nPasteListCurSel = (int)SendMessage(hListDisplay, LB_GETCURSEL, 0, 0L);
+ if (lpPS->nPasteListCurSel == LB_ERR)
+ lpPS->nPasteListCurSel = 0;
+ // Remember if user selected Paste or PasteLink
+ lpPS->fLink = TRUE;
+ }
+
+ // Turn drawing off while the Display List is being filled
+ SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)FALSE, 0L);
+
+ // Move data to Display list box
+ SendMessage(hListDisplay, LB_RESETCONTENT, 0, 0L);
+ nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
+ lpsz = (LPTSTR)GlobalLock(lpPS->hBuff);
+ for (i = 0; i < nItems; i++)
+ {
+ SendMessage(hList, LB_GETTEXT, (WPARAM)i, (LPARAM)lpsz);
+ dwData = SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
+ SendMessage(hListDisplay, LB_INSERTSTRING, (WPARAM)i, (LPARAM)lpsz);
+ SendMessage(hListDisplay, LB_SETITEMDATA, (WPARAM)i, dwData);
+ }
+ GlobalUnlock(lpPS->hBuff);
+
+ // Restore the selection in the Display List from user's last selection
+ if (lpPS->dwFlags & PSF_SELECTPASTE)
+ SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteListCurSel, 0L);
+ else
+ SendMessage(hListDisplay, LB_SETCURSEL, lpPS->nPasteLinkListCurSel, 0L);
+
+ // Paint Display List
+ SendMessage(hListDisplay, WM_SETREDRAW, (WPARAM)TRUE, 0L);
+ InvalidateRect(hListDisplay, NULL, TRUE);
+ UpdateWindow(hListDisplay);
+
+ // Auto give the focus to the Display List
+ SetFocus(hListDisplay);
+
+ // Enable/Disable DisplayAsIcon and set the help result text and bitmap corresponding to
+ // the current selection
+ ChangeListSelection(hDlg, lpPS, hListDisplay);
+
+ return FALSE;
+}
+
+
+/*
+ * ChangeListSelection
+ *
+ * Purpose:
+ * When the user changes the selection in the list, DisplayAsIcon is enabled or disabled,
+ * Result text and bitmap are updated and the index of the arrPasteEntries[] corresponding
+ * to the current format selection is saved.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ * hList HWND of the List
+ *
+ * Return Value:
+ * No return value
+ */
+
+void ChangeListSelection(HWND hDlg, LPPASTESPECIAL lpPS, HWND hList)
+{
+ LPPASTELISTITEMDATA lpItemData;
+ int nCurSel;
+
+ EnableDisplayAsIcon(hDlg, lpPS);
+ SetPasteSpecialHelpResults(hDlg, lpPS);
+
+ // Remember index of arrPasteEntries[] corresponding to the current selection
+ nCurSel = (int)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+ if (nCurSel == LB_ERR) return;
+ lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA,
+ (WPARAM)nCurSel, 0L);
+ if ((LRESULT)lpItemData == LB_ERR) return;
+ lpPS->nSelectedIndex = lpItemData->nPasteEntriesIndex;
+}
+
+/*
+ * EnableDisplayAsIcon
+ *
+ * Purpose:
+ * Enable or disable the DisplayAsIcon button depending on whether
+ * the current selection can be displayed as an icon or not. The following table describes
+ * the state of DisplayAsIcon. The calling application is termed CONTAINER, the source
+ * of data on the clipboard is termed SOURCE.
+ * Y = Yes; N = No; Blank = State does not matter;
+ * =====================================================================
+ * SOURCE SOURCE CONTAINER DisplayAsIcon
+ * specifies specifies specifies Initial State
+ * DVASPECT_ICON OLEMISC_ONLYICONIC OLEUIPASTE_ENABLEICON
+ *
+ * N Unchecked&Disabled
+ * Y Y Checked&Disabled
+ * Y N Y Checked&Enabled
+ * N N Y Unchecked&Enabled
+ * =====================================================================
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * No return value
+ */
+
+void EnableDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ int nIndex;
+ BOOL fCntrEnableIcon;
+ BOOL fSrcOnlyIconic = (lpPS->fLink) ? lpPS->fSrcOnlyIconicLSD : lpPS->fSrcOnlyIconicOD;
+ BOOL fSrcAspectIcon = (lpPS->fLink) ? lpPS->fSrcAspectIconLSD : lpPS->fSrcAspectIconOD;
+ HWND hList;
+ LPPASTELISTITEMDATA lpItemData;
+ HGLOBAL hMetaPict = (lpPS->fLink) ? lpPS->hMetaPictLSD : lpPS->hMetaPictOD;
+
+ hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
+
+ // Get data corresponding to the current selection in the listbox
+ nIndex = (int)SendMessage(hList, LB_GETCURSEL, 0, 0);
+ if (nIndex != LB_ERR)
+ {
+ lpItemData = (LPPASTELISTITEMDATA) SendMessage(hList, LB_GETITEMDATA, (WPARAM)nIndex, 0L);
+ if ((LRESULT)lpItemData != LB_ERR)
+ fCntrEnableIcon = lpItemData->fCntrEnableIcon;
+ else fCntrEnableIcon = FALSE;
+ }
+ else fCntrEnableIcon = FALSE;
+
+ // If there is an icon available
+ if (hMetaPict != NULL)
+ {
+ if (!fCntrEnableIcon) // Does CONTAINER specify OLEUIPASTE_ENABLEICON?
+ {
+ // Uncheck & Disable DisplayAsIcon
+ lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
+
+ // Hide IconDisplay and ChangeIcon button
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
+ }
+ else if (fSrcOnlyIconic) // Does SOURCE specify OLEMISC_ONLYICONIC?
+ {
+ // Check & Disable DisplayAsIcon
+ lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
+ EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
+
+ // Show IconDisplay and ChangeIcon button
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
+ }
+ else if (fSrcAspectIcon) // Does SOURCE specify DVASPECT_ICON?
+ {
+ // Check & Enable DisplayAsIcon
+ lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, TRUE);
+ EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
+
+ // Show IconDisplay and ChangeIcon button
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_SHOWNORMAL);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_SHOWNORMAL);
+ }
+ else
+ {
+ //Uncheck and Enable DisplayAsIcon
+ lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), TRUE);
+
+ // Hide IconDisplay and ChangeIcon button
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
+
+ }
+ }
+ else // No icon available
+ {
+ // Unchecked & Disabled
+ lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
+ CheckDlgButton(hDlg, ID_PS_DISPLAYASICON, FALSE);
+ EnableWindow(GetDlgItem(hDlg, ID_PS_DISPLAYASICON), FALSE);
+
+ // Hide IconDisplay and ChangeIcon button
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, SW_HIDE);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, SW_HIDE);
+ }
+}
+
+/*
+ * ToggleDisplayAsIcon
+ *
+ * Purpose:
+ * Toggles the DisplayAsIcon button. Hides or shows the Icon Display and
+ * the ChangeIcon button and changes the help result text and bitmap.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * None
+ *
+ */
+
+void ToggleDisplayAsIcon(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ BOOL fCheck;
+ int i;
+
+ fCheck = IsDlgButtonChecked(hDlg, ID_PS_DISPLAYASICON);
+
+ if (fCheck)
+ lpPS->dwFlags |= PSF_CHECKDISPLAYASICON;
+ else lpPS->dwFlags &= ~PSF_CHECKDISPLAYASICON;
+
+ // Set the help result text and bitmap
+ SetPasteSpecialHelpResults(hDlg, lpPS);
+
+ // Show or hide the Icon Display and ChangeIcon button depending
+ // on the check state
+ i = (fCheck) ? SW_SHOWNORMAL : SW_HIDE;
+ StandardShowDlgItem(hDlg, ID_PS_ICONDISPLAY, i);
+ StandardShowDlgItem(hDlg, ID_PS_CHANGEICON, i);
+}
+
+/*
+ * ChangeIcon
+ *
+ * Purpose:
+ * Brings up the ChangeIcon dialog which allows the user to change
+ * the icon and label.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * None
+ *
+ */
+
+void ChangeIcon(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ OLEUICHANGEICON ci;
+ UINT uRet;
+ CLSID clsid = (lpPS->fLink) ? lpPS->clsidLSD : lpPS->clsidOD;
+
+ //Initialize the structure
+ _fmemset((LPOLEUICHANGEICON)&ci, 0, sizeof(ci));
+
+ ci.hMetaPict = (HGLOBAL)SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGEGET, 0, 0L);
+ ci.cbStruct = sizeof(ci);
+ ci.hWndOwner = hDlg;
+ ci.clsid = clsid;
+ ci.dwFlags = CIF_SELECTCURRENT;
+
+ // Only show help in the ChangeIcon dialog if we're showing it in this dialog.
+ if (lpPS->dwFlags & PSF_SHOWHELP)
+ ci.dwFlags |= CIF_SHOWHELP;
+
+ // Let the hook in to customize Change Icon if desired.
+ uRet = UStandardHook(lpPS, hDlg, uMsgChangeIcon, 0, (LONG)(LPSTR)&ci);
+
+ if (0 == uRet)
+ uRet=(UINT)(OLEUI_OK==OleUIChangeIcon(&ci));
+
+ // Update the display if necessary.
+ if (0!=uRet)
+ {
+ /*
+ * OleUIChangeIcon will have already freed our
+ * current hMetaPict that we passed in when OK is
+ * pressed in that dialog. So we use 0L as lParam
+ * here so the IconBox doesn't try to free the
+ * metafilepict again.
+ */
+ SendDlgItemMessage(hDlg, ID_PS_ICONDISPLAY, IBXM_IMAGESET, (WPARAM)ci.hMetaPict, 0L);
+ // Remember the new icon chosen by the user. Note that Paste and PasteLink have separate
+ // icons - changing one does not change the other.
+ if (lpPS->fLink)
+ lpPS->hMetaPictLSD = ci.hMetaPict;
+ else lpPS->hMetaPictOD = ci.hMetaPict;
+ }
+}
+
+/*
+ *SetPasteSpecialHelpResults
+ *
+ * Purpose:
+ * Sets the help result text and bitmap according to the current
+ * list selection. The following state table indicates which ResultText
+ * and ResultImage are selected. If %s in the lpstrFormatName is present,
+ * it is assumed that an object is being pasted/paste-linked, otherwise it
+ * is assumed that data is being pasted/paste-linked.
+ * Y = Yes; N = No; Blank = State does not matter;
+ * The numbers in the the ResultText and ResultImage columns refer to the table
+ * entries that follow.
+ * =====================================================================
+ * Paste/ lpstrFormatName in DisplayAsIcon Result Result
+ * PasteLink arrPasteEntry[]contains %s checked Text Image
+ * (Is Object == Y, Is Data == N)
+ * Paste N 1 1
+ * Paste Y N 2 2
+ * Paste Y Y 3 3
+ * PasteLink N 4 4
+ * PasteLink Y N 5 4
+ * PasteLink Y Y 6 5
+ * =====================================================================
+ * Result Text:
+ *
+ * 1. "Inserts the contents of the Clipboard into your document as <native type name,
+ * and optionally an additional help sentence>"
+ * 2. "Inserts the contents of the Clipboard into your document so that you may
+ * activate it using <object app name>"
+ * 3. "Inserts the contents of the Clipboard into your document so that you may
+ * activate it using <object app name>. It will be displayed as an icon."
+ * 4. "Inserts the contents of the Clipboard into your document as <native type name>.
+ * Paste Link creates a link to the source file so that changes to the source file
+ * will be reflected in your document."
+ * 5. "Inserts a picture of the Clipboard contents into your document. Paste Link
+ * creates a link to the source file so that changes to the source file will be
+ * reflected in your document."
+ * 6. "Inserts an icon into your document which represents the Clipboard contents.
+ * Paste Link creates a link to the source file so that changes to the source file
+ * will be reflected in your document."
+ * =====================================================================
+ * Result Image:
+ *
+ * 1. Clipboard Image
+ * 2. Paste image, non-iconic.
+ * 3. Paste image, iconic.
+ * 4. Paste Link image, non-iconic
+ * 5. Paste Link image, iconic
+ * ====================================================================
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * No return value
+ */
+void SetPasteSpecialHelpResults(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ LPTSTR psz1, psz2, psz3, psz4;
+ UINT i, iString, iImage, cch;
+ int nPasteEntriesIndex;
+ BOOL fDisplayAsIcon;
+ BOOL fIsObject;
+ HWND hList;
+ LPPASTELISTITEMDATA lpItemData;
+ LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
+ LPTSTR szFullUserTypeName = (lpPS->fLink) ?
+ lpPS->szFullUserTypeNameLSD : lpPS->szFullUserTypeNameOD;
+ LPTSTR szInsert;
+
+ hList = GetDlgItem(hDlg, ID_PS_DISPLAYLIST);
+
+ i=(UINT)SendMessage(hList, LB_GETCURSEL, 0, 0L);
+ if (i != LB_ERR)
+ {
+ lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, i, 0L);
+ if ((LRESULT)lpItemData == LB_ERR) return;
+ nPasteEntriesIndex = lpItemData->nPasteEntriesIndex;
+ // Check if there is a '%s' in the lpstrFormatName, then an object is being
+ // pasted/pastelinked. Otherwise Data is being pasted-pastelinked.
+ fIsObject = FHasPercentS(lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
+ lpPS);
+ }
+ else return;
+
+ // Is DisplayAsIcon checked?
+ fDisplayAsIcon=(0L!=(lpPS->dwFlags & PSF_CHECKDISPLAYASICON));
+
+ szInsert = szFullUserTypeName;
+
+ if (lpPS->dwFlags & PSF_SELECTPASTE) // If user selected Paste
+ {
+ if (fIsObject)
+ {
+ iString = fDisplayAsIcon ? IDS_PSPASTEOBJECTASICON : IDS_PSPASTEOBJECT;
+ iImage = fDisplayAsIcon ? RESULTIMAGE_EMBEDICON : RESULTIMAGE_EMBED;
+ szInsert = lpPS->szAppName;
+ }
+ else
+ {
+ iString = IDS_PSPASTEDATA;
+ iImage = RESULTIMAGE_PASTE;
+ }
+ }
+ else if (lpPS->dwFlags & PSF_SELECTPASTELINK) // User selected PasteLink
+ {
+ if (fIsObject)
+ {
+ iString = fDisplayAsIcon ? IDS_PSPASTELINKOBJECTASICON : IDS_PSPASTELINKOBJECT;
+ iImage = fDisplayAsIcon ? RESULTIMAGE_LINKICON : RESULTIMAGE_LINK;
+ }
+ else
+ {
+ iString = IDS_PSPASTELINKDATA;
+ iImage = RESULTIMAGE_LINK;
+ }
+
+ }
+ else // Should never occur.
+ {
+ iString = IDS_PSNONOLE;
+ iImage = RESULTIMAGE_PASTE;
+ }
+
+ // hBuff contains enough space for the 4 buffers required to build up the help
+ // result text.
+ cch = (UINT)GlobalSize(lpPS->hBuff)/4;
+
+ psz1=(LPTSTR)GlobalLock(lpPS->hBuff);
+ psz2=psz1+cch;
+ psz3=psz2+cch;
+ psz4=psz3+cch;
+
+ // Default is an empty string.
+ *psz1=0;
+
+ if (0!=LoadString(ghInst, iString, psz1, cch))
+ {
+ // Insert the FullUserTypeName of the source object into the partial result text
+ // specified by the container.
+ wsprintf(psz3, lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrResultText,
+ (LPTSTR)szInsert);
+ // Insert the above partial result text into the standard result text.
+ wsprintf(psz4, psz1, (LPTSTR)psz3);
+ psz1=psz4;
+ }
+
+ // If LoadString failed, we simply clear out the results (*psz1=0 above)
+ SetDlgItemText(hDlg, ID_PS_RESULTTEXT, psz1);
+
+ // Change the result bitmap
+ SendDlgItemMessage(hDlg, ID_PS_RESULTIMAGE, RIM_IMAGESET, iImage, 0L);
+
+ GlobalUnlock(lpPS->hBuff);
+}
+
+/*
+ * FAddPasteListItem
+ *
+ * Purpose:
+ * Adds an item to the list box
+ *
+ * Parameters:
+ * hList HWND List into which item is to be added
+ * fInsertFirst BOOL Insert in the beginning of the list?
+ * nPasteEntriesIndex int Index of Paste Entry array this list item corresponsds to
+ * lpPS Paste Special Dialog Structure
+ * pIMalloc LPMALLOC Memory Allocator
+ * lpszBuf LPSTR Scratch buffer to build up string for list entry
+ * lpszFullUserTypeName LPSTR full user type name for object entry
+ *
+ * Return Value:
+ * BOOL TRUE if sucessful.
+ * FALSE if unsucessful.
+ */
+BOOL FAddPasteListItem(
+ HWND hList, BOOL fInsertFirst, int nPasteEntriesIndex,
+ LPPASTESPECIAL lpPS,
+ LPMALLOC pIMalloc, LPTSTR lpszBuf, LPTSTR lpszFullUserTypeName)
+{
+ LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
+ LPPASTELISTITEMDATA lpItemData;
+ int nIndex;
+
+ // Allocate memory for each list box item
+ lpItemData = (LPPASTELISTITEMDATA)pIMalloc->lpVtbl->Alloc(
+ pIMalloc, (DWORD)sizeof(PASTELISTITEMDATA));
+ if (NULL == lpItemData)
+ return FALSE;
+
+ // Fill data associated with each list box item
+ lpItemData->nPasteEntriesIndex = nPasteEntriesIndex;
+ lpItemData->fCntrEnableIcon = ((lpOPS->arrPasteEntries[nPasteEntriesIndex].dwFlags &
+ OLEUIPASTE_ENABLEICON) ? TRUE : FALSE);
+
+ // Build list box entry string, insert the string and add the data the corresponds to it
+ wsprintf(
+ (LPTSTR)lpszBuf,
+ lpOPS->arrPasteEntries[nPasteEntriesIndex].lpstrFormatName,
+ (LPTSTR)lpszFullUserTypeName
+ );
+
+ // only add to listbox if not a duplicate
+ if (LB_ERR!=SendMessage(hList,LB_FINDSTRING, 0, (LPARAM)(LPTSTR)lpszBuf)) {
+ // item is already in list; SKIP this one
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData);
+ return TRUE; // this is NOT an error
+ }
+
+ nIndex = (int)SendMessage(
+ hList,
+ (fInsertFirst ? LB_INSERTSTRING : LB_ADDSTRING),
+ 0,
+ (LPARAM)(LPTSTR)lpszBuf
+ );
+ SendMessage(
+ hList,
+ LB_SETITEMDATA,
+ nIndex,
+ (LPARAM)(LPPASTELISTITEMDATA)lpItemData
+ );
+ return TRUE;
+}
+
+
+/*
+ * FFillPasteList
+ *
+ * Purpose:
+ * Fills the invisible paste list with the formats offered by the clipboard object and
+ * asked for by the container.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * BOOL TRUE if sucessful and if formats could be found.
+ * FALSE if unsucessful or if no formats could be found.
+ */
+BOOL FFillPasteList(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
+ LPMALLOC pIMalloc = NULL;
+ LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff);
+ HWND hList;
+ int i, j;
+ int nItems = 0;
+ int nDefFormat = -1;
+ BOOL fTryObjFmt = FALSE;
+ BOOL fInsertFirst;
+ BOOL fExclude;
+ HRESULT hrErr;
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+ if (hrErr != NOERROR)
+ goto error;
+
+ hList = GetDlgItem(hDlg, ID_PS_PASTELIST);
+
+ // Loop over the target's priority list of formats
+ for (i = 0; i < lpOPS->cPasteEntries; i++)
+ {
+ if (lpOPS->arrPasteEntries[i].dwFlags != OLEUIPASTE_PASTEONLY &&
+ !(lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_PASTE))
+ continue;
+
+ fInsertFirst = FALSE;
+
+ if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
+ || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbeddedObject
+ || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfEmbedSource) {
+ if (! fTryObjFmt) {
+ fTryObjFmt = TRUE; // only use 1st object format
+ fInsertFirst = TRUE; // OLE obj format should always be 1st
+
+ //Check if this CLSID is in the exclusion list.
+ fExclude=FALSE;
+
+ for (j=0; j < (int)lpOPS->cClsidExclude; j++)
+ {
+ if (IsEqualCLSID(&lpPS->clsidOD,
+ (LPCLSID)(lpOPS->lpClsidExclude+j)))
+ {
+ fExclude=TRUE;
+ break;
+ }
+ }
+
+ if (fExclude)
+ continue; // don't add the object entry to list
+
+ } else {
+ continue; // already added an object format to list
+ }
+ }
+
+ // add to list if entry is marked TRUE
+ if (lpOPS->arrPasteEntries[i].dwScratchSpace) {
+ if (nDefFormat < 0)
+ nDefFormat = (fInsertFirst ? 0 : nItems);
+ else if (fInsertFirst)
+ nDefFormat++; // adjust for obj fmt inserted 1st in list
+
+ if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, pIMalloc,
+ lpszBuf, lpPS->szFullUserTypeNameOD))
+ goto error;
+ nItems++;
+ }
+ }
+
+ // initialize selection to first format matched in list
+ if (nDefFormat >= 0)
+ lpPS->nPasteListCurSel = nDefFormat;
+
+ // Clean up
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (lpszBuf)
+ GlobalUnlock(lpPS->hBuff);
+
+ // If no items have been added to the list box (none of the formats
+ // offered by the source matched those acceptable to the container),
+ // return FALSE
+ if (nItems > 0)
+ return TRUE;
+ else
+ return FALSE;
+
+error:
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (lpszBuf)
+ GlobalUnlock(lpPS->hBuff);
+ FreeListData(hList);
+
+ return FALSE;
+}
+
+
+/*
+ * FFillPasteLinkList
+ *
+ * Purpose:
+ * Fills the invisible paste link list with the formats offered by the clipboard object and
+ * asked for by the container.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * BOOL TRUE if sucessful and if formats could be found.
+ * FALSE if unsucessful or if no formats could be found.
+ */
+BOOL FFillPasteLinkList(HWND hDlg, LPPASTESPECIAL lpPS)
+{
+ LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
+ LPDATAOBJECT lpSrcDataObj = lpOPS->lpSrcDataObj;
+ LPENUMFORMATETC lpEnumFmtEtc = NULL;
+ LPMALLOC pIMalloc = NULL;
+ LPTSTR lpszBuf = (LPTSTR)GlobalLock(lpPS->hBuff);
+ OLEUIPASTEFLAG pasteFlag;
+ UINT arrLinkTypesSupported[PS_MAXLINKTYPES]; // Array of flags that
+ // indicate which link types
+ // are supported by source.
+ FORMATETC fmtetc;
+ int i, j;
+ int nItems = 0;
+ BOOL fLinkTypeSupported = FALSE;
+ HWND hList;
+ int nDefFormat = -1;
+ BOOL fTryObjFmt = FALSE;
+ BOOL fInsertFirst;
+ HRESULT hrErr;
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+ if (hrErr != NOERROR)
+ goto error;
+
+ // Remember which link type formats are offered by lpSrcDataObj.
+ _fmemset(&fmtetc, 0, sizeof(FORMATETC));
+ for (i = 0; i < lpOPS->cLinkTypes; i++)
+ {
+ if (lpOPS->arrLinkTypes[i] = cfLinkSource) {
+ OLEDBG_BEGIN2(TEXT("OleQueryLinkFromData called\r\n"))
+ hrErr = OleQueryLinkFromData(lpSrcDataObj);
+ OLEDBG_END2
+ if(NOERROR == hrErr)
+ {
+ arrLinkTypesSupported[i] = 1;
+ fLinkTypeSupported = TRUE;
+ }
+ else arrLinkTypesSupported[i] = 0;
+ }
+ else {
+ fmtetc.cfFormat = lpOPS->arrLinkTypes[i];
+ fmtetc.dwAspect = DVASPECT_CONTENT;
+ fmtetc.tymed = 0xFFFFFFFF; // All tymed values
+ fmtetc.lindex = -1;
+ OLEDBG_BEGIN2(TEXT("IDataObject::QueryGetData called\r\n"))
+ hrErr = lpSrcDataObj->lpVtbl->QueryGetData(lpSrcDataObj,&fmtetc);
+ OLEDBG_END2
+ if(NOERROR == hrErr)
+ {
+ arrLinkTypesSupported[i] = 1;
+ fLinkTypeSupported = TRUE;
+ }
+ else arrLinkTypesSupported[i] = 0;
+ }
+ }
+ // No link types are offered by lpSrcDataObj
+ if (! fLinkTypeSupported) {
+ nItems = 0;
+ goto cleanup;
+ }
+
+ hList = GetDlgItem(hDlg, ID_PS_PASTELINKLIST);
+
+ // Enumerate the formats acceptable to container
+ for (i = 0; i < lpOPS->cPasteEntries; i++)
+ {
+ fLinkTypeSupported = FALSE;
+
+ // If container will accept any link type offered by source object
+ if (lpOPS->arrPasteEntries[i].dwFlags & OLEUIPASTE_LINKANYTYPE)
+ fLinkTypeSupported = TRUE;
+ else
+ {
+ // Check if any of the link types offered by the source
+ // object are acceptable to the container
+ // This code depends on the LINKTYPE enum values being powers of 2
+ for (pasteFlag = OLEUIPASTE_LINKTYPE1, j = 0;
+ j < lpOPS->cLinkTypes;
+ pasteFlag*=2, j++)
+ {
+ if ((lpOPS->arrPasteEntries[i].dwFlags & pasteFlag) &&
+ arrLinkTypesSupported[j])
+ {
+ fLinkTypeSupported = TRUE;
+ break;
+ }
+ }
+ }
+
+ fInsertFirst = FALSE;
+
+ if (lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfFileName
+ || lpOPS->arrPasteEntries[i].fmtetc.cfFormat==cfLinkSource) {
+ if (! fTryObjFmt) {
+ fTryObjFmt = TRUE; // only use 1st object format
+ fInsertFirst = TRUE; // OLE obj format should always be 1st
+ } else {
+ continue; // already added an object format to list
+ }
+ }
+
+ // add to list if entry is marked TRUE
+ if (fLinkTypeSupported && lpOPS->arrPasteEntries[i].dwScratchSpace) {
+ if (nDefFormat < 0)
+ nDefFormat = (fInsertFirst ? 0 : nItems);
+ else if (fInsertFirst)
+ nDefFormat++; // adjust for obj fmt inserted 1st in list
+
+ if (!FAddPasteListItem(hList, fInsertFirst, i, lpPS, pIMalloc,
+ lpszBuf, lpPS->szFullUserTypeNameLSD))
+ goto error;
+ nItems++;
+ }
+ } // end FOR
+
+ nItems = (int)SendMessage(hList, LB_GETCOUNT, 0, 0L);
+
+ // initialize selection to first format matched in list
+ if (nDefFormat >= 0)
+ lpPS->nPasteLinkListCurSel = nDefFormat;
+
+cleanup:
+ // Clean up
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (lpszBuf)
+ GlobalUnlock(lpPS->hBuff);
+
+ // If no items have been added to the list box (none of the formats
+ // offered by the source matched those acceptable to the destination),
+ // return FALSE
+ if (nItems > 0)
+ return TRUE;
+ else
+ return FALSE;
+
+error:
+ if (pIMalloc)
+ pIMalloc->lpVtbl->Release(pIMalloc);
+ if (lpszBuf)
+ GlobalUnlock(lpPS->hBuff);
+ FreeListData(hList);
+
+ return FALSE;
+}
+
+
+/*
+ * FreeListData
+ *
+ * Purpose:
+ * Free the local memory associated with each list box item
+ *
+ * Parameters:
+ * hList HWND of the list
+ *
+ * Return Value:
+ * None
+ */
+void FreeListData(HWND hList)
+{
+ int nItems, i;
+ LPPASTELISTITEMDATA lpItemData;
+ LPMALLOC pIMalloc;
+ HRESULT hrErr;
+
+ hrErr = CoGetMalloc(MEMCTX_TASK, &pIMalloc);
+ if (hrErr != NOERROR)
+ return;
+
+ nItems = (int) SendMessage(hList, LB_GETCOUNT, 0, 0L);
+ for (i = 0; i < nItems; i++)
+ {
+ lpItemData = (LPPASTELISTITEMDATA)SendMessage(hList, LB_GETITEMDATA, (WPARAM)i, 0L);
+ if ((LRESULT)lpItemData != LB_ERR)
+ pIMalloc->lpVtbl->Free(pIMalloc, (LPVOID)lpItemData);
+ }
+ pIMalloc->lpVtbl->Release(pIMalloc);
+}
+
+/*
+ * FHasPercentS
+ *
+ * Purpose:
+ * Determines if string contains %s.
+ *
+ * Parameters:
+ * lpsz LPCSTR string in which occurence of '%s' is looked for
+ *
+ * Return Value:
+ * BOOL TRUE if %s is found, else FALSE.
+ */
+
+BOOL FHasPercentS(LPCTSTR lpsz, LPPASTESPECIAL lpPS)
+{
+ int n = 0;
+ LPTSTR lpszTmp;
+
+ if (!lpsz) return FALSE;
+ // Copy input string to buffer. This allows caller to pass a
+ // code-based string. Code segments may be swapped out in low memory situations
+ // and so code-based strings need to be copied before string elements can be accessed.
+ lpszTmp = (LPTSTR)GlobalLock(lpPS->hBuff);
+ lstrcpy(lpszTmp, lpsz);
+
+ while (*lpszTmp)
+ {
+ if (*lpszTmp == TEXT('%'))
+ {
+#ifdef WIN32
+ // AnsiNext is obsolete in Win32
+ lpszTmp = CharNext(lpszTmp);
+#else
+ lpszTmp = AnsiNext(lpszTmp);
+#endif
+ if (*lpszTmp == TEXT('s')) // If %s, return
+ {
+ GlobalUnlock(lpPS->hBuff);
+ return TRUE;
+ }
+ else if (*lpszTmp == TEXT('%')) // if %%, skip to next character
+#ifdef WIN32
+ // AnsiNext is obsolete in Win32
+ lpszTmp = CharNext(lpszTmp);
+#else
+ lpszTmp = AnsiNext(lpszTmp);
+#endif
+ }
+ else
+#ifdef WIN32
+ lpszTmp = CharNext(lpszTmp);
+#else
+ lpszTmp = AnsiNext(lpszTmp);
+#endif
+ }
+
+ GlobalUnlock(lpPS->hBuff);
+ return FALSE;
+}
+
+/*
+ * AllocateScratchMem
+ *
+ * Purpose:
+ * Allocates scratch memory for use by the PasteSpecial dialog. The memory is
+ * is used as the buffer for building up strings using wsprintf. Strings are built up
+ * using the buffer while inserting items into the Paste & PasteLink lists and while
+ * setting the help result text. It must be big enough to handle the string that results after
+ * replacing the %s in the lpstrFormatName and lpstrResultText in arrPasteEntries[]
+ * by the FullUserTypeName. It must also be big enough to build the dialog's result text
+ * after %s substitutions by the FullUserTypeName or the ApplicationName.
+ *
+ * Parameters:
+ * lpPS Paste Special Dialog Structure
+ *
+ * Return Value:
+ * HGLOBAL Handle to allocated global memory
+ */
+
+HGLOBAL AllocateScratchMem(LPPASTESPECIAL lpPS)
+{
+ LPOLEUIPASTESPECIAL lpOPS = lpPS->lpOPS;
+ int nLen, i;
+ int nSubstitutedText = 0;
+ int nAlloc = 0;
+
+ // Get the maximum length of the FullUserTypeNames specified by OBJECTDESCRIPTOR
+ // and the LINKSRCDESCRIPTOR and the Application Name. Any of these may be substituted
+ // for %s in the result-text/list entries.
+ if (lpPS->szFullUserTypeNameOD)
+ nSubstitutedText = lstrlen(lpPS->szFullUserTypeNameOD);
+ if (lpPS->szFullUserTypeNameLSD)
+ nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szFullUserTypeNameLSD));
+ if (lpPS->szAppName)
+ nSubstitutedText = __max(nSubstitutedText, lstrlen(lpPS->szAppName));
+
+ // Get the maximum length of lpstrFormatNames & lpstrResultText in arrPasteEntries
+ nLen = 0;
+ for (i = 0; i < lpOPS->cPasteEntries; i++)
+ {
+ nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrFormatName));
+ nLen = __max(nLen, lstrlen(lpOPS->arrPasteEntries[i].lpstrResultText));
+ }
+
+ // Get the maximum length of lpstrFormatNames and lpstrResultText after %s has
+ // been substituted (At most one %s can appear in each string).
+ // Add 1 to hold NULL terminator.
+ nAlloc = (nLen+nSubstitutedText+1)*sizeof(TCHAR);
+
+ // Allocate scratch memory to be used to build strings
+ // nAlloc is big enough to hold any of the lpstrResultText or lpstrFormatName in arrPasteEntries[]
+ // after %s substitution.
+ // We also need space to build up the help result text. 512 is the maximum length of the
+ // standard dialog help text before substitutions. 512+nAlloc is the maximum length
+ // after %s substition.
+ // SetPasteSpecialHelpResults() requires 4 such buffers to build up the result text
+ return GlobalAlloc(GHND, (DWORD)4*(512+nAlloc));
+}
+
diff --git a/private/oleutest/letest/ole2ui/pastespl.dlg b/private/oleutest/letest/ole2ui/pastespl.dlg
new file mode 100644
index 000000000..d64f5e45c
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/pastespl.dlg
@@ -0,0 +1,40 @@
+// DLGINCLUDE RCDATA DISCARDABLE
+// BEGIN
+// "PASTESPL.H\0"
+// END
+
+IDD_PASTESPECIAL DIALOG 3, 15, 293, 140
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Paste Special"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ LTEXT "Source:", ID_PS_STXSOURCE, 6, 9, 30, 8
+ LTEXT "", ID_PS_SOURCETEXT, 37, 9, 180, 8, SS_NOPREFIX | NOT
+ WS_GROUP
+ CONTROL "&Paste", ID_PS_PASTE, "Button", BS_AUTORADIOBUTTON |
+ WS_GROUP | WS_TABSTOP, 6, 38, 55, 10
+ CONTROL "Paste &Link", ID_PS_PASTELINK, "Button",
+ BS_AUTORADIOBUTTON, 6, 63, 55, 10
+ LTEXT "&As:", ID_PS_STXAS, 65, 25, 16, 8
+ LISTBOX ID_PS_PASTELIST, 65, 36, 153, 57, LBS_USETABSTOPS |
+ WS_VSCROLL | WS_GROUP | WS_TABSTOP | NOT WS_VISIBLE
+ LISTBOX ID_PS_PASTELINKLIST, 65, 36, 153, 57, LBS_USETABSTOPS |
+ WS_VSCROLL | WS_GROUP | WS_TABSTOP | NOT WS_VISIBLE
+ LISTBOX ID_PS_DISPLAYLIST, 65, 36, 153, 57, LBS_USETABSTOPS |
+ WS_VSCROLL | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "OK", IDOK, 224, 6, 66, 14, WS_GROUP
+ PUSHBUTTON "Cancel", IDCANCEL, 224, 23, 66, 14
+ PUSHBUTTON "&Help", ID_OLEUIHELP, 224, 42, 66, 14
+ CONTROL "&Display As Icon", ID_PS_DISPLAYASICON, "Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP, 224, 59, 66, 14
+// CONTROL "", ID_PS_ICONDISPLAY, SZCLASSICONBOX, 0, 224, 75, 66, 44
+ PUSHBUTTON "Change &Icon...", ID_PS_CHANGEICON, 224, 123, 66, 14
+// CONTROL "", ID_PS_RESULTIMAGE, SZCLASSRESULTIMAGE, 0, 8, 101,
+// 42, 34
+ LTEXT "Result", ID_PS_RESULTTEXT, 54, 100, 159, 35,
+ SS_NOPREFIX | NOT WS_GROUP
+ GROUPBOX "Result", ID_PS_RESULTGROUP, 6, 90, 212, 48, WS_GROUP
+END
+
+
+
diff --git a/private/oleutest/letest/ole2ui/pastespl.h b/private/oleutest/letest/ole2ui/pastespl.h
new file mode 100644
index 000000000..526462f36
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/pastespl.h
@@ -0,0 +1,110 @@
+/*
+ * PASTESPL.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI Paste Special dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#ifndef _PASTESPL_H_
+#define _PASTESPL_H_
+
+#ifndef RC_INVOKED
+#pragma message ("INCLUDING PASTESPL.H from " __FILE__)
+#endif /* RC_INVOKED */
+
+
+// Length of buffers to hold the strings 'Unknown Type', Unknown Source'
+// and 'the application which created it'
+#define PS_UNKNOWNSTRLEN 100
+
+//Property label used to store clipboard viewer chain information
+#define NEXTCBVIEWER TEXT("NextCBViewer")
+
+//Internally used structure
+typedef struct tagPASTESPECIAL
+{
+ //Keep this item first as the Standard* functions depend on it here.
+ LPOLEUIPASTESPECIAL lpOPS; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+
+ DWORD dwFlags; // Local copy of paste special flags
+
+ int nPasteListCurSel; // Save the selection the user made last
+ int nPasteLinkListCurSel; // in the paste and pastelink lists
+ int nSelectedIndex; // Index in arrPasteEntries[] corresponding to user selection
+ BOOL fLink; // Indicates if Paste or PasteLink was selected by user
+
+ HGLOBAL hBuff; // Scratch Buffer for building up strings
+ TCHAR szUnknownType[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Type' string
+ TCHAR szUnknownSource[PS_UNKNOWNSTRLEN]; // Buffer for 'Unknown Source' string
+ TCHAR szAppName[OLEUI_CCHKEYMAX]; // Application name of Source. Used in the result text
+ // when Paste is selected. Obtained using clsidOD.
+
+ // Information obtained from OBJECTDESCRIPTOR. This information is accessed when the Paste
+ // radio button is selected.
+ CLSID clsidOD; // ClassID of source
+ SIZEL sizelOD; // sizel transfered in
+ // ObjectDescriptor
+ LPTSTR szFullUserTypeNameOD; // Full User Type Name
+ LPTSTR szSourceOfDataOD; // Source of Data
+ BOOL fSrcAspectIconOD; // Does Source specify DVASPECT_ICON?
+ BOOL fSrcOnlyIconicOD; // Does Source specify OLEMISC_ONLYICONIC?
+ HGLOBAL hMetaPictOD; // Metafile containing icon and icon title
+ HGLOBAL hObjDesc; // Handle to OBJECTDESCRIPTOR structure from which the
+ // above information is obtained
+
+ // Information obtained from LINKSRCDESCRIPTOR. This infomation is accessed when the PasteLink
+ // radio button is selected.
+ CLSID clsidLSD; // ClassID of source
+ SIZEL sizelLSD; // sizel transfered in
+ // LinkSrcDescriptor
+ LPTSTR szFullUserTypeNameLSD;// Full User Type Name
+ LPTSTR szSourceOfDataLSD; // Source of Data
+ BOOL fSrcAspectIconLSD; // Does Source specify DVASPECT_ICON?
+ BOOL fSrcOnlyIconicLSD; // Does Source specify OLEMISC_ONLYICONIC?
+ HGLOBAL hMetaPictLSD; // Metafile containing icon and icon title
+ HGLOBAL hLinkSrcDesc; // Handle to LINKSRCDESCRIPTOR structure from which the
+ // above information is obtained
+
+ BOOL fClipboardChanged; // Has clipboard content changed
+ // if so bring down dlg after
+ // ChangeIcon dlg returns.
+} PASTESPECIAL, *PPASTESPECIAL, FAR *LPPASTESPECIAL;
+
+// Data corresponding to each list item. A pointer to this structure is attached to each
+// Paste\PasteLink list box item using LB_SETITEMDATA
+typedef struct tagPASTELISTITEMDATA
+{
+ int nPasteEntriesIndex; // Index of arrPasteEntries[] corresponding to list item
+ BOOL fCntrEnableIcon; // Does calling application (called container here)
+ // specify OLEUIPASTE_ENABLEICON for this item?
+} PASTELISTITEMDATA, *PPASTELISTITEMDATA, FAR *LPPASTELISTITEMDATA;
+
+
+//Internal function prototypes
+//PASTESPL.C
+BOOL CALLBACK EXPORT PasteSpecialDialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL FPasteSpecialInit(HWND hDlg, WPARAM, LPARAM);
+BOOL FTogglePasteType(HWND, LPPASTESPECIAL, DWORD);
+void ChangeListSelection(HWND, LPPASTESPECIAL, HWND);
+void EnableDisplayAsIcon(HWND, LPPASTESPECIAL);
+void ToggleDisplayAsIcon(HWND, LPPASTESPECIAL);
+void ChangeIcon(HWND, LPPASTESPECIAL);
+void SetPasteSpecialHelpResults(HWND, LPPASTESPECIAL);
+BOOL FAddPasteListItem(HWND, BOOL, int, LPPASTESPECIAL, LPMALLOC, LPTSTR, LPTSTR);
+BOOL FFillPasteList(HWND, LPPASTESPECIAL);
+BOOL FFillPasteLinkList(HWND, LPPASTESPECIAL);
+BOOL FHasPercentS(LPCTSTR, LPPASTESPECIAL);
+HGLOBAL AllocateScratchMem(LPPASTESPECIAL);
+void FreeListData(HWND);
+
+#endif //_PASTESPL_H_
+
diff --git a/private/oleutest/letest/ole2ui/precomp.c b/private/oleutest/letest/ole2ui/precomp.c
new file mode 100644
index 000000000..1385d8a41
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/precomp.c
@@ -0,0 +1,23 @@
+/*
+ * PRECOMP.C
+ *
+ * This file is used to precompile the OLE2UI.H header file
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+
+// This dummy function is needed in order for the static link version
+// of this library to work correctly. When we include PRECOMP.OBJ
+// in our library (.LIB file), it will only get linked into our
+// application IFF at least one function in precomp.c is called from
+// either our EXE or LIB. Therefore, we will use a function
+// here called OleUIStaticLibDummy(). You need to call it from
+// your application.
+
+void FAR PASCAL OleUIStaticLibDummy(void)
+{
+
+}
diff --git a/private/oleutest/letest/ole2ui/prompt.dlg b/private/oleutest/letest/ole2ui/prompt.dlg
new file mode 100644
index 000000000..fc8474315
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/prompt.dlg
@@ -0,0 +1,80 @@
+Exclamation ICON bang.ico
+
+
+IDD_LINKSOURCEUNAVAILABLE DIALOG 21, 34, 175, 78
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION ""
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "This action cannot be completed because the selected link's source is presently unavailable.", ID_PU_TEXT, 48, 8, 117, 32
+ DEFPUSHBUTTON "OK", IDOK, 39, 58, 40, 14
+ PUSHBUTTON "Links...", ID_PU_LINKS, 95, 58, 40, 14
+END
+
+
+IDD_CANNOTUPDATELINK DIALOG 21, 34, 175, 78
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION ""
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "Some links could not be updated because their sources are presently unavailable.", ID_PU_TEXT, 48, 8, 117, 32
+ DEFPUSHBUTTON "OK", IDOK, 39, 58, 40, 14
+ PUSHBUTTON "Links...", ID_PU_LINKS, 95, 58, 40, 14
+END
+
+
+IDD_SERVERNOTREG DIALOG 39, 30, 198, 78
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "The application necessary to activate this %s is unavailable. You may convert it to or activate it as another type of object using Convert...", ID_PU_TEXT, 39, 8, 152, 36
+ DEFPUSHBUTTON "Convert...", ID_PU_CONVERT, 23, 58, 40, 14
+ PUSHBUTTON "Cancel", IDCANCEL, 79, 58, 40, 14
+ PUSHBUTTON "Help", ID_OLEUIHELP, 135, 58, 40, 14
+END
+
+
+IDD_LINKTYPECHANGED DIALOG 39, 30, 198, 78
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "The link is no longer a %s. Please choose a different command offered by the new type.",
+ ID_PU_TEXT, 39, 8, 152, 36
+ PUSHBUTTON "OK", IDOK, 79, 58, 40, 14
+END
+
+
+IDD_SERVERNOTFOUND DIALOG 36, 39, 183, 90
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "The server application cannot be found.\n\nMake sure the application is properly installed, or exists in your DOS path, and that is has not been deleted, moved, or renamed.",
+ ID_PU_TEXT, 38, 8, 136, 52
+ DEFPUSHBUTTON "OK", IDOK, 71, 70, 40, 14
+END
+
+
+IDD_UPDATELINKS DIALOG 50, 57, 179, 55
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ CONTROL "", ID_PU_METER, "Static", SS_BLACKFRAME, 5, 40, 122, 9
+ DEFPUSHBUTTON "Stop", ID_PU_STOP, 134, 37, 40, 14
+ LTEXT "Update links...", ID_DUMMY, 5, 7, 56, 8
+ LTEXT "", ID_PU_PERCENT, 56, 26, 20, 8
+END
+
+
+IDD_OUTOFMEMORY DIALOG 36, 39, 107, 73
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+FONT 8, "MS Shell Dlg"
+BEGIN
+ ICON "Exclamation", ID_DUMMY, 8, 8, 0, 0, SS_ICON
+ LTEXT "Out of memory!", ID_PU_TEXT, 41, 13, 57, 12
+ DEFPUSHBUTTON "OK", IDOK, 33, 53, 40, 14
+END
diff --git a/private/oleutest/letest/ole2ui/regdb.c b/private/oleutest/letest/ole2ui/regdb.c
new file mode 100644
index 000000000..b6922b260
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/regdb.c
@@ -0,0 +1,401 @@
+/*
+ * REGDB.C
+ *
+ * Functions to query the registration database
+ *
+ * OleStdGetMiscStatusOfClass
+ * OleStdGetDefaultFileFormatOfClass
+ * OleStdGetAuxUserType
+ * OleStdGetUserTypeOfClass
+ *
+ * (c) Copyright Microsoft Corp. 1992-1993 All Rights Reserved
+ *
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+#include <ctype.h>
+
+OLEDBGDATA
+
+// Replacement for stdlib atol,
+// which didn't work and doesn't take far pointers.
+// Must be tolerant of leading spaces.
+//
+//
+static LONG Atol(LPTSTR lpsz)
+{
+ signed int sign = +1;
+ UINT base = 10;
+ LONG l = 0;
+
+ if (NULL==lpsz)
+ {
+ OleDbgAssert (0);
+ return 0;
+ }
+ while (isspace(*lpsz))
+ lpsz++;
+
+ if (*lpsz=='-')
+ {
+ lpsz++;
+ sign = -1;
+ }
+ if (lpsz[0]==TEXT('0') && lpsz[1]==TEXT('x'))
+ {
+ base = 16;
+ lpsz+=2;
+ }
+
+ if (base==10)
+ {
+ while (isdigit(*lpsz))
+ {
+ l = l * base + *lpsz - '0';
+ lpsz++;
+ }
+ }
+ else
+ {
+ OleDbgAssert (base==16);
+ while (isxdigit(*lpsz))
+ {
+ l = l * base + isdigit(*lpsz) ? *lpsz - '0' : toupper(*lpsz) - 'A' + 10;
+ lpsz++;
+ }
+ }
+ return l * sign;
+}
+
+
+
+/*
+ * OleStdGetUserTypeOfClass(REFCLSID, LPSTR, UINT, HKEY)
+ *
+ * Purpose:
+ * Returns the user type (human readable class name) of the specified class.
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve user type of.
+ * lpszUserType pointer to buffer to return user type in.
+ * cch length of buffer pointed to by lpszUserType
+ * hKey hKey for reg db - if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \ root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ *
+ * Return Value:
+ * UINT Number of characters in returned string. 0 on error.
+ *
+ */
+STDAPI_(UINT) OleStdGetUserTypeOfClass(REFCLSID rclsid, LPTSTR lpszUserType, UINT cch, HKEY hKey)
+{
+
+ LONG dw;
+ LONG lRet;
+ LPSTR lpszCLSID, lpszProgID;
+ BOOL fFreeProgID = FALSE;
+ BOOL bCloseRegDB = FALSE;
+ TCHAR szKey[128];
+ LPMALLOC lpIMalloc;
+
+ if (!lpszUserType)
+ return 0;
+
+ *lpszUserType = TEXT('\0');
+ if (hKey == NULL)
+ {
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return (UINT)FALSE;
+
+ bCloseRegDB = TRUE;
+ }
+
+ // Get a string containing the class name
+ StringFromCLSIDA(rclsid, &lpszCLSID);
+
+ wsprintf(szKey, TEXT("CLSID\\%s"), lpszCLSID);
+
+ dw=cch;
+ lRet = RegQueryValue(hKey, szKey, lpszUserType, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet) {
+ // Load 'Unknown Source' and 'Unknown Type' strings
+ dw = (LONG)LoadString(ghInst, IDS_PSUNKNOWNTYPE, lpszUserType, cch);
+ }
+
+ if ( ((LONG)ERROR_SUCCESS!=lRet) && (CoIsOle1Class(rclsid)) )
+ {
+ // We've got an OLE 1.0 class, so let's try to get the user type
+ // name from the ProgID entry.
+
+ ProgIDFromCLSIDA(rclsid, &lpszProgID);
+ fFreeProgID = TRUE;
+
+ dw = cch;
+ lRet = RegQueryValue(hKey, lpszProgID, lpszUserType, &dw);
+
+ if ((LONG)ERROR_SUCCESS != lRet)
+ dw = 0;
+ }
+
+
+ if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
+ {
+ if (fFreeProgID)
+ lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszProgID);
+
+ lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ }
+
+ if (bCloseRegDB)
+ RegCloseKey(hKey);
+
+ return (UINT)dw;
+
+}
+
+
+
+/*
+ * OleStdGetAuxUserType(RCLSID, WORD, LPSTR, int, HKEY)
+ *
+ * Purpose:
+ * Returns the specified AuxUserType from the reg db.
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve aux user type of.
+ * hKey hKey for reg db - if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \ root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ * wAuxUserType which aux user type field to look for. In 4/93 release
+ * 2 is short name and 3 is exe name.
+ * lpszUserType pointer to buffer to return user type in.
+ * cch length of buffer pointed to by lpszUserType
+ *
+ * Return Value:
+ * UINT Number of characters in returned string. 0 on error.
+ *
+ */
+STDAPI_(UINT) OleStdGetAuxUserType(REFCLSID rclsid,
+ WORD wAuxUserType,
+ LPTSTR lpszAuxUserType,
+ int cch,
+ HKEY hKey)
+{
+ HKEY hThisKey;
+ BOOL fCloseRegDB = FALSE;
+ LONG dw;
+ LRESULT lRet;
+ LPTSTR lpszCLSID;
+ LPMALLOC lpIMalloc;
+ TCHAR szKey[OLEUI_CCHKEYMAX];
+ TCHAR szTemp[32];
+
+ lpszAuxUserType[0] = TEXT('\0');
+
+ if (NULL == hKey)
+ {
+ lRet = RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hThisKey);
+
+ if (ERROR_SUCCESS != lRet)
+ return 0;
+ }
+ else
+ hThisKey = hKey;
+
+ StringFromCLSIDA(rclsid, &lpszCLSID);
+
+ lstrcpy(szKey, TEXT("CLSID\\"));
+ lstrcat(szKey, lpszCLSID);
+ wsprintf(szTemp, TEXT("\\AuxUserType\\%d"), wAuxUserType);
+ lstrcat(szKey, szTemp);
+
+ dw = cch;
+
+ lRet = RegQueryValue(hThisKey, szKey, lpszAuxUserType, &dw);
+
+ if (ERROR_SUCCESS != lRet) {
+ dw = 0;
+ lpszAuxUserType[0] = TEXT('\0');
+ }
+
+
+ if (fCloseRegDB)
+ RegCloseKey(hThisKey);
+
+ if (NOERROR == CoGetMalloc(MEMCTX_TASK, &lpIMalloc))
+ {
+ lpIMalloc->lpVtbl->Free(lpIMalloc, (LPVOID)lpszCLSID);
+ lpIMalloc->lpVtbl->Release(lpIMalloc);
+ }
+
+ return (UINT)dw;
+}
+
+
+
+/*
+ * OleStdGetMiscStatusOfClass(REFCLSID, HKEY)
+ *
+ * Purpose:
+ * Returns the value of the misc status for the given clsid.
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve user type of.
+ * hKey hKey for reg db - if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \\CLSID root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ *
+ * Return Value:
+ * BOOL TRUE on success, FALSE on failure.
+ *
+ */
+STDAPI_(BOOL) OleStdGetMiscStatusOfClass(REFCLSID rclsid, HKEY hKey, DWORD FAR * lpdwValue)
+{
+ DWORD dw;
+ LONG lRet;
+ LPTSTR lpszCLSID;
+ TCHAR szKey[64];
+ TCHAR szMiscStatus[OLEUI_CCHKEYMAX];
+ BOOL bCloseRegDB = FALSE;
+
+ if (hKey == NULL)
+ {
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, TEXT("CLSID"), &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return FALSE;
+
+ bCloseRegDB = TRUE;
+ }
+
+ // Get a string containing the class name
+ StringFromCLSIDA(rclsid, &lpszCLSID);
+
+ // Construct key
+ lstrcpy(szKey, lpszCLSID);
+
+ lstrcat(szKey, TEXT("\\MiscStatus"));
+
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet = RegQueryValue(hKey, szKey, (LPTSTR)szMiscStatus, &dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ {
+ OleStdFreeString(lpszCLSID, NULL);
+
+ if (bCloseRegDB)
+ RegCloseKey(hKey);
+
+ return FALSE;
+
+ }
+
+ *lpdwValue = Atol((LPTSTR)szMiscStatus);
+
+ OleStdFreeString(lpszCLSID, NULL);
+
+ if (bCloseRegDB)
+ RegCloseKey(hKey);
+
+ return TRUE;
+
+
+}
+
+
+/*
+ * CLIPFORMAT OleStdGetDefaultFileFormatOfClass(REFCLSID, HKEY)
+ *
+ * Purpose:
+ * Returns the default file format of the specified class.
+ * this is entered in REGDB as follows:
+ * CLSID\{...}\DataFormats\DefaultFile = <cfFmt>
+ *
+ * Parameters:
+ * rclsid pointer to the clsid to retrieve user type of.
+ * hKey hKey for reg db- if this is NULL, then we
+ * open and close the reg db within this function. If it
+ * is non-NULL, then we assume it's a valid key to the
+ * \ root and use it without closing it. (useful
+ * if you're doing lots of reg db stuff).
+ *
+ * Return Value:
+ * cfFmt -- DefaultFile format
+ * NULL -- failed to get default file format
+ *
+ */
+STDAPI_(CLIPFORMAT) OleStdGetDefaultFileFormatOfClass(
+ REFCLSID rclsid,
+ HKEY hKey
+)
+{
+ CLIPFORMAT cfFmt = 0;
+ DWORD dw;
+ LONG lRet;
+ LPTSTR lpszCLSID;
+ BOOL bCloseRegDB = FALSE;
+ TCHAR szKey[128];
+ TCHAR szDefaultFile[OLEUI_CCHKEYMAX];
+ BOOL bStatus = TRUE;
+
+
+ if (hKey == NULL)
+ {
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return 0;
+
+ bCloseRegDB = TRUE;
+ }
+
+
+ // Get a string containing the class name
+ StringFromCLSIDA(rclsid, &lpszCLSID);
+
+ // Construct key
+ wsprintf(szKey, TEXT("CLSID\\%s\\DataFormats\\DefaultFile"), lpszCLSID);
+
+ OleStdFreeString(lpszCLSID, NULL);
+
+ dw=OLEUI_CCHKEYMAX_SIZE;
+ lRet = RegQueryValue(hKey, szKey, (LPTSTR)szDefaultFile, (LONG FAR *)&dw);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ bStatus = FALSE;
+ else {
+ /* if the format is a number, then it should refer to one of the
+ ** standard Windows formats.
+ */
+ if (isdigit(szDefaultFile[0]))
+ cfFmt = (CLIPFORMAT)Atol(szDefaultFile);
+ else
+ cfFmt = RegisterClipboardFormat(szDefaultFile);
+ }
+
+ if (bCloseRegDB)
+ RegCloseKey(hKey);
+
+ return cfFmt;
+}
+
+
diff --git a/private/oleutest/letest/ole2ui/regdb.h b/private/oleutest/letest/ole2ui/regdb.h
new file mode 100644
index 000000000..d05bc93b2
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/regdb.h
@@ -0,0 +1,8 @@
+// This file is now OBSOLETE (include olestd.h instead)
+/*
+ * Regdb.h
+ *
+ * (c) Copyright Microsoft Corp. 1992 All Rights Reserved
+ */
+
+// Function prototypes moved to olestd.h
diff --git a/private/oleutest/letest/ole2ui/resimage.c b/private/oleutest/letest/ole2ui/resimage.c
new file mode 100644
index 000000000..8a95f4c71
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/resimage.c
@@ -0,0 +1,363 @@
+/*
+ * RESIMAGE.C
+ *
+ * Implementation of the Results Image control for OLE 2.0 UI dialogs.
+ * We need a separate control for dialogs in order to control the repaints
+ * properly and to provide a clean message interface for the dialog
+ * implementations.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "resimage.h"
+
+OLEDBGDATA
+
+//Flag indicating if we've registered the class
+static BOOL fRegistered=FALSE;
+
+//Bitmap and image dimensions for result images.
+static HBITMAP hBmpResults=NULL;
+static UINT cxBmpResult=0;
+static UINT cyBmpResult=0;
+
+/*
+ * FResultImageInitialize
+ *
+ * Purpose:
+ * Attempts to load result bitmaps for the current display driver
+ * for use in OLE 2.0 UI dialogs. Also registers the ResultImage
+ * control class.
+ *
+ * Parameters:
+ * hInst HINSTANCE instance of the DLL.
+ *
+ * hPrevInst HINSTANCE of the previous instance. Used to
+ * determine whether to register window classes or not.
+ *
+ * lpszClassName LPSTR containing the class name to register the
+ * ResultImage control class with.
+ *
+ * Return Value:
+ * BOOL TRUE if all initialization succeeded, FALSE otherwise.
+ */
+
+BOOL FResultImageInitialize(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpszClassName)
+ {
+ int cx, iBmp;
+ HDC hDC;
+ BITMAP bm;
+
+ WNDCLASS wc;
+
+
+ /*
+ * Determine the aspect ratio of the display we're currently
+ * running on and load the appropriate bitmap into the global
+ * hBmpResults (used from the ResultImage control only).
+ *
+ * By retrieving the logical Y extent of the display driver, you
+ * only have limited possibilities:
+ * LOGPIXELSY Display
+ * ----------------------------------------
+ * 48 CGA (unsupported)
+ * 72 EGA
+ * 96 VGA
+ * 120 8514/a (i.e. HiRes VGA)
+ */
+
+ hDC=GetDC(NULL);
+
+ if (NULL==hDC)
+ return FALSE;
+
+ cx=GetDeviceCaps(hDC, LOGPIXELSY);
+ ReleaseDC(NULL, hDC);
+
+ /*
+ * Instead of single comparisons, check ranges instead, so in case
+ * we get something funky, we'll act reasonable.
+ */
+ if (72 >=cx) iBmp=IDB_RESULTSEGA;
+ if (72 < cx && 120 > cx) iBmp=IDB_RESULTSVGA;
+ if (120 <=cx) iBmp=IDB_RESULTSHIRESVGA;
+
+ hBmpResults=LoadBitmap(hInst, MAKEINTRESOURCE(iBmp));
+
+ if (NULL==hBmpResults)
+ {
+ //On error, fail loading the DLL
+ OleDbgOut1(TEXT("FResultImageInitialize: Failed LoadBitmap.\r\n"));
+ return FALSE;
+ }
+
+ OleDbgOut4(TEXT("FResultImageInitialize: Loaded hBmpResults\r\n"));
+
+ //Now that we have the bitmap, calculate image dimensions
+ GetObject(hBmpResults, sizeof(BITMAP), &bm);
+ cxBmpResult=bm.bmWidth;
+ cyBmpResult=bm.bmHeight/CIMAGESY;
+
+
+ // Only register class if we're the first instance
+ if (hPrevInst)
+ fRegistered = TRUE;
+ else
+ {
+ // Static flag fRegistered guards against calling this function more
+ // than once in the same instance
+
+ if (!fRegistered)
+ {
+ wc.lpfnWndProc =ResultImageWndProc;
+ wc.cbClsExtra =0;
+ wc.cbWndExtra =CBRESULTIMAGEWNDEXTRA;
+ wc.hInstance =hInst;
+ wc.hIcon =NULL;
+ wc.hCursor =LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground =NULL;
+ wc.lpszMenuName =NULL;
+ wc.lpszClassName =lpszClassName;
+ wc.style =CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW;
+
+ fRegistered = RegisterClass(&wc);
+ }
+ }
+
+ return fRegistered;
+}
+
+
+
+
+
+/*
+ * ResultImageUninitialize
+ *
+ * Purpose:
+ * Cleans up anything done in FResultImageInitialize, such as freeing
+ * the bitmaps. Call from WEP.
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * None
+ */
+
+void ResultImageUninitialize(void)
+ {
+ if (NULL!=hBmpResults)
+ {
+ DeleteObject(hBmpResults);
+ }
+
+ return;
+ }
+
+
+
+
+
+
+/*
+ * ResultImageWndProc
+ *
+ * Purpose:
+ * Window Procedure for the ResultImage custom control. Only handles
+ * WM_CREATE, WM_PAINT, and private messages to manipulate the bitmap.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ */
+
+LONG CALLBACK EXPORT ResultImageWndProc(HWND hWnd, UINT iMsg
+ , WPARAM wParam, LPARAM lParam)
+ {
+ UINT iBmp;
+ PAINTSTRUCT ps;
+ HDC hDC;
+
+ //Handle standard Windows messages.
+ switch (iMsg)
+ {
+ case WM_CREATE:
+ SetWindowWord(hWnd, RIWW_IMAGEINDEX, RESULTIMAGE_NONE);
+ return 0L;
+
+ case WM_PAINT:
+ iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
+
+ hDC=BeginPaint(hWnd, &ps);
+
+ if (RESULTIMAGE_NONE!=iBmp)
+ {
+ RECT rc;
+ UINT x, y;
+ HDC hDCDlg;
+ HBRUSH hBr;
+ LOGBRUSH lb;
+ HWND hDlg;
+
+ /*
+ * Our job before using TransparentBlt is to figure out
+ * where to position the result image. We place it centered
+ * on this control, so get our rect's center and subtract
+ * half of the image dimensions.
+ */
+ GetClientRect(hWnd, &rc);
+ x=(rc.right+rc.left-cxBmpResult)/2;
+ y=(rc.bottom+rc.top-cyBmpResult)/2;
+
+ //Get the backgroup color the dialog is using.
+ hDlg=GetParent(hWnd);
+ hDCDlg=GetDC(hDlg);
+#if defined( WIN32 )
+ hBr = (HBRUSH)SendMessage(hDlg,
+ WM_CTLCOLORDLG,
+ (WPARAM)hDCDlg,
+ (LPARAM)hDlg);
+#else
+ hBr = (HBRUSH)SendMessage(hDlg,
+ WM_CTLCOLOR,
+ (WPARAM)hDCDlg,
+ MAKELPARAM(hDlg, CTLCOLOR_DLG));
+#endif
+ ReleaseDC(hDlg, hDCDlg);
+
+ GetObject(hBr, sizeof(LOGBRUSH), &lb);
+ SetBkColor(hDC, lb.lbColor);
+
+ TransparentBlt(hDC, x, y, hBmpResults, 0, iBmp*cyBmpResult
+ , cxBmpResult, cyBmpResult, RGBTRANSPARENT);
+ }
+
+ EndPaint(hWnd, &ps);
+ break;
+
+ case RIM_IMAGESET:
+ //wParam contains the new index.
+ iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
+
+ //Validate the index before changing it and repainting
+ if (RESULTIMAGE_NONE==wParam ||
+ ((RESULTIMAGE_MIN <= wParam) && (RESULTIMAGE_MAX >= wParam)))
+ {
+ SetWindowWord(hWnd, RIWW_IMAGEINDEX, (WORD)wParam);
+ InvalidateRect(hWnd, NULL, FALSE);
+ UpdateWindow(hWnd);
+ }
+
+ //Return the previous index.
+ return iBmp;
+
+ case RIM_IMAGEGET:
+ //Return the current index.
+ iBmp=GetWindowWord(hWnd, RIWW_IMAGEINDEX);
+ return (LONG)iBmp;
+
+ default:
+ return DefWindowProc(hWnd, iMsg, wParam, lParam);
+ }
+
+ return 0L;
+ }
+
+
+
+
+
+
+/*
+ * TransparentBlt
+ *
+ * Purpose:
+ * Given a DC, a bitmap, and a color to assume as transparent in that
+ * bitmap, BitBlts the bitmap to the DC letting the existing background
+ * show in place of the transparent color.
+ *
+ * Parameters:
+ * hDC HDC on which to draw.
+ * x, y UINT location at which to draw the bitmap
+ * hBmp HBITMIP to draw from
+ * xOrg, yOrg UINT coordinates from which to draw the bitamp
+ * cx, cy UINT dimensions of the bitmap to Blt.
+ * cr COLORREF to consider as transparent.
+ *
+ * Return Value:
+ * None
+ */
+
+void TransparentBlt(HDC hDC, UINT x, UINT y, HBITMAP hBmp, UINT xOrg, UINT yOrg
+ , UINT cx, UINT cy, COLORREF cr)
+ {
+ HDC hDCSrc, hDCMid, hMemDC;
+ HBITMAP hBmpMono, hBmpT;
+ HBRUSH hBr, hBrT;
+ COLORREF crBack, crText;
+
+ if (NULL==hBmp)
+ return;
+
+ //Get three intermediate DC's
+ hDCSrc=CreateCompatibleDC(hDC);
+ hDCMid=CreateCompatibleDC(hDC);
+ hMemDC=CreateCompatibleDC(hDC);
+
+ SelectObject(hDCSrc, hBmp);
+
+ //Create a monochrome bitmap for masking
+ hBmpMono=CreateCompatibleBitmap(hDCMid, cx, cy);
+ SelectObject(hDCMid, hBmpMono);
+
+ //Create a middle bitmap
+ hBmpT=CreateCompatibleBitmap(hDC, cx, cy);
+ SelectObject(hMemDC, hBmpT);
+
+
+ //Create a monochrome mask where we have 0's in the image, 1's elsewhere.
+ crBack=SetBkColor(hDCSrc, cr);
+ BitBlt(hDCMid, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
+ SetBkColor(hDCSrc, crBack);
+
+ //Put the unmodified image in the temporary bitmap
+ BitBlt(hMemDC, 0, 0, cx, cy, hDCSrc, xOrg, yOrg, SRCCOPY);
+
+ //Create an select a brush of the background color
+ hBr=CreateSolidBrush(GetBkColor(hDC));
+ hBrT=SelectObject(hMemDC, hBr);
+
+ //Force conversion of the monochrome to stay black and white.
+ crText=SetTextColor(hMemDC, 0L);
+ crBack=SetBkColor(hMemDC, RGB(255, 255, 255));
+
+ /*
+ * Where the monochrome mask is 1, Blt the brush; where the mono mask
+ * is 0, leave the destination untouches. This results in painting
+ * around the image with the background brush. We do this first
+ * in the temporary bitmap, then put the whole thing to the screen.
+ */
+ BitBlt(hMemDC, 0, 0, cx, cy, hDCMid, 0, 0, ROP_DSPDxax);
+ BitBlt(hDC, x, y, cx, cy, hMemDC, 0, 0, SRCCOPY);
+
+
+ SetTextColor(hMemDC, crText);
+ SetBkColor(hMemDC, crBack);
+
+ SelectObject(hMemDC, hBrT);
+ DeleteObject(hBr);
+
+ DeleteDC(hMemDC);
+ DeleteDC(hDCSrc);
+ DeleteDC(hDCMid);
+ DeleteObject(hBmpT);
+ DeleteObject(hBmpMono);
+
+ return;
+ }
diff --git a/private/oleutest/letest/ole2ui/resimage.h b/private/oleutest/letest/ole2ui/resimage.h
new file mode 100644
index 000000000..31640be91
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/resimage.h
@@ -0,0 +1,61 @@
+/*
+ * RESIMAGE.H
+ *
+ * Structures and definitions for the ResultImage control.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _RESIMAGE_H_
+#define _RESIMAGE_H_
+
+
+/*
+ * Indices into the bitmaps to extract the right image. Each bitmap
+ * contains five images arranged vertically, so the offset to the correct
+ * image is (iImage*cy)
+ */
+
+#define RESULTIMAGE_NONE 0xFFFF
+#define RESULTIMAGE_PASTE 0
+#define RESULTIMAGE_EMBED 1
+#define RESULTIMAGE_EMBEDICON 2
+#define RESULTIMAGE_LINK 3
+#define RESULTIMAGE_LINKICON 4
+#define RESULTIMAGE_LINKTOLINK 5
+#define RESULTIMAGE_LINKTOLINKICON 6
+
+#define RESULTIMAGE_MIN 0
+#define RESULTIMAGE_MAX 6
+
+
+//Total number of images in each bitmap.
+#define CIMAGESY (RESULTIMAGE_MAX+1)
+
+//The color to use for transparancy (cyan)
+#define RGBTRANSPARENT RGB(0, 255, 255)
+
+
+//Function prototypes
+BOOL FResultImageInitialize(HINSTANCE, HINSTANCE, LPTSTR);
+void ResultImageUninitialize(void);
+LONG CALLBACK EXPORT ResultImageWndProc(HWND, UINT, WPARAM, LPARAM);
+void TransparentBlt(HDC, UINT, UINT, HBITMAP, UINT, UINT, UINT, UINT, COLORREF);
+
+
+//Window extra bytes contain the bitmap index we deal with currently.
+#define CBRESULTIMAGEWNDEXTRA sizeof(UINT)
+#define RIWW_IMAGEINDEX 0
+
+
+//Control messages
+#define RIM_IMAGESET (WM_USER+0)
+#define RIM_IMAGEGET (WM_USER+1)
+
+
+//Special ROP code for TransparentBlt.
+#define ROP_DSPDxax 0x00E20746
+
+
+#endif //_RESIMAGE_H_
diff --git a/private/oleutest/letest/ole2ui/stdpal.c b/private/oleutest/letest/ole2ui/stdpal.c
new file mode 100644
index 000000000..abe3e82ac
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/stdpal.c
@@ -0,0 +1,94 @@
+/*-----------------------------------------------------------------------
+| stdpal.c
+|
+| Standard App Palette useful for OLE applications. v 1.01
+|
+| NOTE: Palette MUST be created with OleStdCreateStandardPalette
+|
+| Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
+|
+-----------------------------------------------------------------------*/
+
+#ifndef PC_RESERVED
+#ifndef INC_OLE2
+ #define INC_OLE2
+#endif
+
+#undef UNICODE
+#include <windows.h>
+#include <ole2.h>
+#endif
+
+#include "stdpal.h"
+
+#define cpeAppPal 256 // number of colors in our apps palette
+typedef struct
+ {
+ WORD wVersion;
+ WORD cpe;
+ PALETTEENTRY rgpe[cpeAppPal];
+ } LOGPAL;
+
+
+/*-----------------------------------------------------------------------
+| OleStdCreateStandardPalette
+|
+| Creates the standard Apps palette. Create one of these for your
+| app, and select/realize it into each DC.
+|
+| Arguments:
+| void:
+|
+| Returns:
+|
+| Keywords:
+-----------------------------------------------------------------------*/
+STDAPI_(HPALETTE) OleStdCreateStandardPalette(void)
+ {
+ HDC hdc;
+ HPALETTE hpal;
+
+ hpal = (HPALETTE) NULL;
+ hdc = GetDC(NULL);
+ if (hdc != NULL && GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)
+ {
+ int cpeSysPal;
+ int cpeReserved;
+
+ cpeSysPal = GetDeviceCaps(hdc, SIZEPALETTE);
+ cpeReserved = GetDeviceCaps(hdc, NUMRESERVED);
+ if (cpeSysPal > cpeReserved)
+ {
+ int cpeReserved2;
+ unsigned char FAR* lpb;
+ PALETTEENTRY FAR* ppe;
+ PALETTEENTRY FAR* ppeMac;
+ LOGPAL logpal;
+
+ cpeReserved2 = cpeReserved/2;
+
+ // Get the system palette entries at the beginning and end.
+ GetSystemPaletteEntries(hdc, 0, cpeReserved2, logpal.rgpe);
+ GetSystemPaletteEntries(hdc, cpeSysPal - cpeReserved2, cpeReserved2,
+ &logpal.rgpe[cpeAppPal-cpeReserved2]);
+
+ logpal.cpe = cpeAppPal;
+ logpal.wVersion = 0x300;
+
+ lpb = (BYTE FAR *) &palSVGA[10];
+ ppe = (PALETTEENTRY FAR*)&logpal.rgpe[cpeReserved2];
+ ppeMac = (PALETTEENTRY FAR*)&logpal.rgpe[cpeAppPal-cpeReserved2];
+ while (ppe < ppeMac)
+ {
+ ppe->peFlags = PC_NOCOLLAPSE;
+ ppe->peRed = *lpb++;
+ ppe->peGreen = *lpb++;
+ ppe->peBlue = *lpb++;
+ ppe++;
+ }
+ hpal = CreatePalette((LOGPALETTE FAR *)&logpal);
+ }
+ }
+ ReleaseDC(NULL, hdc);
+ return hpal;
+ }
diff --git a/private/oleutest/letest/ole2ui/stdpal.h b/private/oleutest/letest/ole2ui/stdpal.h
new file mode 100644
index 000000000..59162ed78
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/stdpal.h
@@ -0,0 +1,292 @@
+/*-----------------------------------------------------------------------
+| stdpal.h
+|
+| Standard App Palette useful for OLE applications. v 1.01
+|
+| #include this file in the same file as HpalCreateAppPalette
+|
+| NOTE: Palette MUST be created with HpalCreateAppPalette
+|
+| Copyright (c) 1992 - 1993 Microsoft Corporation. All rights reserved.
+|
+-----------------------------------------------------------------------*/
+
+#include <commdlg.h> // needed for LPPRINTDLG
+#include <shellapi.h> // needed for HKEY
+
+#ifdef WIN32
+#define _based(A)
+#define _segname(A)
+#endif
+
+#ifndef CSCONST
+#ifdef FLAT
+#define CSCONST(type) type const
+#else
+#define CSCONST(type) type _based(_segname("_CODE")) const
+#endif
+#endif
+
+CSCONST(unsigned char) palSVGA[256][3] =
+ {
+ // R G B
+ {0x00, 0x00, 0x00}, // 0 Sys Black gray 0
+ {0x80, 0x00, 0x00}, // 1 Sys Dk Red
+ {0x00, 0x80, 0x00}, // 2 Sys Dk Green
+ {0x80, 0x80, 0x00}, // 3 Sys Dk Yellow
+ {0x00, 0x00, 0x80}, // 4 Sys Dk Blue
+ {0x80, 0x00, 0x80}, // 5 Sys Dk Violet
+ {0x00, 0x80, 0x80}, // 6 Sys Dk Cyan
+ {0xc0, 0xc0, 0xc0}, // 7 Sys Lt Grey gray 192
+ {0xc0, 0xdc, 0xc0}, // 8 Sys 8
+ {0xa6, 0xca, 0xf0}, // 9 Sys 9 (the first 10 are fixed by Windows)
+
+ {0x80, 0x00, 0x00}, // 10 Sys Dk Red repeat
+ {0x00, 0x80, 0x00}, // 11 Sys Dk Green repeat
+ {0x80, 0x80, 0x00}, // 12 Sys Dk Yellow repeat
+ {0x00, 0x00, 0x80}, // 13 Sys Dk Blue repeat
+ {0x80, 0x00, 0x80}, // 14 Sys Dk Violet repeat
+ {0x00, 0x80, 0x80}, // 15 Sys Dk Cyan repeat
+ {0x80, 0x80, 0x80}, // 16 Sys Dk Grey repeat gray 128
+ {0x80, 0x80, 0xff}, // 17 Excel Chart Fill 1
+ {0x80, 0x20, 0x60}, // 18 Excel Chart Fill 2
+ {0xff, 0xff, 0xc0}, // 19 Excel Chart Fill 3
+ {0xa0, 0xe0, 0xe0}, // 20 Excel Chart Fill 4
+ {0x60, 0x00, 0x80}, // 21 Excel Chart Fill 4
+ {0xff, 0x80, 0x80}, // 22 Excel Chart Fill 6
+ {0x00, 0x80, 0xc0}, // 23 Excel Chart Fill 7
+ {0xc0, 0xc0, 0xff}, // 24 Excel Chart Fill 8
+ {0x00, 0xcf, 0xff}, // 25 Excel clrt entry
+ {0x69, 0xff, 0xff}, // 26 Excel clrt entry
+ {0xe0, 0xff, 0xe0}, // 27 Excel clrt entry
+ {0xdd, 0x9c, 0xb3}, // 28 Excel clrt entry
+ {0xb3, 0x8f, 0xee}, // 29 Excel clrt entry
+ {0x2a, 0x6f, 0xf9}, // 30 Excel clrt entry
+ {0x3f, 0xb8, 0xcd}, // 31 Excel clrt entry
+ {0x48, 0x84, 0x36}, // 32 Excel clrt entry
+ {0x95, 0x8c, 0x41}, // 33 Excel clrt entry
+ {0x8e, 0x5e, 0x42}, // 34 Excel clrt entry
+ {0xa0, 0x62, 0x7a}, // 35 Excel clrt entry
+ {0x62, 0x4f, 0xac}, // 36 Excel clrt entry
+ {0x1d, 0x2f, 0xbe}, // 37 Excel clrt entry
+ {0x28, 0x66, 0x76}, // 38 Excel clrt entry
+ {0x00, 0x45, 0x00}, // 39 Excel clrt entry
+ {0x45, 0x3e, 0x01}, // 40 Excel clrt entry
+ {0x6a, 0x28, 0x13}, // 41 Excel clrt entry
+ {0x85, 0x39, 0x6a}, // 42 Excel clrt entry
+ {0x4a, 0x32, 0x85}, // 43 Excel clrt entry
+ {0x04, 0x04, 0x04}, // 44 gray 4
+ {0x08, 0x08, 0x08}, // 45 gray 8
+ {0x0c, 0x0c, 0x0c}, // 46 gray 12
+ {0x11, 0x11, 0x11}, // 47 gray 17
+ {0x16, 0x16, 0x16}, // 48 gray 22
+ {0x1c, 0x1c, 0x1c}, // 49 gray 28
+ {0x22, 0x22, 0x22}, // 50 gray 34
+ {0x29, 0x29, 0x29}, // 51 gray 41
+ {0x30, 0x30, 0x30}, // 52 gray 48
+ {0x5f, 0x5f, 0x5f}, // 53 swapped so inversions look good gray 95
+ {0x55, 0x55, 0x55}, // 54 swapped so inversions look good gray 85
+ {0x4d, 0x4d, 0x4d}, // 55 swapped so inversions look good gray 77
+ {0x42, 0x42, 0x42}, // 56 swapped so inversions look good gray 66
+ {0x39, 0x39, 0x39}, // 57 swapped so inversions look good gray 57
+ {0x00, 0x07, 0x00}, // 58
+ {0x0d, 0x00, 0x00}, // 59
+ {0xb7, 0x99, 0x81}, // 60
+ {0x84, 0x99, 0xb4}, // 61
+ {0xbd, 0xbd, 0x90}, // 62
+ {0x7f, 0x7f, 0x60}, // 63
+ {0x60, 0x60, 0x7f}, // 64
+ {0x00, 0x0e, 0x00}, // 65
+ {0x1b, 0x00, 0x00}, // 66
+ {0x28, 0x00, 0x00}, // 67
+ {0x08, 0x09, 0x2b}, // 68
+ {0x00, 0x1d, 0x00}, // 69
+ {0x39, 0x00, 0x00}, // 70
+ {0x00, 0x00, 0x9b}, // 71
+ {0x00, 0x25, 0x00}, // 72
+ {0x49, 0x00, 0x00}, // 73
+ {0x11, 0x11, 0x3b}, // 74
+ {0x00, 0x2f, 0x00}, // 75
+ {0x5d, 0x00, 0x00}, // 76
+ {0x17, 0x17, 0x45}, // 77
+ {0x00, 0x3a, 0x00}, // 78
+ {0x49, 0x11, 0x11}, // 79
+ {0x1c, 0x1c, 0x53}, // 80
+ {0x00, 0x16, 0xff}, // 81
+ {0x2b, 0x00, 0xff}, // 82
+ {0x21, 0x21, 0x6c}, // 83
+ {0x59, 0x14, 0x14}, // 84
+ {0x00, 0x51, 0x00}, // 85
+ {0x47, 0x1a, 0x6a}, // 86
+ {0x19, 0x32, 0x67}, // 87
+ {0x00, 0x61, 0x00}, // 88
+ {0x00, 0x31, 0xff}, // 89
+ {0x61, 0x00, 0xff}, // 90
+ {0x53, 0x20, 0x7b}, // 91
+ {0x16, 0x43, 0x67}, // 92
+ {0x2e, 0x2e, 0xe2}, // 93
+ {0x26, 0x59, 0x16}, // 94
+ {0x51, 0x46, 0x04}, // 95
+ {0x68, 0x2e, 0x49}, // 96
+ {0x07, 0x52, 0x8f}, // 97
+ {0x6a, 0x18, 0xb8}, // 98
+ {0x90, 0x23, 0x15}, // 99
+ {0x00, 0x53, 0xff}, // 100
+ {0xa3, 0x00, 0xff}, // 101
+ {0x6a, 0x4a, 0x12}, // 102
+ {0x75, 0x33, 0x6c}, // 103
+ {0x4a, 0x41, 0x9a}, // 104
+ {0x37, 0x65, 0x0b}, // 105
+ {0xa4, 0x2c, 0x15}, // 106
+ {0x83, 0x1f, 0xb1}, // 107
+ {0x4e, 0x2c, 0xff}, // 108
+ {0x20, 0x51, 0xb6}, // 109
+ {0x08, 0x64, 0x92}, // 110
+ {0x6f, 0x56, 0x0b}, // 111
+ {0x59, 0x43, 0xad}, // 112
+ {0x36, 0x72, 0x12}, // 113
+ {0xb0, 0x33, 0x17}, // 114
+ {0x00, 0xa1, 0x00}, // 115
+ {0x77, 0x5f, 0x1f}, // 116
+ {0x89, 0x47, 0x71}, // 117
+ {0xb0, 0x43, 0x1c}, // 118
+ {0xb7, 0x2d, 0x7d}, // 119
+ {0x00, 0x86, 0x95}, // 120
+ {0x7a, 0x6e, 0x23}, // 121
+ {0x26, 0x9f, 0x00}, // 122
+ {0x73, 0xa9, 0x01}, // 123
+ {0x00, 0x00, 0x00}, // 124 free 0 gray 0
+ {0x00, 0x00, 0x00}, // 125 free 2 gray 0
+ {0x00, 0x00, 0x00}, // 126 free 4 gray 0
+ {0x00, 0x00, 0x00}, // 127 free 6 gray 0
+ {0x00, 0x00, 0x00}, // 128 free 7 gray 0
+ {0x00, 0x00, 0x00}, // 129 free 5 gray 0
+ {0x00, 0x00, 0x00}, // 130 free 3 gray 0
+ {0x00, 0x00, 0x00}, // 131 free 1 gray 0
+ {0x00, 0xca, 0x00}, // 132
+ {0xac, 0x5b, 0x01}, // 133
+ {0x20, 0x1d, 0xc2}, // 134
+ {0x94, 0x52, 0x70}, // 135
+ {0x24, 0xaa, 0x4c}, // 136
+ {0x0a, 0x94, 0x89}, // 137
+ {0x36, 0x6e, 0x7b}, // 138
+ {0x44, 0x75, 0x90}, // 139
+ {0xff, 0x00, 0xa8}, // 140
+ {0x00, 0x71, 0xff}, // 141
+ {0xdf, 0x00, 0xff}, // 142
+ {0x56, 0x91, 0x4a}, // 143
+ {0x34, 0x48, 0xf8}, // 144
+ {0xcc, 0x32, 0x82}, // 145
+ {0xe4, 0x41, 0x70}, // 146
+ {0x68, 0xca, 0x01}, // 147
+ {0x36, 0xbc, 0x42}, // 148
+ {0x00, 0x9a, 0xff}, // 149
+ {0x96, 0x22, 0xb7}, // 150
+ {0x85, 0x7d, 0x33}, // 151
+ {0x25, 0xb7, 0x8c}, // 152
+ {0x36, 0x5a, 0xed}, // 153
+ {0x5c, 0xff, 0x00}, // 154
+ {0xff, 0x48, 0x00}, // 155
+ {0x22, 0x9b, 0xa2}, // 156
+ {0x42, 0xcf, 0x4d}, // 157
+ {0xc2, 0x58, 0x52}, // 158
+ {0x20, 0xd3, 0x95}, // 159
+ {0xa5, 0x24, 0xe0}, // 160
+ {0x73, 0x56, 0xb5}, // 161
+ {0xa9, 0xa9, 0x00}, // 162
+ {0xd0, 0x6f, 0x3c}, // 163
+ {0x67, 0x9f, 0x58}, // 164
+ {0x89, 0xcf, 0x0b}, // 165
+ {0xff, 0xac, 0x00}, // 166
+ {0xa7, 0x2e, 0xfe}, // 167
+ {0xe2, 0x59, 0x7f}, // 168
+ {0x4c, 0xdc, 0x67}, // 169
+ {0xff, 0x18, 0xff}, // 170
+ {0x3a, 0x7d, 0xff}, // 171
+ {0xb1, 0xd0, 0x18}, // 172
+ {0xc7, 0xff, 0x00}, // 173
+ {0xff, 0xe2, 0x00}, // 174
+ {0xdf, 0x9a, 0x3d}, // 175
+ {0x56, 0x81, 0x9f}, // 176
+ {0xc6, 0x43, 0xba}, // 177
+ {0xaf, 0x71, 0x8b}, // 178
+ {0x38, 0xa2, 0xc9}, // 179
+ {0xd1, 0x53, 0xce}, // 180
+ {0xff, 0x9a, 0x65}, // 181
+ {0x46, 0xca, 0xdb}, // 182
+ {0xff, 0x4d, 0xff}, // 183
+ {0xc8, 0xe9, 0x6a}, // 184
+ {0x4c, 0xde, 0xe0}, // 185
+ {0xff, 0x98, 0xff}, // 186
+ {0xdf, 0xc0, 0x82}, // 187
+ {0xe9, 0xec, 0xa5}, // 188
+ {0xf5, 0xf6, 0xcd}, // 189
+ {0xff, 0xd0, 0xff}, // 190
+ {0xb1, 0xac, 0x5a}, // 191
+ {0x63, 0x91, 0xae}, // 192
+ {0x22, 0x4c, 0x65}, // 193
+ {0x8d, 0x4e, 0x3f}, // 194
+ {0x50, 0x70, 0x70}, // 195
+ {0xd0, 0xff, 0xff}, // 196
+ {0xff, 0xe7, 0xff}, // 197
+ {0x69, 0x69, 0x69}, // 198 gray 105
+ {0x77, 0x77, 0x77}, // 199 gray 119
+ {0x86, 0x86, 0x86}, // 200 gray 134
+ {0x96, 0x96, 0x96}, // 201 gray 150
+ {0x9d, 0x9d, 0x9d}, // 202 gray 157
+ {0xa4, 0xa4, 0xa4}, // 203 gray 164
+ {0xb2, 0xb2, 0xb2}, // 204 gray 178
+ {0xcb, 0xcb, 0xcb}, // 205 gray 203
+ {0xd7, 0xd7, 0xd7}, // 206 gray 215
+ {0xdd, 0xdd, 0xdd}, // 207 gray 221
+ {0xe3, 0xe3, 0xe3}, // 208 gray 227
+ {0xea, 0xea, 0xea}, // 209 gray 234
+ {0xf1, 0xf1, 0xf1}, // 210 gray 241
+ {0xf8, 0xf8, 0xf8}, // 211 gray 248
+ {0xb2, 0xc1, 0x66}, // 212
+ {0x80, 0xbf, 0x78}, // 213
+ {0xc6, 0xf0, 0xf0}, // 214
+ {0xb2, 0xa4, 0xff}, // 215
+ {0xff, 0xb3, 0xff}, // 216
+ {0xd1, 0x8e, 0xa3}, // 217
+ {0xc3, 0xdc, 0x37}, // 218
+ {0xa0, 0x9e, 0x54}, // 219
+ {0x76, 0xae, 0x70}, // 220
+ {0x78, 0x9e, 0xc1}, // 221
+ {0x83, 0x64, 0xbf}, // 222
+ {0xa4, 0x83, 0xd3}, // 223
+ {0xd1, 0x3f, 0x32}, // 224
+ {0xff, 0x7d, 0x00}, // 225
+ {0x44, 0x78, 0x23}, // 226
+ {0x24, 0x5f, 0x60}, // 227
+ {0x0e, 0x0e, 0x2c}, // 228
+ {0xbe, 0x00, 0x00}, // 229
+ {0xff, 0x1f, 0x00}, // 230
+ {0x31, 0x39, 0x00}, // 231
+ {0xd9, 0x85, 0x3e}, // 232
+ {0x02, 0x77, 0x85}, // 233
+ {0xb0, 0xd8, 0x81}, // 234
+ {0x56, 0x21, 0x1d}, // 235
+ {0x00, 0x00, 0x30}, // 236
+ {0x88, 0xc8, 0xb3}, // 237
+ {0xa0, 0x79, 0x00}, // 238
+ {0xc0, 0xc0, 0xc0}, // 239 Sys Dk Grey repeat inversion gray 192
+ {0xea, 0x70, 0x81}, // 240
+ {0x51, 0xf1, 0x69}, // 241
+ {0xff, 0xff, 0x80}, // 242
+ {0x91, 0x74, 0xcd}, // 243
+ {0xff, 0x7c, 0xff}, // 244
+ {0xa2, 0xff, 0xff}, // 245
+
+ {0xff, 0xfb, 0xf0}, // 246 Sys Reserved
+ {0xa0, 0xa0, 0xa4}, // 247 Sys Reserved
+ {0x80, 0x80, 0x80}, // 248 Sys Lt Gray gray 128
+ {0xff, 0x00, 0x00}, // 249 Sys Red
+ {0x00, 0xff, 0x00}, // 250 Sys Green
+ {0xff, 0xff, 0x00}, // 251 Sys Yellow
+ {0x00, 0x00, 0xff}, // 252 Sys Blue
+ {0xff, 0x00, 0xff}, // 253 Sys Violet
+ {0x00, 0xff, 0xff}, // 254 Sys Cyan
+ {0xff, 0xff, 0xff} // 255 Sys White gray 255
+ };
+
diff --git a/private/oleutest/letest/ole2ui/strings.rc b/private/oleutest/letest/ole2ui/strings.rc
new file mode 100644
index 000000000..f3f8c415a
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/strings.rc
@@ -0,0 +1,124 @@
+/*
+ * STRINGS.RC
+ *
+ * strings for the OLE 2.0 UI Support Library.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#include "ole2ui.h"
+
+
+//Stringtable common for all dialogs.
+STRINGTABLE
+ BEGIN
+ IDS_FILTERS, "All Files (*.*)|*.*|"
+ IDS_ICONFILTERS, "Icon Files|*.exe;*.dll;*.ico|Programs (*.exe)|*.exe|Libraries (*.dll)|Icons (*.ico)|All Files (*.*)|*.*|"
+ END
+
+// browse dialog
+STRINGTABLE
+ BEGIN
+ IDS_BROWSE "Browse"
+ END
+
+
+//Insert Object stringtable.
+STRINGTABLE
+ BEGIN
+ IDS_IORESULTNEW, "Inserts a new %s object into your document."
+ IDS_IORESULTNEWICON, "Inserts a new %s object into your document. It will be displayed as an icon."
+ IDS_IORESULTFROMFILE1, "Inserts the contents of the file as an object into your document so that you may activate it using the "
+ IDS_IORESULTFROMFILE2, "application which created it."
+ IDS_IORESULTFROMFILEICON2, "application which created it. It will be displayed as an icon."
+ IDS_IORESULTLINKFILE1, "Inserts a picture of the file contents into your document. The picture will be linked to "
+ IDS_IORESULTLINKFILE2, "the file so that changes to the file will be reflected in your document."
+ IDS_IORESULTLINKFILEICON1, "Inserts an icon into your document which represents the file. The icon will be linked to "
+ IDS_IORESULTLINKFILEICON2, "the file so that changes to the file will be reflected in your document."
+ END
+
+//Change Icon stringtable
+STRINGTABLE
+ BEGIN
+ IDS_CINOICONSINFILE, "There are no icons in %s."
+ IDS_CIINVALIDFILE, "File %s does not exist."
+ IDS_CIFILEACCESS, "Unable to open file %s. Access denied."
+ IDS_CIFILESHARE, "Unable to open file %s. Sharing violation."
+ IDS_CIFILEOPENFAIL, "Unable to open file %s. General failure."
+ END
+
+// Convert stringtable.
+STRINGTABLE
+ BEGIN
+ IDS_CVRESULTCONVERTLINK, "A linked object must be converted at the source."
+ IDS_CVRESULTCONVERTTO, "Permanently changes the selected %s object to a %s object."
+ IDS_CVRESULTNOCHANGE, "The selected %s object will not be converted."
+ IDS_CVRESULTDISPLAYASICON, " It will be displayed as an icon."
+ IDS_CVRESULTACTIVATEAS, "Every %s object will be activated as a %s object"
+ IDS_CVRESULTACTIVATEDIFF, ", but it will not be converted."
+ END
+
+//Paste Special stringtable
+STRINGTABLE
+ BEGIN
+ IDS_PSPASTEDATA, "Inserts the contents of the Clipboard into your document as %s."
+ IDS_PSPASTEOBJECT, "Inserts the contents of the Clipboard into your document so that you may activate it using %s."
+ IDS_PSPASTEOBJECTASICON, "Inserts the contents of the Clipboard into your document so that you may activate it using %s. It will be displayed as an icon."
+ IDS_PSPASTELINKDATA, "Inserts the contents of the Clipboard into your document as %s. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document."
+ IDS_PSPASTELINKOBJECT, "Inserts a picture of the Clipboard contents into your document. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document."
+ IDS_PSPASTELINKOBJECTASICON, "Inserts an icon into your document which represents the Clipboard contents. Paste Link creates a link to the source file so that changes to the source file will be reflected in your document."
+ IDS_PSNONOLE, "Inserts the contents of the Clipboard into your document."
+ IDS_PSUNKNOWNTYPE, "Unknown Type"
+ IDS_PSUNKNOWNSRC, "Unknown Source"
+ IDS_PSUNKNOWNAPP, "the application which created it"
+ END
+
+// Busy/Blocked dialog stringtable
+STRINGTABLE
+ BEGIN
+ IDS_BZRESULTTEXTBUSY "This action cannot be completed because the %s application (%s) is busy. Choose ""Switch To"" to activate %s and correct the problem."
+ IDS_BZRESULTTEXTNOTRESPONDING "This action cannot be completed because the %s application (%s) is not responding. Choose ""Switch To"" to activate %s and correct the problem."
+ END
+
+// OLESTD stringtable
+STRINGTABLE
+ BEGIN
+ IDS_OLESTDNOCREATEFILE, "Could not create file!"
+ IDS_OLESTDNOOPENFILE, "Could not open file!"
+ IDS_OLESTDDISKFULL, "Disk full--unable to complete save operation"
+ END
+
+// OLE2UI stringtable
+STRINGTABLE
+ BEGIN
+ IDS_OLE2UIEDITNOOBJCMD, "&Object"
+ IDS_OLE2UIEDITLINKCMD_1VERB, "0%s Linked %s &Object"
+ IDS_OLE2UIEDITOBJECTCMD_1VERB, "0%s %s &Object"
+ IDS_OLE2UIEDITLINKCMD_NVERB, "Linked %s &Object"
+ IDS_OLE2UIEDITOBJECTCMD_NVERB, "%s &Object"
+ IDS_OLE2UIUNKNOWN, "Unknown"
+ IDS_OLE2UILINK, "Link"
+ IDS_OLE2UIOBJECT, "Object"
+ IDS_OLE2UIEDIT, "&Edit"
+ IDS_OLE2UICONVERT, "&Convert..."
+ IDS_DEFICONLABEL, "Document"
+ IDS_OLE2UIPASTELINKEDTYPE, "Linked %s"
+ END
+
+// LINKS stringtable
+STRINGTABLE
+ BEGIN
+ IDS_LINK_AUTO "Automatic"
+ IDS_LINK_MANUAL "Manual"
+ IDS_LINK_UNKNOWN "Unavail"
+ IDS_LINKS "Links"
+ IDS_FAILED "Operation failed!"
+ IDS_CHANGESOURCE "Change Source"
+ IDS_INVALIDSOURCE "Invalid Source : Do you want to correct it?"
+ IDS_CHANGEADDITIONALLINKS "The selected link has been changed.\nThis document contains additional links to\n%s.\n\nChange additional links?"
+ IDS_ERR_GETLINKSOURCE "Fail to get source of the link!"
+ IDS_ERR_GETLINKUPDATEOPTIONS "Fail to get update option of the link!"
+ IDS_ERR_ADDSTRING "Fail to add item to ListBox!"
+ IDS_CLOSE "Close"
+ END
diff --git a/private/oleutest/letest/ole2ui/suminfo.cpp b/private/oleutest/letest/ole2ui/suminfo.cpp
new file mode 100644
index 000000000..528fe2540
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/suminfo.cpp
@@ -0,0 +1,1371 @@
+/*************************************************************************
+**
+** OLE 2.0 Property Set Utilities
+**
+** suminfo.cpp
+**
+** This file contains functions that are useful for the manipulation
+** of OLE 2.0 Property Sets particularly to manage the Summary Info
+** property set.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+// Note: this file is designed to be stand-alone; it includes a
+// carefully chosen, minimal set of headers.
+//
+// For conditional compilation we use the ole2 conventions,
+// _MAC = mac
+// WIN32 = Win32 (NT really)
+// <nothing> = defaults to Win16
+
+// REVIEW: the following needs to modified to handle _MAC
+#define STRICT
+#ifndef INC_OLE2
+ #define INC_OLE2
+#endif
+
+#include <windows.h>
+#include <string.h>
+#include <ole2.h>
+#include "ole2ui.h"
+
+OLEDBGDATA
+
+/* A LPSUMINFO variable is a pointer to an instance of an abstract data
+** type. There can be an arbitrary number of SummaryInfo streams open
+** simultaneously (subject to available memory); each must have its
+** own LPSUMINFO instance. Each LPSUMINFO instance must
+** be initialized prior to use by calling Init and freed after its
+** last use by calling Free. The param argument to Init is reserved
+** for future expansion and should be zero initially. Once a LPSUMINFO
+** instance is allocated (by Init), the user can call the Set
+** procedures to initialize fields. A copy of the arguments is made
+** in every case except SetThumbnail where control of the storage
+** occupied by the METAFILEPICT is merely transferred. When the
+** Free routine is called, all storage will be deallocated including
+** that of the thumbnail. The arguments to SetThumbNail and the
+** return values from GetThumbNail correspond to the OLE2.0 spec.
+** Note that on input, the thumbnail is read on demand but all the
+** other properties are pre-loaded. The thumbnail is manipulated as
+** a windows handle to a METAFILEPICT structure, which in turn
+** contains a handle to the METAFILE. The transferClip argument on
+** GetThumbNail, when set to true, transfers responsibility for
+** storage management of the thumbnail to the caller; that is, after
+** Free has been called, the handle is still valid. Clear can be
+** used to free storage for all the properties but then you must
+** call Read to load them again. All the code is based on FAR
+** pointers.
+** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo.
+** Memory is allocated using the currently active IMalloc*
+** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
+**
+** Common scenarios:
+** Read SummaryInfo
+** ----------------
+** OleStdInitSummaryInfo()
+** OleStdReadSummaryInfo()
+** . . . . .
+** call different Get routines
+** . . . . .
+** OleStdFreeSummaryInfo()
+**
+** Create SummaryInfo
+** ------------------
+** OleStdInitSummaryInfo()
+** call different Set routines
+** OleStdWriteSummaryInfo()
+** OleStdFreeSummaryInfo()
+**
+** Update SummaryInfo
+** ------------------
+** OleStdInitSummaryInfo()
+** OleStdReadSummaryInfo()
+** OleStdGetThumbNailProperty(necessary only if no SetThumb)
+** call different Set routines
+** OleStdWriteSummaryInfo()
+** OleStdFreeSummaryInfo()
+*/
+
+#ifdef WIN32
+#define CHAR TCHAR
+#else
+#define CHAR unsigned char
+#endif
+#define fTrue 1
+#define fFalse 0
+#define BYTE unsigned char
+#define WORD unsigned short
+#define DWORD unsigned long
+#define LPVOID void FAR *
+#define uchar unsigned char
+#define ulong unsigned long
+#define BOOL unsigned char
+#define BF unsigned int
+
+#include "suminfo.h"
+#include "wn_dos.h"
+
+#if defined( _DEBUG )
+ #ifndef NOASSERT
+ // following is from compobj.dll (ole2)
+ #ifdef UNICODE
+ #define ASSERT(x) (!(x) ? FnAssert(TEXT(#x), NULL, \
+ TEXT(__FILE__), __LINE__) : 0)
+ #else
+ #define ASSERT(x) (!(x) ? \
+ { \
+ WCHAR wsz[255]; \
+ wcscpy(wsz, (#x)); \
+ FnAssert(wsz, NULL, TEXT(__FILE__), __LINE__) \
+ } \
+ : 0)
+ #endif
+ #else
+ #define ASSERT(x)
+ #endif
+#else
+#define ASSERT(x)
+#endif
+
+
+typedef struct _RSUMINFO
+ {
+ WORD byteOrder;
+ WORD formatVersion;
+ WORD getOSVersion;
+ WORD osVersion;
+ CLSID classId; //from compobj.h
+ DWORD cSections;
+ PROPSETLIST rgPropSet[1/*cSections*/]; //one section in standard summary info
+ STANDARDSECINMEM section;
+ ULONG fileOffset; //offset for thumbnail to support demand read
+ } RSUMINFO;
+
+typedef RSUMINFO FAR * LPRSI;
+
+ typedef union _foo{
+ ULARGE_INTEGER uli;
+ struct {
+ DWORD dw;
+ DWORD dwh;
+ };
+ struct {
+ WORD w0;
+ WORD w1;
+ WORD w2;
+ WORD w3;
+ };
+ } Foo;
+
+
+
+/* MemAlloc
+** ---------
+** allocate memory using the currently active IMalloc* allocator
+*/
+static LPVOID MemAlloc(ULONG ulSize)
+{
+ LPVOID pout;
+ LPMALLOC pmalloc;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssert(pmalloc);
+ return NULL;
+ }
+
+ pout = (LPVOID)pmalloc->Alloc(ulSize);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->Release();
+ }
+
+ return pout;
+}
+
+
+/* MemFree
+** -------
+** free memory using the currently active IMalloc* allocator
+*/
+static void MemFree(LPVOID pmem)
+{
+ LPMALLOC pmalloc;
+
+ if (pmem == NULL)
+ return;
+
+ if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
+ OleDbgAssert(pmalloc);
+ return;
+ }
+
+ pmalloc->Free(pmem);
+
+ if (pmalloc != NULL) {
+ ULONG refs = pmalloc->Release();
+ }
+}
+
+// Replace the first argument with the product of itself and the multiplier
+static void ulargeMultiply(ULARGE_INTEGER FAR *ul, USHORT m)
+{
+ Foo out, in;
+ in.uli = *ul;
+ out.dw = (ULONG)m * in.w0; in.w0 = out.w0;
+ out.dw = (ULONG)m * in.w1 + out.w1; in.w1 = out.w0;
+ out.dw = (ULONG)m * in.w2 + out.w1; in.w2 = out.w0;
+ out.dw = (ULONG)m * in.w3 + out.w1; in.w3 = out.w0;
+ *ul = in.uli;
+}
+
+// Replace the first argument with the product of itself and the multiplier
+static void ulargeDivide(ULARGE_INTEGER FAR *ul, USHORT m)
+{
+ Foo out, in;
+ DWORD i;
+ in.uli = *ul;
+ out.dwh = in.dwh/(ULONG)m;
+ i = in.dwh%(ULONG)m;
+ in.w2 = in.w1;
+ in.w3 = (WORD)i;
+ out.w1 = (WORD)(in.dwh/(ULONG)m);
+ in.w1 = (WORD)(in.dwh%(ULONG)m);
+ out.w0 = (WORD)(in.dw/(ULONG)m);
+ *ul = out.uli;
+}
+
+
+static void setStandard(LPRSI lprsi)
+{
+ int i;
+ lprsi->cSections = 1;
+ SetSumInfFMTID(&lprsi->rgPropSet[0].formatID);
+ _fmemcpy(&lprsi->classId, &lprsi->rgPropSet[0].formatID, sizeof(FMTID));
+ lprsi->rgPropSet[0].byteOffset = cbNewSummaryInfo(1);
+ for (i=0; i<cPID_STANDARD; i++)
+ lprsi->section.rgPropId[i].propertyID = PID_TITLE+i;
+ lprsi->section.cProperties = cPID_STANDARD; //always; do null test to check validity
+}
+
+extern "C" {
+
+/*************************************************************************
+**
+** OleStdInitSummaryInfo
+**
+** Purpose:
+** Initialize a Summary Info structure.
+**
+** Parameters:
+** int reserved - reserverd for future use. must be 0.
+**
+** Return Value:
+** LPSUMINFO
+**
+** Comments:
+** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo.
+** Memory is allocated using the currently active IMalloc*
+** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
+** Each LPSUMINFO instance must be initialized prior to use by
+** calling OleStdInitSummaryInfo. Once a LPSUMINFO instance is allocated
+** (by OleStdInitSummaryInfo), the user can call the Set procedures to
+** initialize fields.
+*************************************************************************/
+
+STDAPI_(LPSUMINFO) OleStdInitSummaryInfo(int reserved)
+{
+ LPRSI lprsi;
+
+ if ((lprsi = (LPRSI)MemAlloc(sizeof(RSUMINFO))) != NULL)
+ {
+ ClearSumInf(lprsi, sizeof(RSUMINFO));
+ } else return NULL;
+
+ setStandard(lprsi);
+ return (LPSUMINFO)lprsi;
+}
+
+
+/*************************************************************************
+**
+** OleStdFreeSummaryInfo
+**
+** Purpose:
+** Free a Summary Info structure.
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+**
+** Return Value:
+** void
+**
+** Comments:
+** Memory is freed using the currently active IMalloc*
+** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
+** Every LPSUMINFO struct must be freed after its last use.
+** When the OleStdFreeSummaryInfo routine is called, all storage will be
+** deallocated including that of the thumbnail (unless ownership of
+** the thumbnail has been transfered to the caller -- see
+** description of transferClip in GetThumbnail API).
+**
+*************************************************************************/
+
+STDAPI_(void) OleStdFreeSummaryInfo(LPSUMINFO FAR *lplp)
+{
+ if (lplp==NULL||*lplp==NULL) return;
+ OleStdClearSummaryInfo(*lplp);
+ MemFree(*lplp);
+ *lplp = NULL;
+}
+
+
+/*************************************************************************
+**
+** OleStdClearSummaryInfo
+**
+** Purpose:
+** Free storage (memory) for all the properties of the LPSUMINFO.
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+**
+** Return Value:
+** void
+**
+** Comments:
+** After calling OleStdClearSummaryInfo you must call OleStdReadSummaryInfo to
+** load them again.
+**
+*************************************************************************/
+
+STDAPI_(void) OleStdClearSummaryInfo(LPSUMINFO lp)
+{
+ OleStdSetStringProperty(lp, PID_TITLE, NULL);
+ OleStdSetStringProperty(lp, PID_SUBJECT, NULL);
+ OleStdSetStringProperty(lp, PID_AUTHOR, NULL);
+ OleStdSetStringProperty(lp, PID_KEYWORDS, NULL);
+ OleStdSetStringProperty(lp, PID_COMMENTS, NULL);
+ OleStdSetStringProperty(lp, PID_TEMPLATE, NULL);
+ OleStdSetStringProperty(lp, PID_REVNUMBER, NULL);
+ OleStdSetStringProperty(lp, PID_APPNAME, NULL);
+ OleStdSetThumbNailProperty(NULL, lp, VT_CF_EMPTY, 0, NULL, NULL, 0);
+ ClearSumInf((LPRSI)lp, sizeof(RSUMINFO));
+}
+
+
+/*************************************************************************
+**
+** OleStdReadSummaryInfo
+**
+** Purpose:
+** Read all Summary Info properties into memory (except thumbnail
+** which is demand loaded).
+**
+** Parameters:
+** LPSTREAM lps - open SummaryInfo IStream*
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+** Comments:
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdReadSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp)
+{
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ LPRSI lpSumInfo = (LPRSI)lp;
+ SCODE sc;
+ ULONG cbRead,i,sectionOffset;
+ LARGE_INTEGER a;
+ ULARGE_INTEGER b;
+ int j,k,l;
+ union {
+ RSUMINFO rsi;
+ STDZ stdz;
+ };
+ OleStdClearSummaryInfo(lp);
+ LISet32(a, 0);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sectionOffset = cbNewSummaryInfo(1);
+ sc = GetScode(lpStream->Read(&rsi, sectionOffset, &cbRead));
+ if (FAILED(sc)||cbRead<sectionOffset) goto fail;
+ if (!FIntelOrder(&rsi)||rsi.formatVersion!=0) goto fail;
+ j = (int)rsi.cSections;
+ while (j-->0) {
+ if (FEqSumInfFMTID(&rsi.rgPropSet[0].formatID)) {
+ sectionOffset = rsi.rgPropSet[0].byteOffset;
+ break;
+ } else {
+ sc = GetScode(lpStream->Read(&rsi.rgPropSet[0].formatID, sizeof(PROPSETLIST), &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(PROPSETLIST)) goto fail;
+ }
+ if (j<=0) goto fail;
+ }
+
+ LISet32(a, sectionOffset);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sc = GetScode(lpStream->Read(&rsi.section, cbNewSection(1), &cbRead));
+ if (FAILED(sc)||cbRead!=cbNewSection(1)) goto fail;
+ i = rsi.section.cBytes+sectionOffset;
+ j = (int)rsi.section.cProperties;
+ if (j>cPID_STANDARD) goto fail;
+ k = 0;
+ while (j-->0) {
+ k++;
+ switch (l=(int)rsi.section.rgPropId[0].propertyID) {
+ case PID_PAGECOUNT:
+ case PID_WORDCOUNT:
+ case PID_CHARCOUNT:
+ case PID_SECURITY:
+ if (l==PID_SECURITY) l=3; else l-=PID_PAGECOUNT;
+ cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
+ if (cbRead>=i) goto fail;
+ LISet32(a, cbRead);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sc = GetScode(lpStream->Read(&lpSSIM->rgInts[l], sizeof(INTS), &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(INTS)) goto fail;
+ if (lpSSIM->rgInts[l].vtType==VT_EMPTY) break;
+ if (lpSSIM->rgInts[l].vtType!=VT_I4) goto fail;
+ break;
+ case PID_EDITTIME:
+ case PID_LASTPRINTED:
+ case PID_CREATE_DTM_RO:
+ case PID_LASTSAVE_DTM:
+ l-=PID_EDITTIME;
+ cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
+ if (cbRead>=i) goto fail;
+ LISet32(a, cbRead);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sc = GetScode(lpStream->Read(&lpSSIM->rgTime[l], sizeof(TIME), &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(TIME)) goto fail;
+ if (lpSSIM->rgTime[l].vtType==VT_EMPTY) break;
+ if (lpSSIM->rgTime[l].vtType!=VT_FILETIME) goto fail;
+ break;
+ case PID_TITLE:
+ case PID_SUBJECT:
+ case PID_AUTHOR:
+ case PID_KEYWORDS:
+ case PID_COMMENTS:
+ case PID_TEMPLATE:
+ case PID_LASTAUTHOR:
+ case PID_REVNUMBER:
+ case PID_APPNAME:
+ cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
+ if (cbRead>=i) goto fail;
+ LISet32(a, cbRead);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sc = GetScode(lpStream->Read(&stdz, sizeof(STDZ), &cbRead));
+ if (FAILED(sc)||cbRead<sizeof(DWORD)*2) goto fail;
+ if (stdz.vtType==VT_EMPTY||stdz.vtByteCount<=1) break;
+ if (stdz.vtType!=VT_LPSTR||stdz.vtByteCount>WORDMAX) goto fail;
+ stdz.rgchars[(int)stdz.vtByteCount-1] = TEXT('\0');
+ OleStdSetStringProperty(lp, (DWORD)l, (LPTSTR)&stdz.rgchars[0]);
+ break;
+ case PID_THUMBNAIL:
+ cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
+ if (cbRead>=i) goto fail;
+ LISet32(a, cbRead);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ lpSumInfo->fileOffset = cbRead+sizeof(DWORD)*3;
+ sc = GetScode(lpStream->Read(&lpSSIM->thumb, sizeof(DWORD)*4, &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(DWORD)*4) {
+ lpSSIM->thumb.vtType = VT_EMPTY;
+ goto fail;
+ }
+ if (lpSSIM->thumb.vtType == VT_EMPTY) {
+ lpSSIM->thumb.cBytes = 0;
+ break;
+ }
+ if (lpSSIM->thumb.vtType != VT_CF) {
+ lpSSIM->thumb.vtType = VT_EMPTY;
+ goto fail;
+ }
+ lpSSIM->thumb.cBytes -= sizeof(DWORD); //for selector
+ if (lpSSIM->thumb.selector==VT_CF_WIN||lpSSIM->thumb.selector==VT_CF_MAC) {
+ lpSumInfo->fileOffset += sizeof(DWORD);
+ lpSSIM->thumb.cBytes -= sizeof(DWORD); //for format val
+ }
+ break;
+ default: ;
+ }
+ if (j<=0)
+ {
+ // We should fail if the document is password-protected.
+ if(OleStdGetSecurityProperty(lp)==fSecurityPassworded)
+ goto fail;
+ return 1;
+ }
+ LISet32(a, sectionOffset+sizeof(DWORD)*2+k*sizeof(PROPIDLIST));
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) goto fail;
+ sc = GetScode(lpStream->Read(&rsi.section.rgPropId[0], sizeof(PROPIDLIST), &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(PROPIDLIST)) goto fail;
+ }
+
+fail:
+ OleStdClearSummaryInfo(lpSumInfo);
+
+ return 0;
+}
+
+
+/*************************************************************************
+**
+** OleStdWriteSummaryInfo
+**
+** Purpose:
+** Write all Summary Info properties to a IStream*
+**
+** Parameters:
+** LPSTREAM lps - open SummaryInfo IStream*
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+** Comments:
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdWriteSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp)
+{
+
+
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ // REVIEW: localization issues for propert sets
+ // do we need to include a code page and dictionary?
+
+ LPRSI lpSumInfo = (LPRSI)lp;
+ SCODE sc;
+ ULONG cbWritten;
+ ULONG cBytes, oBytes, k,l,m,n;
+ LARGE_INTEGER a;
+ ULARGE_INTEGER b;
+ CHAR FAR *lps;
+ LPMETAFILEPICT lpmfp;
+ int i,j,s;
+
+ setStandard(lpSumInfo);
+ oBytes = cbNewSection(cPID_STANDARD); //offsets are relative to the section
+ cBytes = cbNewSection(cPID_STANDARD)+(sizeof(TIME)*MAXTIME)+(sizeof(INTS)*MAXINTS);
+
+ lpSSIM->rgPropId[PID_EDITTIME-2].byteOffset = oBytes;
+ lpSSIM->rgPropId[PID_LASTPRINTED-2].byteOffset = oBytes+sizeof(TIME);
+ lpSSIM->rgPropId[PID_CREATE_DTM_RO-2].byteOffset = oBytes+sizeof(TIME)*2;
+ lpSSIM->rgPropId[PID_LASTSAVE_DTM-2].byteOffset = oBytes+sizeof(TIME)*3;
+
+ lpSSIM->rgPropId[PID_PAGECOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME);
+ lpSSIM->rgPropId[PID_WORDCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS));
+ lpSSIM->rgPropId[PID_CHARCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*2);
+ lpSSIM->rgPropId[PID_SECURITY-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*3);
+ oBytes += sizeof(TIME)*MAXTIME + sizeof(INTS)*MAXINTS;
+
+ lpSSIM->rgPropId[PID_THUMBNAIL-2].byteOffset = oBytes;
+ l = 0;
+ if (lpSSIM->thumb.vtType==VT_EMPTY) k = sizeof(DWORD);
+ else {
+ l = ((lpSSIM->thumb.cBytes+4-1)>>2)<<2;
+ if (lpSSIM->thumb.selector==VT_CF_BYTES) k = sizeof(DWORD)*3;
+ else if (lpSSIM->thumb.selector==VT_CF_FMTID) {k = sizeof(DWORD)*3; l += sizeof(FMTID); }
+ else if (lpSSIM->thumb.selector==VT_CF_NAME) {k = sizeof(DWORD)*3; l += (((*lpSSIM->thumb.lpstzName+1+3)>>2)<<2);}
+ else k = sizeof(DWORD)*4;
+ }
+ cBytes += k+l;
+ oBytes += k+l;
+
+ for (i=0; i<MAXSTDZ; i++) {
+ j = 0;
+ if (lpSSIM->rglpsz[i]!=NULL) {
+ j = lpSSIM->rglpsz[i]->VTCB+1/*null*/;
+ lpSSIM->rglpsz[i]->vtByteCount = j;
+ j = (((j+4-1)>>2)<<2)+sizeof(DWORD);
+ cBytes += j;
+ }
+ if (i!=MAXSTDZ-1) lpSSIM->rgPropId[i].byteOffset = oBytes;
+ else lpSSIM->rgPropId[PID_APPNAME-2].byteOffset = oBytes;
+ oBytes += j+sizeof(DWORD);
+ cBytes += sizeof(DWORD); //type
+ }
+ lpSSIM->cBytes = cBytes;
+
+
+ LISet32(a, 0);
+ sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) return 0;
+ sc = GetScode(lpStream->Write(lpSumInfo, cbNewSummaryInfo(1), &cbWritten));
+ if (FAILED(sc)||cbWritten!=cbNewSummaryInfo(1)) return 0;
+ sc = GetScode(lpStream->Write(lpSSIM, cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS, &cbWritten));
+ if (FAILED(sc)||cbWritten!=cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS) return 0;
+
+ m = lpSSIM->thumb.cBytes;
+ if (lpSSIM->thumb.lpstzName!=NULL) s = *lpSSIM->thumb.lpstzName;
+ else s = 0;
+ if (m!=0) {
+ lpSSIM->thumb.cBytes = (k-sizeof(DWORD)*2)+
+ (((lpSSIM->thumb.cBytes+4-1)>>2)<<2)+(((s+4-1)>>2)<<2);
+ n = lpSSIM->thumb.selector;
+ lps = lpSSIM->thumb.lpByte;
+ OleDbgAssert(lps!=NULL); //maybe a GetThumbNail here
+ OleDbgAssert(n!=VT_CF_NAME);
+ if (n==VT_CF_WIN) { //bytes are in global memory
+ lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lps);
+ if (lpmfp==NULL) goto fail;
+ lps = (CHAR FAR*)GlobalLock(lpmfp->hMF);
+ }
+ if (n==VT_CF_NAME) lpSSIM->thumb.selector = *lpSSIM->thumb.lpstzName+1/*null*/;
+ }
+ sc = GetScode(lpStream->Write(&lpSSIM->thumb, k, &cbWritten));
+ if (FAILED(sc)||cbWritten!=k) goto fail;
+ if (s!=0) {
+ k = ((s+1+4-1)>>2)<<2;
+ sc = GetScode(lpStream->Write(lpSSIM->thumb.lpstzName+1, k, &cbWritten));
+ if (FAILED(sc)||cbWritten!=k) goto fail;
+ }
+ if (m!=0) {
+ k = ((m+3)>>2)<<2;
+ if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory
+ sc = GetScode(lpStream->Write(lpmfp, sizeof(METAFILEPICT), &cbWritten));
+ k -= sizeof(METAFILEPICT);
+ }
+ sc = GetScode(lpStream->Write(lps, k, &cbWritten));
+ if (FAILED(sc)||cbWritten!=k) goto fail;
+ if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory
+ GlobalUnlock(lpmfp->hMF);
+ GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
+ }
+ }
+ lpSSIM->thumb.cBytes = m; //restore in mem value
+ lpSSIM->thumb.selector = n;
+
+ k = VT_EMPTY;
+ for (i=0; i<MAXSTDZ; i++) {
+ if (lpSSIM->rglpsz[i]!=NULL) {
+ l = lpSSIM->rglpsz[i]->vtByteCount;
+ j = ((((int)l+4-1)/4)*4)+sizeof(DWORD)*2;
+ sc = GetScode(lpStream->Write(lpSSIM->rglpsz[i], j, &cbWritten));
+ if (FAILED(sc)||cbWritten!=(ULONG)j) return 0;
+ lpSSIM->rglpsz[i]->vtByteCount = 0; //restore stz count convention
+ lpSSIM->rglpsz[i]->VTCB = (int)l;
+ } else {
+ sc = GetScode(lpStream->Write(&k, sizeof(DWORD), &cbWritten));
+ if (FAILED(sc)||cbWritten!=sizeof(DWORD)) return 0;
+ }
+ }
+ return 1;
+fail:
+ lpSSIM->thumb.cBytes = m; //restore in mem value
+ lpSSIM->thumb.selector = n;
+ if (m!=0&&(n==VT_CF_WIN||VT_CF_NAME)) { //bytes are in global memory
+ GlobalUnlock((HANDLE)(DWORD)lps);
+ }
+
+ return 0;
+}
+
+
+/*************************************************************************
+**
+** OleStdGetSecurityProperty
+**
+** Purpose:
+** Retrieve the Security Property
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+**
+** Return Value:
+** DWORD - security level
+** AllSecurityFlagsEqNone 0 - no security
+** fSecurityPassworded 1 - password required
+** fSecurityRORecommended 2 - read-only is recommended
+** fSecurityRO 4 - read-only is required
+** fSecurityLockedForAnnotations 8 - locked for annotations
+**
+** Comments:
+** by noting the (suggested; that is, application-enforced) security
+** level on the document, an application other than the originator
+** of the document can adjust its user interface to the properties
+** appropriately. An application should not display any of the
+** information about a password protected document, and should not
+** allow modifications to enforced read-only or locked for
+** annotations documents. It should warn the user about read-only
+** recommended if the user attempts to modify properties.
+**
+*************************************************************************/
+
+STDAPI_(DWORD) OleStdGetSecurityProperty(LPSUMINFO lp)
+{
+STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ if (lpSSIM->rgInts[3].vtType == VT_I4) return lpSSIM->rgInts[3].value;
+
+ return 0;
+}
+
+
+/*************************************************************************
+**
+** OleStdSetSecurityProperty
+**
+** Purpose:
+** Set the Security Property
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD security - security level
+** AllSecurityFlagsEqNone 0 - no security
+** fSecurityPassworded 1 - password required
+** fSecurityRORecommended 2 - read-only is recommended
+** fSecurityRO 4 - read-only is required
+** fSecurityLockedForAnnotations 8 - locked for annotations
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+** (there are no errors)
+**
+** Comments:
+** by noting the (suggested; that is, application-enforced) security
+** level on the document, an application other than the originator
+** of the document can adjust its user interface to the properties
+** appropriately. An application should not display any of the
+** information about a password protected document, and should not
+** allow modifications to enforced read-only or locked for
+** annotations documents. It should warn the user about read-only
+** recommended if the user attempts to modify properties.
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdSetSecurityProperty(LPSUMINFO lp, DWORD security)
+{
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+
+ // REVIEW: check valid transitions; how do we know APP called us?
+
+ if (security==0) {
+ lpSSIM->rgInts[3].vtType = VT_EMPTY;
+ return 1;
+ }
+ lpSSIM->rgInts[3].vtType = VT_I4;
+ lpSSIM->rgInts[3].value = security;
+ return 1;
+}
+
+
+/*************************************************************************
+**
+** OleStdGetStringProperty
+**
+** Purpose:
+** Retrieve a String Propety.
+** (returns zero terminated string -- C string)
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD pid - ID of String Property
+**
+** Return Value:
+** LPTSTR - value of String Property
+** (zero terminated string--C string)
+**
+** Comments:
+** String should NOT be freed by caller. Memory for string will be
+** freed when OleStdFreeSummaryInfo is called.
+*************************************************************************/
+
+STDAPI_(LPTSTR) OleStdGetStringProperty(LPSUMINFO lp, DWORD pid)
+{
+ LPTSTR l = OleStdGetStringZProperty(lp,pid);
+ if (l==NULL) return NULL; else return l+1;
+}
+
+
+/*************************************************************************
+**
+** OleStdSetStringProperty
+**
+** Purpose:
+** Set a String Propety
+** (takes zero terminated string -- C string)
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD pid - ID of String Property
+** LPTSTR lpsz - new value for String Property.
+** zero terminated string -- C string.
+** May be NULL, in which case the
+** propery is cleared.
+**
+** Return Value:
+** int - 1 if successful
+** - 0 invalid property id
+**
+** Comments:
+** The input string is copied.
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdSetStringProperty(LPSUMINFO lp, DWORD pid, LPTSTR lpsz)
+{
+ LPRSI lprsi=(LPRSI)lp;
+ STANDARDSECINMEM FAR* lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ int i;
+ if (pid==PID_APPNAME) {
+ pid = MAXSTDZ-1;
+ } else if (pid<PID_TITLE || pid>PID_REVNUMBER) return 0; else pid -= 2;
+ OleDbgAssert(lpSSIM);
+ if (lpSSIM->rglpsz[pid]) MemFree(lpSSIM->rglpsz[pid]);
+ if ((lpsz==NULL)||(*lpsz==0)) {
+ lpSSIM->rglpsz[pid] = NULL;
+ return (1);
+ }
+ i = _fstrlen(lpsz);
+ lpSSIM->rglpsz[pid] = (STDZ FAR*)MemAlloc((i+1/*null*/)*sizeof(TCHAR)+
+ sizeof(DWORD)*2);
+ if (lpSSIM->rglpsz[pid]==NULL) return 0;
+ _fstrcpy((LPTSTR)&lpSSIM->rglpsz[pid]->rgchars, lpsz);
+ lpSSIM->rglpsz[pid]->vtType = VT_LPSTR;
+ lpSSIM->rglpsz[pid]->vtByteCount = 0;
+ lpSSIM->rglpsz[pid]->VTCB = i;
+ return (1);
+}
+
+
+/*************************************************************************
+**
+** OleStdGetStringZProperty
+**
+** Purpose:
+** Retrieve a String Propety.
+** (returns zero-terminated with leading byte count string)
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD pid - ID of Property
+**
+** Return Value:
+** LPSTZR - value of String Property
+** (zero-terminated with leading
+** byte count)
+**
+** Comments:
+** String should NOT be freed by caller. Memory for string will be
+** freed when OleStdFreeSummaryInfo is called.
+*************************************************************************/
+
+STDAPI_(LPSTZR) OleStdGetStringZProperty(LPSUMINFO lp, DWORD pid)
+{
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ if (pid==PID_APPNAME) {
+ pid = MAXSTDZ-1;
+ } else if (pid<PID_TITLE || pid>PID_REVNUMBER) return NULL; else pid -= 2;
+ if (lpSSIM->rglpsz[pid]!=NULL) {
+ return (LPTSTR)&lpSSIM->rglpsz[pid]->VTCB;
+ }
+ return NULL;
+}
+
+
+/*************************************************************************
+**
+** OleStdGetDocProperty
+**
+** Purpose:
+** Retrieve document properties (no. pages, no. words, no. characters)
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD FAR *nPage - (OUT) number of pages in document
+** DWORD FAR *nWords - (OUT) number of words in document
+** DWORD FAR *nChars - (OUT) number of charactrs in doc
+**
+** Return Value:
+** void
+**
+** Comments:
+**
+*************************************************************************/
+
+STDAPI_(void) OleStdGetDocProperty(
+ LPSUMINFO lp,
+ DWORD FAR* nPage,
+ DWORD FAR* nWords,
+ DWORD FAR* nChars
+)
+{
+STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ *nPage=0; *nWords=0; *nChars=0;
+ if (lpSSIM->rgInts[0].vtType == VT_I4) *nPage = lpSSIM->rgInts[0].value;
+ if (lpSSIM->rgInts[1].vtType == VT_I4) *nWords = lpSSIM->rgInts[1].value;
+ if (lpSSIM->rgInts[2].vtType == VT_I4) *nChars = lpSSIM->rgInts[2].value;
+}
+
+
+/*************************************************************************
+**
+** OleStdSetDocProperty
+**
+** Purpose:
+** Set document properties (no. pages, no. words, no. characters)
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD nPage - number of pages in document
+** DWORD nWords - number of words in document
+** DWORD nChars - number of charactrs in doc
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+** (there are no errors)
+**
+** Comments:
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdSetDocProperty(
+ LPSUMINFO lp,
+ DWORD nPage,
+ DWORD nWords,
+ DWORD nChars
+)
+{
+DWORD vttype=VT_I4;
+STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ if ((nPage|nWords|nChars)==0) {
+ vttype = VT_EMPTY;
+ nPage=0; nWords=0; nChars=0;
+ }
+ lpSSIM->rgInts[0].vtType = vttype;
+ lpSSIM->rgInts[1].vtType = vttype;
+ lpSSIM->rgInts[2].vtType = vttype;
+ lpSSIM->rgInts[0].value = nPage;
+ lpSSIM->rgInts[1].value = nWords;
+ lpSSIM->rgInts[2].value = nChars;
+ return 1;
+}
+
+
+/*************************************************************************
+**
+** OleStdGetThumbNailProperty
+**
+** Purpose:
+** Retrieve a Thumbnail Property
+**
+** Parameters:
+** LPSTREAM lps
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD FAR* clipFormatNo - clipboard format for thumbnail
+** (type of value depends on vtcf
+** return value.)
+** NOTE: ONLY VT_CF_WIN is
+** implemented, so clipFormatNo
+** will be CF_METAFILEPICT
+** LPTSTR FAR* lpszName - format name if VT_CF_NAME is
+** returned
+** NOTE: NOT IMPLEMENTED
+** THUMBNAIL FAR* clip - handle to thumbnail
+** for VT_CF_WIN clip will be
+** handle to MetafilePict
+** NOTE: only VT_CF_WIN IMPLEMENTED
+** DWORD FAR* byteCount - size of thumbnail stream
+** for VT_CF_WIN case this should
+** be combined size of both the
+** Metafile as well as the
+** MetafilePict structure.
+** BOOL transferClip - transfer ownership of thumbnail
+** to caller. (see comment)
+**
+** Return Value:
+** int vtcfNo - OLE thumbnail selector value
+** VT_CF_WIN - Windows thumbnail
+** (interpret clipFormatNo as
+** Windows clipboard format)
+** VT_CF_FMTID - (NOT IMPLEMENTED)
+** thumbnail format is specified
+** by ID. use clipFormatNo.
+** (but NOT a Windows format ID)
+**
+** VT_CF_NAME - (NOT IMPLEMENTED)
+** thumbnail format is specified
+** by name. use lpszName.
+** VT_CF_EMPTY - blank thumbnail
+** (clip will be NULL)
+** VT_CF_OOM - Memory allocation failure
+**
+** Comments:
+** NOTE: Currently there is only proper support for VT_CF_WIN.
+** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME,
+** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and
+** OleStdWriteSummaryInfo only support VT_CF_WIN.
+**
+** Note that on input, the thumbnail is read on demand while all the
+** other properties are pre-loaded. The thumbnail is manipulated as
+** a windows handle to a METAFILEPICT structure, which in turn
+** contains a handle to the METAFILE. The transferClip argument on
+** GetThumbNail, when set to true, transfers responsibility for
+** storage management of the thumbnail to the caller; that is, after
+** OleStdFreeSummaryInfo has been called, the handle is still valid.
+*************************************************************************/
+
+STDAPI_(int) OleStdGetThumbNailProperty(
+ LPSTREAM lps,
+ LPSUMINFO lp,
+ DWORD FAR* clipFormatNo,
+ LPTSTR FAR* lpszName,
+ THUMBNAIL FAR* clip,
+ DWORD FAR* byteCount,
+ BOOL transferClip
+)
+{
+ int i;
+ LPRSI lprsi=(LPRSI)lp;
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ ULONG cbRead, cbToRead;
+ LARGE_INTEGER a;
+ ULARGE_INTEGER b;
+ CHAR FAR *lpst;
+ LPMETAFILEPICT lpmfp;
+ HANDLE hst, hmfp;
+ SCODE sc;
+ *byteCount = 0;
+ if (lpSSIM->thumb.cBytes==0) return VT_CF_EMPTY;
+ if (lpSSIM->thumb.lpByte==NULL) {
+ LISet32(a, lprsi->fileOffset);
+ sc = GetScode(lps->Seek(a, STREAM_SEEK_SET, &b));
+ if (FAILED(sc)) return VT_CF_EMPTY;
+ i = (int) lpSSIM->thumb.selector;
+ if (i>0||i==VT_CF_FMTID) {
+ if (i>255) return VT_CF_EMPTY;
+ else if (i==VT_CF_FMTID) i = sizeof(FMTID);
+ else lpSSIM->thumb.selector = VT_CF_NAME;
+ cbToRead = ((i+3)>>2)<<2;
+ lpSSIM->thumb.lpstzName=(CHAR FAR*)MemAlloc(i+1/*n*/+1);
+ if (lpSSIM->thumb.lpstzName==NULL) return VT_CF_OOM;
+ sc = GetScode(lps->Read(lpSSIM->thumb.lpstzName+1, cbToRead, &cbRead));
+ if (FAILED(sc)||cbRead!=cbToRead) return VT_CF_EMPTY;
+ *lpSSIM->thumb.lpstzName = i;
+ *(lpSSIM->thumb.lpstzName+i) = 0;
+ lpSSIM->thumb.cBytes -= cbToRead+sizeof(DWORD);
+ }
+ i = (int) lpSSIM->thumb.selector;
+ cbToRead = lpSSIM->thumb.cBytes;
+ if (cbToRead>65535) return VT_CF_OOM;
+ OleDbgAssert(i!=VT_CF_NAME);
+ if (i==VT_CF_WIN) {
+ cbToRead -= sizeof(METAFILEPICT);
+ hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
+ if (hmfp==NULL) return VT_CF_OOM;
+ hst = GlobalAlloc(GMEM_MOVEABLE, cbToRead);
+ if (hst==NULL) {
+ GlobalFree(hmfp);
+ return VT_CF_OOM;
+ }
+ lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp);
+ sc = GetScode(lps->Read(lpmfp, sizeof(METAFILEPICT), &cbRead));
+ if (FAILED(sc)||cbRead!=sizeof(METAFILEPICT)) {
+ GlobalUnlock(hmfp);
+ GlobalFree(hmfp);
+ GlobalFree(hst);
+ return VT_CF_EMPTY;
+ }
+ lpst = (CHAR FAR*)GlobalLock(hst);
+ lpmfp->hMF = (HMETAFILE)hst;
+ lpSSIM->thumb.lpByte = (CHAR FAR*)hmfp;
+ } else {
+ lpst =(CHAR FAR*)MemAlloc((int)cbToRead);
+ if (lpst==NULL) return VT_CF_OOM;
+ lpSSIM->thumb.lpByte = lpst;
+ }
+ sc = GetScode(lps->Read(lpst, cbToRead, &cbRead));
+ if (i==VT_CF_WIN) {
+ GlobalUnlock(hst);
+ GlobalUnlock(hmfp);
+ }
+ if (FAILED(sc)||cbRead!=cbToRead) {
+ if (i==VT_CF_WIN) {
+ GlobalFree(hst);
+ GlobalFree(hmfp);
+ } else MemFree(lpst);
+ lpSSIM->thumb.lpByte = NULL;
+ if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL))
+ MemFree(lpSSIM->thumb.lpstzName);
+ return VT_CF_EMPTY;
+ }
+ }
+ *clipFormatNo = lpSSIM->thumb.clipFormat;
+ *byteCount = lpSSIM->thumb.cBytes;
+ if(lpszName!=NULL)
+ *lpszName = (TCHAR FAR*)lpSSIM->thumb.lpstzName+1;
+ *clip = (TCHAR FAR*)lpSSIM->thumb.lpByte;
+ if (transferClip) lpSSIM->thumb.lpByte=NULL;
+ return (int)lpSSIM->thumb.selector;
+}
+
+
+/*************************************************************************
+**
+** OleStdSetThumbNailProperty
+**
+** Purpose:
+** Set a Thumbnail Property
+**
+** Parameters:
+** LPSTREAM lps - open SummaryInfo IStream*
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** int vtcfNo - OLE thumbnail selector value
+** VT_CF_WIN - Windows thumbnail
+** (interpret clipFormatNo as
+** Windows clipboard format)
+** VT_CF_FMTID - thumbnail format is specified
+** by ID. use clipFormatNo.
+** (but NOT a Windows format ID)
+**
+** VT_CF_NAME - thumbnail format is specified
+** by name. use lpszName.
+** VT_CF_EMPTY - blank thumbnail
+** (clip will be NULL)
+**
+** DWORD FAR* clipFormatNo - clipboard format for thumbnail
+** used if vtcfNo is VT_CF_WIN or
+** VT_CF_FMTID. interpretation of
+** value depends on vtcfNo specified.
+** (normally vtcfNo==VT_CF_WIN and
+** clipFormatNo==CF_METAFILEPICT)
+** LPSTR FAR* lpszName - format name if vtcfNo is VT_CF_NAME
+** THUMBNAIL clip - handle to thumbnail
+** for VT_CF_WIN clip will be
+** handle to MetafilePict
+** DWORD FAR* byteCount - size of thumbnail stream
+** for VT_CF_WIN case this should
+** be combined size of both the
+** Metafile as well as the
+** MetafilePict structure.
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+**
+** Comments:
+** NOTE: Currently there is only proper support for VT_CF_WIN.
+** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME,
+** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and
+** OleStdWriteSummaryInfo only support VT_CF_WIN.
+**
+** This function copies lpszName but saves the "clip" handle passed.
+**
+** NOTE: overwriting or emptying frees space for clip and name.
+** The thumbnail is manipulated as a windows handle to a
+** METAFILEPICT structure, which in turn contains a handle to the
+** METAFILE.
+*************************************************************************/
+
+STDAPI_(int) OleStdSetThumbNailProperty(
+ LPSTREAM lps,
+ LPSUMINFO lp,
+ int vtcfNo,
+ DWORD clipFormatNo,
+ LPTSTR lpszName,
+ THUMBNAIL clip,
+ DWORD byteCount
+)
+{
+ int i;
+ LPRSI lprsi=(LPRSI)lp;
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ LPMETAFILEPICT lpmfp;
+ if (lpSSIM==NULL||vtcfNo>0||vtcfNo<VT_CF_EMPTY||(vtcfNo==VT_CF_NAME&&(lpszName==NULL||*lpszName==0))) {
+ return 0;
+ }
+ if (vtcfNo!=VT_CF_EMPTY&&(clip==0||byteCount==0)) return 0;
+ i = (int) lpSSIM->thumb.vtType;
+ if (i!=VT_EMPTY) {
+ i = (int) lpSSIM->thumb.selector;
+ OleDbgAssert(i!=VT_CF_NAME);
+ if (i==VT_CF_WIN) {
+ if (lpSSIM->thumb.lpByte!=NULL) {
+ lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
+ GlobalFree(lpmfp->hMF);
+ GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
+ GlobalFree((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
+ }
+ } else {
+ MemFree(lpSSIM->thumb.lpByte);
+ }
+ if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL))
+ MemFree(lpSSIM->thumb.lpstzName);
+ lpSSIM->thumb.lpstzName = NULL;
+ lpSSIM->thumb.lpByte = NULL;
+ }
+ if (vtcfNo==VT_CF_EMPTY) {
+ lpSSIM->thumb.vtType = VT_EMPTY;
+ lpSSIM->thumb.cBytes = 0;
+ } else {
+ lpSSIM->thumb.vtType = VT_CF;
+ lpSSIM->thumb.selector = vtcfNo;
+ lpSSIM->thumb.cBytes = byteCount;
+ lpSSIM->thumb.clipFormat = clipFormatNo;
+ lpSSIM->thumb.lpByte = (CHAR FAR*)clip; //just save the hnadle
+ if (vtcfNo==VT_CF_NAME||vtcfNo==VT_CF_FMTID) {
+ i = _fstrlen(lpszName);
+ if (vtcfNo==VT_CF_FMTID) OleDbgAssert(i*sizeof(TCHAR)==sizeof(FMTID));
+ lpSSIM->thumb.lpstzName =
+ (CHAR FAR*)MemAlloc((i+1/*n*/+1/*null*/)*sizeof(TCHAR));
+ if (lpSSIM->thumb.lpstzName==NULL) {
+ lpSSIM->thumb.vtType = VT_EMPTY;
+ return 0;
+ }
+ _fstrcpy((TCHAR FAR*)lpSSIM->thumb.lpstzName+1, lpszName);
+ *lpSSIM->thumb.lpstzName = i;
+ }
+ }
+ return 1;
+}
+
+
+/*************************************************************************
+**
+** OleStdGetDateProperty
+**
+** Purpose:
+** Retrieve Data Property
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD pid - ID of Property
+** int FAR *yr - (OUT) year
+** int FAR *mo - (OUT) month
+** int FAR *dy - (OUT) day
+** DWORD FAR *sc - (OUT) seconds
+**
+** Return Value:
+** void
+**
+** Comments:
+**
+*************************************************************************/
+
+STDAPI_(void) OleStdGetDateProperty(
+ LPSUMINFO lp,
+ DWORD pid,
+ int FAR* yr,
+ int FAR* mo,
+ int FAR* dy,
+ DWORD FAR* sc
+)
+{
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ SFFS sffs;
+ pid -= PID_EDITTIME;
+ *yr = 0; *mo = 0; *dy = 0; *sc = 0;
+ if (pid<0||pid>=MAXTIME) return;
+ if (lpSSIM->rgTime[pid].vtType == VT_FILETIME) {
+ if (pid==0) {
+ //convert from 100ns to seconds
+ ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000);
+ ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000);
+ pid = lpSSIM->rgTime[0].time.dwLowDateTime;
+ *sc = pid%((DWORD)60*60*24);
+ pid /= (DWORD)60*60*24;
+ *dy = (int)(pid%(DWORD)30);
+ pid /= (DWORD)30;
+ *mo = (int)(pid%(DWORD)12);
+ *yr = (int)(pid/(DWORD)12);
+ } else {
+ if (CoFileTimeToDosDateTime(&lpSSIM->rgTime[pid].time,
+ &sffs.dateVariable, &sffs.timeVariable)) {
+ *yr = sffs.yr+1980;
+ *mo = sffs.mon;
+ *dy = sffs.dom;
+ *sc = (DWORD)sffs.hr*3600+sffs.mint*60+sffs.sec*2;
+ }
+ }
+ }
+ return;
+}
+
+
+
+/*************************************************************************
+**
+** OleStdSetDateProperty
+**
+** Purpose:
+** Set Data Property
+**
+** Parameters:
+** LPSUMINFO FAR *lp - pointer to open Summary Info struct
+** DWORD pid - ID of Property
+** int yr - year
+** int mo - month
+** int dy - day
+** DWORD sc - seconds
+**
+** Return Value:
+** int - 1 for success
+** - 0 if error occurs
+**
+** Comments:
+** Use all zeros to clear.
+** The following is an example of valid input:
+** yr=1993 mo=1(Jan) dy=1(1st) hr=12(noon) mn=30 sc=23
+** for PID_EDITTIME property, the values are a zero-origin duration
+** of time.
+**
+*************************************************************************/
+
+STDAPI_(int) OleStdSetDateProperty(
+ LPSUMINFO lp,
+ DWORD pid,
+ int yr,
+ int mo,
+ int dy,
+ int hr,
+ int mn,
+ int sc
+)
+{
+ STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
+ SFFS sffs;
+ pid -= PID_EDITTIME;
+ if (pid<0||pid>=MAXTIME) return 0;
+ if ((yr|mo|dy|hr|mn|sc)==0) { //all must be zero
+ lpSSIM->rgTime[pid].vtType = VT_EMPTY;
+ return 1;
+ }
+ lpSSIM->rgTime[pid].vtType = VT_FILETIME;
+ if (pid==0) {
+ lpSSIM->rgTime[0].time.dwLowDateTime =
+ (((((DWORD)yr*365+mo*30)+dy)*24+hr)*60+mn)*60+sc;
+ lpSSIM->rgTime[0].time.dwHighDateTime = 0;
+ //10^7 nanoseconds/second
+ ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000);
+ //convert to units of 100 ns
+ ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000);
+ } else {
+ sffs.yr = max(yr-1980,0);
+ sffs.mon = mo;
+ sffs.dom = dy;
+ sffs.hr = hr;
+ sffs.mint= mn;
+ sffs.sec = sc/2; //dos is 2 second intervals
+ if (!CoDosDateTimeToFileTime(sffs.date, sffs.time,
+ &lpSSIM->rgTime[pid].time)) {
+ lpSSIM->rgTime[pid].vtType = VT_EMPTY;
+ return 0;
+ }
+ }
+ return 1;
+}
+
+} //END C
diff --git a/private/oleutest/letest/ole2ui/suminfo.h b/private/oleutest/letest/ole2ui/suminfo.h
new file mode 100644
index 000000000..ef803ab65
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/suminfo.h
@@ -0,0 +1,331 @@
+/*************************************************************************
+**
+** OLE 2.0 Property Set Utilities
+**
+** suminfo.h
+**
+** This file contains file contains data structure defintions,
+** function prototypes, constants, etc. for OLE 2.0 Property Set
+** utilities used to manage the Summary Info property set.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#ifndef SUMINFO_H
+#define SUMINFO_H
+
+#include <ole2.h>
+
+/* A SUMINFO variable is an instance of an abstract data type. Thus,
+** there can be an arbitrary number of SummaryInfo streams open
+** simultaneously (subject to available memory). Each variable must
+** be initialized prior to use by calling Init and freed after its
+** last use by calling Free. The param argument to Init is reserved
+** for future expansion and should be zero initially. Once a SUMINFO
+** variable is allocated (by Init), the user can call the Set
+** procedures to initialize fields. A copy of the arguments is made
+** in every case except SetThumbnail where control of the storage
+** occupied by the METAFILEPICT is merely transferred. When the
+** Free routine is called, all storage will be deallocated including
+** that of the thumbnail. The arguments to SetThumbNail and the
+** return values from GetThumbNail correspond to the OLE2.0 spec.
+** Note that on input, the thumbnail is read on demand but all the
+** other properties are pre-loaded. The thumbnail is manipulated as
+** a windows handle to a METAFILEPICT structure, which in turn
+** contains a handle to the METAFILE. The transferClip argument on
+** GetThumbNail, when set to true, transfers responsibility for
+** storage management of the thumbnail to the caller; that is, after
+** Free has been called, the handle is still valid. Clear can be
+** used to free storage for all the properties but then you must
+** call Read to load them again. All the code is based on FAR
+** pointers.
+** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo.
+** Memory is allocated using the currently active IMalloc*
+** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
+**
+** Common scenarios:
+** Read SummaryInfo
+** ----------------
+** OleStdInitSummaryInfo()
+** OleStdReadSummaryInfo()
+** . . . . .
+** call different Get routines
+** . . . . .
+** OleStdFreeSummaryInfo()
+**
+** Create SummaryInfo
+** ------------------
+** OleStdInitSummaryInfo()
+** call different Set routines
+** OleStdWriteSummaryInfo()
+** OleStdFreeSummaryInfo()
+**
+** Update SummaryInfo
+** ------------------
+** OleStdInitSummaryInfo()
+** OleStdReadSummaryInfo()
+** OleStdGetThumbNailProperty(necessary only if no SetThumb)
+** call different Set routines
+** OleStdWriteSummaryInfo()
+** OleStdFreeSummaryInfo()
+*/
+
+#define WORDMAX 256 //current string max for APPS; 255 + null terminator
+
+
+typedef union {
+ short iVal; /* VT_I2 */
+ long lVal; /* VT_I4 */
+ float fltVal; /* VT_R4 */
+ double dblVal; /* VT_R8 */
+ DWORD bool; /* VT_BOOL */
+ SCODE scodeVal; /* VT_ERROR */
+ DWORD systimeVal; /* VT_SYSTIME */
+#ifdef UNICODE
+ TCHAR bstrVal[WORDMAX]; /* VT_BSTR */
+#else
+ unsigned char bstrVal[WORDMAX]; /* VT_BSTR */
+#endif
+ } VTUNION;
+
+#if 0
+typedef struct _FMTID
+ {
+ DWORD dword;
+ WORD words[2];
+ BYTE bytes[8];
+ } FMTID;
+#endif
+
+typedef struct _PROPSETLIST
+ {
+ FMTID formatID;
+ DWORD byteOffset;
+ } PROPSETLIST;
+
+typedef struct _PROPIDLIST
+ {
+ DWORD propertyID;
+ DWORD byteOffset;
+ } PROPIDLIST;
+
+typedef struct _PROPVALUE
+ {
+ DWORD vtType;
+ VTUNION vtValue;
+ } PROPVALUE;
+
+typedef struct _SECTION
+ {
+ DWORD cBytes;
+ DWORD cProperties;
+ PROPIDLIST rgPropId[1/*cProperties*/]; //variable-length array
+ PROPVALUE rgPropValue[1]; //CANNOT BE ACCESSED BY NAME; ONLY BY POINTER
+ } SECTION;
+
+typedef struct _SUMMARYINFO
+ {
+ WORD byteOrder;
+ WORD formatVersion;
+ WORD getOSVersion;
+ WORD osVersion;
+ CLSID classId; //from compobj.h
+ DWORD cSections;
+ PROPSETLIST rgPropSet[1/*cSections*/]; //variable-length array
+ SECTION rgSections[1/*cSections*/]; //CANNOT BE ACCESSED BY NAME; ONLY BY POINTER
+ } SUMMARYINFO;
+
+#define osWinOnDos 0
+#define osMac 1
+#define osWinNT 2
+
+#define PID_DICTIONARY 0X00000000
+#define PID_CODEPAGE 0X00000001
+#define PID_TITLE 0X00000002
+#define PID_SUBJECT 0X00000003
+#define PID_AUTHOR 0X00000004
+#define PID_KEYWORDS 0X00000005
+#define PID_COMMENTS 0X00000006
+#define PID_TEMPLATE 0X00000007
+#define PID_LASTAUTHOR 0X00000008
+#define PID_REVNUMBER 0X00000009
+#define PID_EDITTIME 0X0000000A
+#define PID_LASTPRINTED 0X0000000B
+#define PID_CREATE_DTM_RO 0X0000000C
+#define PID_LASTSAVE_DTM 0X0000000D
+#define PID_PAGECOUNT 0X0000000E
+#define PID_WORDCOUNT 0X0000000F
+#define PID_CHARCOUNT 0X00000010
+#define PID_THUMBNAIL 0X00000011
+#define PID_APPNAME 0X00000012
+#define PID_SECURITY 0X00000013
+#define cPID_STANDARD (PID_SECURITY+1-2)
+
+#define MAXWORD 256 //maximum string size for APPS at present
+
+typedef struct _STDZ
+ {
+ DWORD vtType;
+ union {
+ DWORD vtByteCount;
+#ifdef UNICODE
+ TCHAR fill[4]; //use last byte as byte count for stz requests
+#else
+ unsigned char fill[4]; //use last byte as byte count for stz requests
+#endif
+ };
+
+#ifdef UNICODE
+ TCHAR rgchars[MAXWORD];
+#else
+ unsigned char rgchars[MAXWORD];
+#endif
+ } STDZ;
+#define VTCB fill[3] //used to set/get the count byte when in memory
+
+typedef struct _THUMB
+ {
+ DWORD vtType;
+ DWORD cBytes; //clip size in memory
+ DWORD selector; //on disk -1,win clip no. -2,mac clip no. -3,ole FMTID 0,bytes nameLength, format name
+ DWORD clipFormat;
+ char FAR *lpstzName;
+ char FAR *lpByte;
+ } THUMB;
+
+#define VT_CF_BYTES 0
+#define VT_CF_WIN ((DWORD)(-1))
+#define VT_CF_MAC ((DWORD)(-2))
+#define VT_CF_FMTID ((DWORD)(-3))
+#define VT_CF_NAME ((DWORD)(-4))
+#define VT_CF_EMPTY ((DWORD)(-5))
+#define VT_CF_OOM ((DWORD)(-6)) // Out of memory
+typedef THUMB FAR *LPTHUMB;
+
+typedef STDZ FAR *LPSTDZ;
+
+typedef struct _TIME
+ {
+ DWORD vtType;
+ FILETIME time;
+ } TIME;
+
+typedef struct _INTS
+ {
+ DWORD vtType;
+ DWORD value;
+ } INTS;
+
+#define MAXTIME (PID_LASTSAVE_DTM-PID_EDITTIME+1)
+#define MAXINTS (PID_CHARCOUNT-PID_PAGECOUNT+1+1)
+#define MAXSTDZ (PID_REVNUMBER-PID_TITLE+1+1)
+
+typedef struct _STANDARDSECINMEM
+ {
+ DWORD cBytes;
+ DWORD cProperties;
+ PROPIDLIST rgPropId[cPID_STANDARD/*cProperties*/]; //variable-length array
+ TIME rgTime[MAXTIME];
+ INTS rgInts[MAXINTS];
+ LPSTDZ rglpsz[MAXSTDZ];
+ THUMB thumb;
+ } STANDARDSECINMEM;
+
+
+#define OFFSET_NIL 0X00000000
+
+#define AllSecurityFlagsEqNone 0
+#define fSecurityPassworded 1
+#define fSecurityRORecommended 2
+#define fSecurityRO 4
+#define fSecurityLockedForAnnotations 8
+
+#define PropStreamNamePrefixByte '\005'
+#define PropStreamName "\005SummaryInformation"
+#define cbNewSummaryInfo(nSection) (sizeof(SUMMARYINFO)-sizeof(SECTION)+sizeof(PROPSETLIST)*((nSection)-1))
+#define cbNewSection(nPropIds) (sizeof(SECTION)-sizeof(PROPVALUE)+sizeof(PROPIDLIST)*((nPropIds)-1))
+
+#define FIntelOrder(prop) ((prop)->byteOrder==0xfffe)
+#define SetOs(prop, os) {(prop)->osVersion=os; (prop)->getOSVersion=LOWORD(GetVersion());}
+#define SetSumInfFMTID(fmtId) {(fmtId)->Data1=0XF29F85E0; *(long FAR *)&(fmtId)->Data2=0X10684FF9;\
+ *(long FAR *)&(fmtId)->Data4[0]=0X000891AB; *(long FAR *)&(fmtId)->Data4[4]=0XD9B3272B;}
+#define FEqSumInfFMTID(fmtId) ((fmtId)->Data1==0XF29F85E0&&*((long FAR *)&(fmtId)->Data2)==0X10684FF9&&\
+ *((long FAR *)&(fmtId)->Data4[0])==0X000891AB&&*((long FAR *)&(fmtId)->Data4[4])==0XD9B3272B)
+#define FSzEqPropStreamName(sz) _fstricmp(sz, PropStreamName)
+#define ClearSumInf(lpsuminf, cb) {_fmemset(lpsuminf,0,cb); (lpsuminf)->byteOrder=0xfffe;\
+ SetOs(lpsuminf, osWinOnDos);}
+
+typedef void FAR *LPSUMINFO;
+typedef LPTSTR LPSTZR;
+typedef void FAR *THUMBNAIL; //for VT_CF_WIN this is an unlocked global handle
+#define API __far __pascal
+
+
+/*************************************************************************
+** Public Summary Info Property Set Management API
+*************************************************************************/
+
+extern "C" {
+STDAPI_(LPSUMINFO) OleStdInitSummaryInfo(int reserved);
+STDAPI_(void) OleStdFreeSummaryInfo(LPSUMINFO FAR *lplp);
+STDAPI_(void) OleStdClearSummaryInfo(LPSUMINFO lp);
+STDAPI_(int) OleStdReadSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp);
+STDAPI_(int) OleStdWriteSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp);
+STDAPI_(DWORD) OleStdGetSecurityProperty(LPSUMINFO lp);
+STDAPI_(int) OleStdSetSecurityProperty(LPSUMINFO lp, DWORD security);
+STDAPI_(LPTSTR) OleStdGetStringProperty(LPSUMINFO lp, DWORD pid);
+STDAPI_(int) OleStdSetStringProperty(LPSUMINFO lp, DWORD pid, LPTSTR lpsz);
+STDAPI_(LPSTZR) OleStdGetStringZProperty(LPSUMINFO lp, DWORD pid);
+STDAPI_(void) OleStdGetDocProperty(
+ LPSUMINFO lp,
+ DWORD FAR* nPage,
+ DWORD FAR* nWords,
+ DWORD FAR* nChars
+);
+STDAPI_(int) OleStdSetDocProperty(
+ LPSUMINFO lp,
+ DWORD nPage,
+ DWORD nWords,
+ DWORD nChars
+);
+STDAPI_(int) OleStdGetThumbNailProperty(
+ LPSTREAM lps,
+ LPSUMINFO lp,
+ DWORD FAR* clipFormatNo,
+ LPTSTR FAR* lpszName,
+ THUMBNAIL FAR* clip,
+ DWORD FAR* byteCount,
+ BOOL transferClip
+);
+STDAPI_(int) OleStdSetThumbNailProperty(
+ LPSTREAM lps,
+ LPSUMINFO lp,
+ int vtcfNo,
+ DWORD clipFormatNo,
+ LPTSTR lpszName,
+ THUMBNAIL clip,
+ DWORD byteCount
+);
+STDAPI_(void) OleStdGetDateProperty(
+ LPSUMINFO lp,
+ DWORD pid,
+ int FAR* yr,
+ int FAR* mo,
+ int FAR* dy,
+ DWORD FAR* sc
+);
+STDAPI_(int) OleStdSetDateProperty(
+ LPSUMINFO lp,
+ DWORD pid,
+ int yr,
+ int mo,
+ int dy,
+ int hr,
+ int mn,
+ int sc
+);
+
+} //END C
+
+#endif // SUMINFO_H
diff --git a/private/oleutest/letest/ole2ui/targtdev.c b/private/oleutest/letest/ole2ui/targtdev.c
new file mode 100644
index 000000000..55b6b0886
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/targtdev.c
@@ -0,0 +1,328 @@
+/*************************************************************************
+**
+** OLE 2 Standard Utilities
+**
+** olestd.c
+**
+** This file contains utilities that are useful for dealing with
+** target devices.
+**
+** (c) Copyright Microsoft Corp. 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#define STRICT 1
+#include "ole2ui.h"
+#ifndef WIN32
+#include <print.h>
+#endif
+
+/*
+ * OleStdCreateDC()
+ *
+ * Purpose:
+ *
+ * Parameters:
+ *
+ * Return Value:
+ * SCODE - S_OK if successful
+ */
+STDAPI_(HDC) OleStdCreateDC(DVTARGETDEVICE FAR* ptd)
+{
+ HDC hdc=NULL;
+ LPDEVNAMES lpDevNames;
+ LPDEVMODE lpDevMode;
+ LPTSTR lpszDriverName;
+ LPTSTR lpszDeviceName;
+ LPTSTR lpszPortName;
+
+ if (ptd == NULL) {
+ hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
+ goto errReturn;
+ }
+
+ lpDevNames = (LPDEVNAMES) ptd; // offset for size field
+
+ if (ptd->tdExtDevmodeOffset == 0) {
+ lpDevMode = NULL;
+ }else{
+ lpDevMode = (LPDEVMODE) ((LPSTR)ptd + ptd->tdExtDevmodeOffset);
+ }
+
+ lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset;
+ lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset;
+ lpszPortName = (LPTSTR) lpDevNames + ptd->tdPortNameOffset;
+
+ hdc = CreateDC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode);
+
+errReturn:
+ return hdc;
+}
+
+
+/*
+ * OleStdCreateIC()
+ *
+ * Purpose: Same as OleStdCreateDC, except that information context is
+ * created, rather than a whole device context. (CreateIC is
+ * used rather than CreateDC).
+ * OleStdDeleteDC is still used to delete the information context.
+ *
+ * Parameters:
+ *
+ * Return Value:
+ * SCODE - S_OK if successful
+ */
+STDAPI_(HDC) OleStdCreateIC(DVTARGETDEVICE FAR* ptd)
+{
+ HDC hdcIC=NULL;
+ LPDEVNAMES lpDevNames;
+ LPDEVMODE lpDevMode;
+ LPTSTR lpszDriverName;
+ LPTSTR lpszDeviceName;
+ LPTSTR lpszPortName;
+
+ if (ptd == NULL) {
+ hdcIC = CreateIC(TEXT("DISPLAY"), NULL, NULL, NULL);
+ goto errReturn;
+ }
+
+ lpDevNames = (LPDEVNAMES) ptd; // offset for size field
+
+ lpDevMode = (LPDEVMODE) ((LPTSTR)ptd + ptd->tdExtDevmodeOffset);
+
+ lpszDriverName = (LPTSTR) lpDevNames + ptd->tdDriverNameOffset;
+ lpszDeviceName = (LPTSTR) lpDevNames + ptd->tdDeviceNameOffset;
+ lpszPortName = (LPTSTR) lpDevNames + ptd->tdPortNameOffset;
+
+ hdcIC = CreateIC(lpszDriverName, lpszDeviceName, lpszPortName, lpDevMode);
+
+errReturn:
+ return hdcIC;
+}
+
+
+#ifdef NEVER
+// This code is wrong
+/*
+ * OleStdCreateTargetDevice()
+ *
+ * Purpose:
+ *
+ * Parameters:
+ *
+ * Return Value:
+ * SCODE - S_OK if successful
+ */
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCreateTargetDevice(LPPRINTDLG lpPrintDlg)
+{
+ DVTARGETDEVICE FAR* ptd=NULL;
+ LPDEVNAMES lpDevNames, pDN;
+ LPDEVMODE lpDevMode, pDM;
+ UINT nMaxOffset;
+ LPTSTR pszName;
+ DWORD dwDevNamesSize, dwDevModeSize, dwPtdSize;
+
+ if ((pDN = (LPDEVNAMES)GlobalLock(lpPrintDlg->hDevNames)) == NULL) {
+ goto errReturn;
+ }
+
+ if ((pDM = (LPDEVMODE)GlobalLock(lpPrintDlg->hDevMode)) == NULL) {
+ goto errReturn;
+ }
+
+ nMaxOffset = (pDN->wDriverOffset > pDN->wDeviceOffset) ?
+ pDN->wDriverOffset : pDN->wDeviceOffset ;
+
+ nMaxOffset = (pDN->wOutputOffset > nMaxOffset) ?
+ pDN->wOutputOffset : nMaxOffset ;
+
+ pszName = (LPTSTR)pDN + nMaxOffset;
+
+ dwDevNamesSize = (DWORD)((nMaxOffset+lstrlen(pszName) + 1/* NULL term */)*sizeof(TCHAR));
+ dwDevModeSize = (DWORD) (pDM->dmSize + pDM->dmDriverExtra);
+
+ dwPtdSize = sizeof(DWORD) + dwDevNamesSize + dwDevModeSize;
+
+ if ((ptd = (DVTARGETDEVICE FAR*)OleStdMalloc(dwPtdSize)) != NULL) {
+
+ // copy in the info
+ ptd->tdSize = (UINT)dwPtdSize;
+
+ lpDevNames = (LPDEVNAMES) &ptd->tdDriverNameOffset;
+ _fmemcpy(lpDevNames, pDN, (size_t)dwDevNamesSize);
+
+ lpDevMode=(LPDEVMODE)((LPTSTR)&ptd->tdDriverNameOffset+dwDevNamesSize);
+ _fmemcpy(lpDevMode, pDM, (size_t)dwDevModeSize);
+
+ ptd->tdDriverNameOffset += 4 ;
+ ptd->tdDeviceNameOffset += 4 ;
+ ptd->tdPortNameOffset += 4 ;
+ ptd->tdExtDevmodeOffset = (UINT)dwDevNamesSize + 4 ;
+ }
+
+errReturn:
+ GlobalUnlock(lpPrintDlg->hDevNames);
+ GlobalUnlock(lpPrintDlg->hDevMode);
+
+ return ptd;
+}
+#endif // NEVER
+
+
+
+/*
+ * OleStdDeleteTargetDevice()
+ *
+ * Purpose:
+ *
+ * Parameters:
+ *
+ * Return Value:
+ * SCODE - S_OK if successful
+ */
+STDAPI_(BOOL) OleStdDeleteTargetDevice(DVTARGETDEVICE FAR* ptd)
+{
+ BOOL res=TRUE;
+
+ if (ptd != NULL) {
+ OleStdFree(ptd);
+ }
+
+ return res;
+}
+
+
+
+/*
+ * OleStdCopyTargetDevice()
+ *
+ * Purpose:
+ * duplicate a TARGETDEVICE struct. this function allocates memory for
+ * the copy. the caller MUST free the allocated copy when done with it
+ * using the standard allocator returned from CoGetMalloc.
+ * (OleStdFree can be used to free the copy).
+ *
+ * Parameters:
+ * ptdSrc pointer to source TARGETDEVICE
+ *
+ * Return Value:
+ * pointer to allocated copy of ptdSrc
+ * if ptdSrc==NULL then retuns NULL is returned.
+ * if ptdSrc!=NULL and memory allocation fails, then NULL is returned
+ */
+STDAPI_(DVTARGETDEVICE FAR*) OleStdCopyTargetDevice(DVTARGETDEVICE FAR* ptdSrc)
+{
+ DVTARGETDEVICE FAR* ptdDest = NULL;
+
+ if (ptdSrc == NULL) {
+ return NULL;
+ }
+
+ if ((ptdDest = (DVTARGETDEVICE FAR*)OleStdMalloc(ptdSrc->tdSize)) != NULL) {
+ _fmemcpy(ptdDest, ptdSrc, (size_t)ptdSrc->tdSize);
+ }
+
+ return ptdDest;
+}
+
+
+/*
+ * OleStdCopyFormatEtc()
+ *
+ * Purpose:
+ * Copies the contents of a FORMATETC structure. this function takes
+ * special care to copy correctly copying the pointer to the TARGETDEVICE
+ * contained within the source FORMATETC structure.
+ * if the source FORMATETC has a non-NULL TARGETDEVICE, then a copy
+ * of the TARGETDEVICE will be allocated for the destination of the
+ * FORMATETC (petcDest).
+ *
+ * OLE2NOTE: the caller MUST free the allocated copy of the TARGETDEVICE
+ * within the destination FORMATETC when done with it
+ * using the standard allocator returned from CoGetMalloc.
+ * (OleStdFree can be used to free the copy).
+ *
+ * Parameters:
+ * petcDest pointer to destination FORMATETC
+ * petcSrc pointer to source FORMATETC
+ *
+ * Return Value:
+ * returns TRUE is copy is successful; retuns FALSE if not successful
+ */
+STDAPI_(BOOL) OleStdCopyFormatEtc(LPFORMATETC petcDest, LPFORMATETC petcSrc)
+{
+ if ((petcDest == NULL) || (petcSrc == NULL)) {
+ return FALSE;
+ }
+
+ petcDest->cfFormat = petcSrc->cfFormat;
+ petcDest->ptd = OleStdCopyTargetDevice(petcSrc->ptd);
+ petcDest->dwAspect = petcSrc->dwAspect;
+ petcDest->lindex = petcSrc->lindex;
+ petcDest->tymed = petcSrc->tymed;
+
+ return TRUE;
+
+}
+
+
+// returns 0 for exact match, 1 for no match, -1 for partial match (which is
+// defined to mean the left is a subset of the right: fewer aspects, null target
+// device, fewer medium).
+
+STDAPI_(int) OleStdCompareFormatEtc(FORMATETC FAR* pFetcLeft, FORMATETC FAR* pFetcRight)
+{
+ BOOL bExact = TRUE;
+
+ if (pFetcLeft->cfFormat != pFetcRight->cfFormat)
+ return 1;
+ else if (!OleStdCompareTargetDevice (pFetcLeft->ptd, pFetcRight->ptd))
+ return 1;
+ if (pFetcLeft->dwAspect == pFetcRight->dwAspect)
+ // same aspects; equal
+ ;
+ else if ((pFetcLeft->dwAspect & ~pFetcRight->dwAspect) != 0)
+ // left not subset of aspects of right; not equal
+ return 1;
+ else
+ // left subset of right
+ bExact = FALSE;
+
+ if (pFetcLeft->tymed == pFetcRight->tymed)
+ // same medium flags; equal
+ ;
+ else if ((pFetcLeft->tymed & ~pFetcRight->tymed) != 0)
+ // left not subset of medium flags of right; not equal
+ return 1;
+ else
+ // left subset of right
+ bExact = FALSE;
+
+ return bExact ? 0 : -1;
+}
+
+
+
+STDAPI_(BOOL) OleStdCompareTargetDevice
+ (DVTARGETDEVICE FAR* ptdLeft, DVTARGETDEVICE FAR* ptdRight)
+{
+ if (ptdLeft == ptdRight)
+ // same address of td; must be same (handles NULL case)
+ return TRUE;
+ else if ((ptdRight == NULL) || (ptdLeft == NULL))
+ return FALSE;
+ else if (ptdLeft->tdSize != ptdRight->tdSize)
+ // different sizes, not equal
+ return FALSE;
+#ifdef WIN32
+ else if (memcmp(ptdLeft, ptdRight, ptdLeft->tdSize) != 0)
+#else
+ else if (_fmemcmp(ptdLeft, ptdRight, (int)ptdLeft->tdSize) != 0)
+#endif
+ // not same target device, not equal
+ return FALSE;
+
+ return TRUE;
+}
+
diff --git a/private/oleutest/letest/ole2ui/template.c b/private/oleutest/letest/ole2ui/template.c
new file mode 100644
index 000000000..9c35b4c2f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/template.c
@@ -0,0 +1,243 @@
+/*
+ * TEMPLATE.C
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ *
+ *
+ * CUSTOMIZATION INSTRUCTIONS:
+ *
+ * 1. Replace <FILE> with the uppercased filename for this file.
+ * Lowercase the <FILE>.h entry
+ *
+ * 2. Replace <NAME> with the mixed case dialog name in one word,
+ * such as InsertObject
+ *
+ * 3. Replace <FULLNAME> with the mixed case dialog name in multiple
+ * words, such as Insert Object
+ *
+ * 4. Replace <ABBREV> with the suffix for pointer variables, such
+ * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI.
+ * Check the alignment of the first variable declaration in the
+ * Dialog Proc after this. I will probably be misaligned with the
+ * rest of the variables.
+ *
+ * 5. Replace <STRUCT> with the uppercase structure name for this
+ * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI<STRUCT>
+ * in most cases, but we also use this for IDD_<STRUCT> as the
+ * standard template resource ID.
+ *
+ * 6. Find <UFILL> fields and fill them out with whatever is appropriate.
+ *
+ * 7. Delete this header up to the start of the next comment.
+ */
+
+
+/*
+ * <FILE>.C
+ *
+ * Implements the OleUI<NAME> function which invokes the complete
+ * <FULLNAME> dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include "common.h"
+
+#ifndef WIN32
+#include "<FILE>.h"
+#else
+ #include "template.h"
+#endif
+
+
+
+
+/*
+ * OleUI<NAME>
+ *
+ * Purpose:
+ * Invokes the standard OLE <FULLNAME> dialog box allowing the user
+ * to <UFILL>
+ *
+ * Parameters:
+ * lp<ABBREV> LPOLEUI<NAME> 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
+ */
+
+STDAPI_(UINT) OleUI<NAME>(LPOLEUI<STRUCT> lp<ABBREV>)
+ {
+ UINT uRet;
+ HGLOBAL hMemDlg=NULL;
+
+ uRet=UStandardValidation((LPOLEUISTANDARD)lp<ABBREV>, sizeof(OLEUI<STRUCT>)
+ , &hMemDlg);
+
+ if (OLEUI_SUCCESS!=uRet)
+ return uRet;
+
+ /*
+ * PERFORM ANY STRUCTURE-SPECIFIC VALIDATION HERE!
+ * ON FAILURE:
+ * {
+ * if (NULL!=hMemDlg)
+ * FreeResource(hMemDlg)
+ *
+ * return OLEUI_<ABBREV>ERR_<ERROR>
+ * }
+ */
+
+ //Now that we've validated everything, we can invoke the dialog.
+ uRet=UStandardInvocation(<NAME>DialogProc, (LPOLEUISTANDARD)lp<ABBREV>
+ , hMemDlg, MAKEINTRESOURCE(IDD_<STRUCT>));
+
+ /*
+ * IF YOU ARE CREATING ANYTHING BASED ON THE RESULTS, DO IT HERE.
+ */
+ <UFILL>
+
+ return uRet;
+ }
+
+
+
+
+
+/*
+ * <NAME>DialogProc
+ *
+ * Purpose:
+ * Implements the OLE <FULLNAME> dialog as invoked through the
+ * OleUI<NAME> function.
+ *
+ * Parameters:
+ * Standard
+ *
+ * Return Value:
+ * Standard
+ */
+
+BOOL CALLBACK EXPORT <NAME>DialogProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
+ {
+ P<STRUCT> p<ABBREV>;
+ BOOL fHook=FALSE;
+
+ //Declare Win16/Win32 compatible WM_COMMAND parameters.
+ COMMANDPARAMS(wID, wCode, hWndMsg);
+
+ //This will fail under WM_INITDIALOG, where we allocate it.
+ p<ABBREV>=(<STRUCT>)PvStandardEntry(hDlg, iMsg, wParam, lParam, &uHook);
+
+ //If the hook processed the message, we're done.
+ if (0!=uHook)
+ return (BOOL)uHook;
+
+ //Process the temination message
+ if (iMsg==uMsgEndDialog)
+ {
+ //Free any specific allocations before calling StandardCleanup
+ StandardCleanup((PVOID)p<ABBREV>, hDlg);
+ EndDialog(hDlg, wParam);
+ return TRUE;
+ }
+
+ switch (iMsg)
+ {
+ case WM_INITDIALOG:
+ F<NAME>Init(hDlg, wParam, lParam);
+ return TRUE;
+
+
+ case WM_COMMAND:
+ switch (wID)
+ {
+ case IDOK:
+ /*
+ * PERFORM WHATEVER FUNCTIONS ARE DEFAULT HERE.
+ */
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_OK, 0L);
+ break;
+
+ case IDCANCEL:
+ /*
+ * PERFORM ANY UNDOs HERE, BUT NOT CLEANUP THAT WILL
+ * ALWAYS HAPPEN WHICH SHOULD BE IN uMsgEndDialog.
+ */
+ SendMessage(hDlg, uMsgEndDialog, OLEUI_CANCEL, 0L);
+ break;
+
+ case ID_OLEUIHELP:
+ PostMessage(p<ABBREV>->lpO<ABBREV>->hWndOwner, uMsgHelp
+ , (WPARAM)hDlg, MAKELPARAM(IDD_<STRUCT>, 0));
+ break;
+ }
+ break;
+ }
+ return FALSE;
+ }
+
+
+
+
+/*
+ * F<NAME>Init
+ *
+ * Purpose:
+ * WM_INITIDIALOG handler for the <FULLNAME> dialog box.
+ *
+ * Parameters:
+ * hDlg HWND of the dialog
+ * wParam WPARAM of the message
+ * lParam LPARAM of the message
+ *
+ * Return Value:
+ * BOOL Value to return for WM_INITDIALOG.
+ */
+
+BOOL F<NAME>Init(HWND hDlg, WPARAM wParam, LPARAM lParam)
+ {
+ P<STRUCT> p<ABBREV>;
+ LPOLEUI<STRUCT> lpO<ABBREV>;
+ HFONT hFont;
+
+ //1. Copy the structure at lParam into our instance memory.
+ p<ABBREV>=(PSTRUCT)PvStandardInit(hDlg, sizeof(<STRUCT>), TRUE, &hFont);
+
+ //PvStandardInit send a termination to us already.
+ if (NULL==p<ABBREV>)
+ return FALSE;
+
+ lpO<ABBREV>=(LPOLEUI<STRUCT>)lParam);
+
+ p<ABBREV>->lpO<ABBREV>=lpO<ABBREV>;
+
+ //Copy other information from lpO<ABBREV> that we might modify.
+ <UFILL>
+
+ //2. 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, ID_<UFILL>, WM_SETFONT, (WPARAM)hFont, 0L);
+ }
+
+
+ //3. Show or hide the help button
+ if (!(p<ABBREV>->lpO<ABBREV>->dwFlags & <ABBREV>F_SHOWHELP))
+ StandardShowDlgItem(hDlg, ID_OLEUIHELP, SW_HIDE);
+
+ /*
+ * PERFORM OTHER INITIALIZATION HERE. ON ANY LoadString
+ * FAILURE POST OLEUI_MSG_ENDDIALOG WITH OLEUI_ERR_LOADSTRING.
+ */
+
+ //n. Call the hook with lCustData in lParam
+ UStandardHook((PVOID)p<ABBREV>, hDlg, WM_INITDIALOG, wParam, lpO<ABBREV>->lCustData);
+ return TRUE;
+ }
diff --git a/private/oleutest/letest/ole2ui/template.h b/private/oleutest/letest/ole2ui/template.h
new file mode 100644
index 000000000..3f277aec1
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/template.h
@@ -0,0 +1,119 @@
+/*
+ * TEMPLATE.H
+ *
+ * CUSTOMIZATION INSTRUCTIONS:
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ *
+ *
+ * 1. Replace <FILE> with the uppercased filename for this file.
+ * Lowercase the <FILE>.h entry
+ *
+ * 2. Replace <NAME> with the mixed case dialog name in one word,
+ * such as InsertObject
+ *
+ * 3. Replace <FULLNAME> with the mixed case dialog name in multiple
+ * words, such as Insert Object
+ *
+ * 4. Replace <ABBREV> with the suffix for pointer variables, such
+ * as the IO in InsertObject's pIO or the CI in ChangeIcon's pCI.
+ * Check the alignment of the first variable declaration in the
+ * Dialog Proc after this. I will probably be misaligned with the
+ * rest of the variables.
+ *
+ * 5. Replace <STRUCT> with the uppercase structure name for this
+ * dialog sans OLEUI, such as INSERTOBJECT. Changes OLEUI<STRUCT>
+ * in most cases, but we also use this for IDD_<STRUCT> as the
+ * standard template resource ID.
+ *
+ * 6. Find <UFILL> fields and fill them out with whatever is appropriate.
+ *
+ * 7. Delete this header up to the start of the next comment.
+ *
+ */
+
+
+/*
+ * <FILE>.H
+ *
+ * Internal definitions, structures, and function prototypes for the
+ * OLE 2.0 UI <FULLNAME> dialog.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef <UFILL>
+#define <UFILL>
+
+//UFILL> Move from here to INTERNAL to to OLE2UI.H
+
+
+typedef struct tagOLEUI<STRUCT>
+ {
+ //These IN fields are standard across all OLEUI dialog functions.
+ DWORD cbStruct; //Structure Size
+ DWORD dwFlags; //IN-OUT: Flags
+ HWND hWndOwner; //Owning window
+ LPCTSTR lpszCaption; //Dialog caption bar contents
+ LPFNOLEUIHOOK lpfnHook; //Hook callback
+ LPARAM lCustData; //Custom data to pass to hook
+ HINSTANCE hInstance; //Instance for customized template name
+ LPCTSTR lpszTemplate; //Customized template name
+ HRSRC hResource; //Customized template handle
+
+ //Specifics for OLEUI<STRUCT>. All are IN-OUT unless otherwise spec.
+ } OLEUI<STRUCT>, *POLEUI<STRUCT>, FAR *LPOLEUI<STRUCT>;
+
+
+//API Prototype
+UINT FAR PASCAL OleUI<NAME>(LPOLEUI<STRUCT>);
+
+
+//<FULLNAME> flags
+#define <ABBREV>F_SHOWHELP 0x00000001L
+<UFILL>
+
+
+//<FULLNAME> specific error codes
+//DEFINE AS OLEUI_<ABBREV>ERR_<ERROR> (OLEUI_ERR_STANDARDMAX+n)
+<UFILL>
+
+
+//<FULLNAME> Dialog identifiers
+//FILL IN DIALOG IDs HERE
+<UFILL>
+
+
+
+
+
+//INTERNAL INFORMATION STARTS HERE
+
+//Internally used structure
+typedef struct tag<STRUCT>
+ {
+ //Keep this item first as the Standard* functions depend on it here.
+ LPOLEUI<STRUCT> lpO<ABBREV>; //Original structure passed.
+
+ /*
+ * What we store extra in this structure besides the original caller's
+ * pointer are those fields that we need to modify during the life of
+ * the dialog but that we don't want to change in the original structure
+ * until the user presses OK.
+ */
+
+ <UFILL>
+ } <STRUCT>, *P<STRUCT>;
+
+
+
+//Internal function prototypes
+//<FILE>.C
+BOOL FAR PASCAL <NAME>DialogProc(HWND, UINT, WPARAM, LPARAM);
+BOOL F<NAME>Init(HWND hDlg, WPARAM, LPARAM);
+<UFILL>
+
+
+
+#endif //<UFILL>
diff --git a/private/oleutest/letest/ole2ui/uiclass.h b/private/oleutest/letest/ole2ui/uiclass.h
new file mode 100644
index 000000000..801819141
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/uiclass.h
@@ -0,0 +1,2 @@
+#define SZCLASSICONBOX TEXT("OLE2UIIBClass")
+#define SZCLASSRESULTIMAGE TEXT("OLE2UIRIClass")
diff --git a/private/oleutest/letest/ole2ui/uimake.cmd b/private/oleutest/letest/ole2ui/uimake.cmd
new file mode 100644
index 000000000..b6bd1f6c7
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/uimake.cmd
@@ -0,0 +1 @@
+nmake -f ole2ui.mak %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/private/oleutest/letest/ole2ui/uimake.ini b/private/oleutest/letest/ole2ui/uimake.ini
new file mode 100644
index 000000000..a7d847908
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/uimake.ini
@@ -0,0 +1,24 @@
+# This is the DEBUG static .LIB UILibrary INI file
+MSG=DEBUG Static LIB Version ($(LANG))
+DEBUG=1
+MODEL=M
+# Make a static library called OLE2UI.LIB
+LIBNAME=OLE2UI
+REL_DIR=d:\cairo\cairole\h\export
+OLEREL_DIR=d:\cairo\cairole\h\export
+OBJ=DEBUGLIB
+BUILD=LIB
+RESOURCE=RESOURCE
+
+# 16 bit CFLAGS=-c -Od -GA2s -W3 -Zpei -AM -D_DEBUG -DWIN32 -DUNICODE
+
+CFLAGS=-c -Od -Gs -W3 -Zpei -D_DEBUG -DWIN32 -DUNICODE
+RFLAGS=-D DEBUG
+LFLAGS=/MAP:FULL /CO /LINE /NOD /NOE /SE:300 /NOPACKCODE
+UILIBS=mlibcew libw ole2 storage shell commdlg toolhelp
+CC=cl
+AS=masm
+RS=rc
+LK=link
+LANG=USA
+LIBOBJS = $(UI_COBJS:D^\=DEBUGLIB^\) $(UI_NOPCOBJS:D^\=DEBUGLIB\NOPC^\)
diff --git a/private/oleutest/letest/ole2ui/utility.c b/private/oleutest/letest/ole2ui/utility.c
new file mode 100644
index 000000000..98deecc25
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/utility.c
@@ -0,0 +1,1039 @@
+/*
+ * UTILITY.C
+ *
+ * Utility routines for functions inside OLE2UI.DLL
+ *
+ * General:
+ * ----------------------
+ * HourGlassOn Displays the hourglass
+ * HourGlassOff Hides the hourglass
+ *
+ * Misc Tools:
+ * ----------------------
+ * Browse Displays the "File..." or "Browse..." dialog.
+ * ReplaceCharWithNull Used to form filter strings for Browse.
+ * ErrorWithFile Creates an error message with embedded filename
+ * OpenFileError Give error message for OpenFile error return
+ * ChopText Chop a file path to fit within a specified width
+ * DoesFileExist Checks if file is valid
+ *
+ * Registration Database:
+ * ----------------------
+ * HIconFromClass Extracts the first icon in a class's server path
+ * FServerFromClass Retrieves the server path for a class name (fast)
+ * UClassFromDescription Finds the classname given a description (slow)
+ * UDescriptionFromClass Retrieves the description for a class name (fast)
+ * FGetVerb Retrieves a specific verb for a class (fast)
+ *
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+#define STRICT 1
+#include "ole2ui.h"
+#include <stdlib.h>
+#include <commdlg.h>
+#include <memory.h>
+#include <cderr.h>
+#include "common.h"
+#include "utility.h"
+#include "geticon.h"
+
+OLEDBGDATA
+
+/*
+ * HourGlassOn
+ *
+ * Purpose:
+ * Shows the hourglass cursor returning the last cursor in use.
+ *
+ * Parameters:
+ * None
+ *
+ * Return Value:
+ * HCURSOR Cursor in use prior to showing the hourglass.
+ */
+
+HCURSOR WINAPI HourGlassOn(void)
+ {
+ HCURSOR hCur;
+
+ hCur=SetCursor(LoadCursor(NULL, IDC_WAIT));
+ ShowCursor(TRUE);
+
+ return hCur;
+ }
+
+
+
+/*
+ * HourGlassOff
+ *
+ * Purpose:
+ * Turns off the hourglass restoring it to a previous cursor.
+ *
+ * Parameters:
+ * hCur HCURSOR as returned from HourGlassOn
+ *
+ * Return Value:
+ * None
+ */
+
+void WINAPI HourGlassOff(HCURSOR hCur)
+ {
+ ShowCursor(FALSE);
+ SetCursor(hCur);
+ return;
+ }
+
+
+
+
+/*
+ * Browse
+ *
+ * Purpose:
+ * Displays the standard GetOpenFileName dialog with the title of
+ * "Browse." The types listed in this dialog are controlled through
+ * iFilterString. If it's zero, then the types are filled with "*.*"
+ * Otherwise that string is loaded from resources and used.
+ *
+ * Parameters:
+ * hWndOwner HWND owning the dialog
+ * lpszFile LPSTR specifying the initial file and the buffer in
+ * which to return the selected file. If there is no
+ * initial file the first character of this string should
+ * be NULL.
+ * lpszInitialDir LPSTR specifying the initial directory. If none is to
+ * set (ie, the cwd should be used), then this parameter
+ * should be NULL.
+ * cchFile UINT length of pszFile
+ * iFilterString UINT index into the stringtable for the filter string.
+ * dwOfnFlags DWORD flags to OR with OFN_HIDEREADONLY
+ *
+ * Return Value:
+ * BOOL TRUE if the user selected a file and pressed OK.
+ * FALSE otherwise, such as on pressing Cancel.
+ */
+
+BOOL WINAPI Browse(HWND hWndOwner, LPTSTR lpszFile, LPTSTR lpszInitialDir, UINT cchFile, UINT iFilterString, DWORD dwOfnFlags)
+ {
+ UINT cch;
+ TCHAR szFilters[256];
+ OPENFILENAME ofn;
+ BOOL fStatus;
+ DWORD dwError;
+ TCHAR szDlgTitle[128]; // that should be big enough
+
+ if (NULL==lpszFile || 0==cchFile)
+ return FALSE;
+
+ /*
+ * REVIEW: Exact contents of the filter combobox is TBD. One idea
+ * is to take all the extensions in the RegDB and place them in here
+ * with the descriptive class name associate with them. This has the
+ * extra step of finding all extensions of the same class handler and
+ * building one extension string for all of them. Can get messy quick.
+ * UI demo has only *.* which we do for now.
+ */
+
+ if (0!=iFilterString)
+ cch=LoadString(ghInst, iFilterString, (LPTSTR)szFilters, sizeof(szFilters)/sizeof(TCHAR));
+ else
+ {
+ szFilters[0]=0;
+ cch=1;
+ }
+
+ if (0==cch)
+ return FALSE;
+
+ ReplaceCharWithNull(szFilters, szFilters[cch-1]);
+
+ //Prior string must also be initialized, if there is one.
+ _fmemset((LPOPENFILENAME)&ofn, 0, sizeof(ofn));
+ ofn.lStructSize =sizeof(ofn);
+ ofn.hwndOwner =hWndOwner;
+ ofn.lpstrFile =lpszFile;
+ ofn.nMaxFile =cchFile;
+ ofn.lpstrFilter =(LPTSTR)szFilters;
+ ofn.nFilterIndex=1;
+ if (LoadString(ghInst, IDS_BROWSE, (LPTSTR)szDlgTitle, sizeof(szDlgTitle)/sizeof(TCHAR)))
+ ofn.lpstrTitle =(LPTSTR)szDlgTitle;
+ ofn.hInstance = ghInst;
+ ofn.lpTemplateName = MAKEINTRESOURCE(IDD_FILEOPEN);
+ if (NULL != lpszInitialDir)
+ ofn.lpstrInitialDir = lpszInitialDir;
+
+ ofn.Flags= OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | (dwOfnFlags) ;
+
+ //On success, copy the chosen filename to the static display
+ fStatus = GetOpenFileName((LPOPENFILENAME)&ofn);
+ dwError = CommDlgExtendedError();
+ return fStatus;
+
+ }
+
+
+
+
+
+/*
+ * ReplaceCharWithNull
+ *
+ * Purpose:
+ * Walks a null-terminated string and replaces a given character
+ * with a zero. Used to turn a single string for file open/save
+ * filters into the appropriate filter string as required by the
+ * common dialog API.
+ *
+ * Parameters:
+ * psz LPTSTR to the string to process.
+ * ch int character to replace.
+ *
+ * Return Value:
+ * int Number of characters replaced. -1 if psz is NULL.
+ */
+
+int WINAPI ReplaceCharWithNull(LPTSTR psz, int ch)
+ {
+ int cChanged=-1;
+
+ if (NULL!=psz)
+ {
+ while (0!=*psz)
+ {
+ if (ch==*psz)
+ {
+ *psz=TEXT('\0');
+ cChanged++;
+ }
+ psz++;
+ }
+ }
+ return cChanged;
+ }
+
+
+
+
+
+
+/*
+ * ErrorWithFile
+ *
+ * Purpose:
+ * Displays a message box built from a stringtable string containing
+ * one %s as a placeholder for a filename and from a string of the
+ * filename to place there.
+ *
+ * Parameters:
+ * hWnd HWND owning the message box. The caption of this
+ * window is the caption of the message box.
+ * hInst HINSTANCE from which to draw the idsErr string.
+ * idsErr UINT identifier of a stringtable string containing
+ * the error message with a %s.
+ * lpszFile LPSTR to the filename to include in the message.
+ * uFlags UINT flags to pass to MessageBox, like MB_OK.
+ *
+ * Return Value:
+ * int Return value from MessageBox.
+ */
+
+int WINAPI ErrorWithFile(HWND hWnd, HINSTANCE hInst, UINT idsErr
+ , LPTSTR pszFile, UINT uFlags)
+ {
+ int iRet=0;
+ HANDLE hMem;
+ const UINT cb=(2*OLEUI_CCHPATHMAX_SIZE);
+ LPTSTR psz1, psz2, psz3;
+
+ if (NULL==hInst || NULL==pszFile)
+ return iRet;
+
+ //Allocate three 2*OLEUI_CCHPATHMAX byte work buffers
+ hMem=GlobalAlloc(GHND, (DWORD)(3*cb));
+
+ if (NULL==hMem)
+ return iRet;
+
+ psz1=GlobalLock(hMem);
+ psz2=psz1+cb;
+ psz3=psz2+cb;
+
+ if (0!=LoadString(hInst, idsErr, psz1, cb))
+ {
+ wsprintf(psz2, psz1, pszFile);
+
+ //Steal the caption of the dialog
+ GetWindowText(hWnd, psz3, cb);
+ iRet=MessageBox(hWnd, psz2, psz3, uFlags);
+ }
+
+ GlobalUnlock(hMem);
+ GlobalFree(hMem);
+ return iRet;
+ }
+
+
+
+
+
+
+
+
+
+/*
+ * HIconFromClass
+ *
+ * Purpose:
+ * Given an object class name, finds an associated executable in the
+ * registration database and extracts the first icon from that
+ * executable. If none is available or the class has no associated
+ * executable, this function returns NULL.
+ *
+ * Parameters:
+ * pszClass LPSTR giving the object class to look up.
+ *
+ * Return Value:
+ * HICON Handle to the extracted icon if there is a module
+ * associated to pszClass. NULL on failure to either
+ * find the executable or extract and icon.
+ */
+
+HICON WINAPI HIconFromClass(LPTSTR pszClass)
+ {
+ HICON hIcon;
+ TCHAR szEXE[OLEUI_CCHPATHMAX];
+ UINT Index;
+ CLSID clsid;
+
+ if (NULL==pszClass)
+ return NULL;
+
+ CLSIDFromStringA(pszClass, &clsid);
+
+ if (!FIconFileFromClass((REFCLSID)&clsid, szEXE, OLEUI_CCHPATHMAX_SIZE, &Index))
+ return NULL;
+
+ hIcon=ExtractIcon(ghInst, szEXE, Index);
+
+ if ((HICON)32 > hIcon)
+ hIcon=NULL;
+
+ return hIcon;
+ }
+
+
+
+
+
+/*
+ * FServerFromClass
+ *
+ * Purpose:
+ * Looks up the classname in the registration database and retrieves
+ * the name undet protocol\StdFileEditing\server.
+ *
+ * Parameters:
+ * pszClass LPSTR to the classname to look up.
+ * pszEXE LPSTR at which to store the server name
+ * cch UINT size of pszEXE
+ *
+ * Return Value:
+ * BOOL TRUE if one or more characters were loaded into pszEXE.
+ * FALSE otherwise.
+ */
+
+BOOL WINAPI FServerFromClass(LPTSTR pszClass, LPTSTR pszEXE, UINT cch)
+{
+
+ DWORD dw;
+ LONG lRet;
+ HKEY hKey;
+
+ if (NULL==pszClass || NULL==pszEXE || 0==cch)
+ return FALSE;
+
+ /*
+ * We have to go walking in the registration database under the
+ * classname, so we first open the classname key and then check
+ * under "\\LocalServer" to get the .EXE.
+ */
+
+ //Open up the class key
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, pszClass, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return FALSE;
+
+ //Get the executable path.
+ dw=(DWORD)cch;
+ lRet=RegQueryValue(hKey, TEXT("LocalServer"), pszEXE, &dw);
+
+ RegCloseKey(hKey);
+
+ return ((ERROR_SUCCESS == lRet) && (dw > 0));
+}
+
+
+
+/*
+ * UClassFromDescription
+ *
+ * Purpose:
+ * Looks up the actual OLE class name in the registration database
+ * for the given descriptive name chosen from a listbox.
+ *
+ * Parameters:
+ * psz LPSTR to the descriptive name.
+ * pszClass LPSTR in which to store the class name.
+ * cb UINT maximum length of pszClass.
+ *
+ * Return Value:
+ * UINT Number of characters copied to pszClass. 0 on failure.
+ */
+
+UINT WINAPI UClassFromDescription(LPTSTR psz, LPTSTR pszClass, UINT cb)
+ {
+ DWORD dw;
+ HKEY hKey;
+ TCHAR szClass[OLEUI_CCHKEYMAX];
+ LONG lRet;
+ UINT i;
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return 0;
+
+ i=0;
+ lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX_SIZE);
+
+ //Walk the available keys
+ while ((LONG)ERROR_SUCCESS==lRet)
+ {
+ dw=(DWORD)cb;
+ lRet=RegQueryValue(hKey, szClass, pszClass, &dw);
+
+ //Check if the description matches the one just enumerated
+ if ((LONG)ERROR_SUCCESS==lRet)
+ {
+ if (!lstrcmp(pszClass, psz))
+ break;
+ }
+
+ //Continue with the next key.
+ lRet=RegEnumKey(hKey, i++, szClass, OLEUI_CCHKEYMAX_SIZE);
+ }
+
+ //If we found it, copy to the return buffer
+ if ((LONG)ERROR_SUCCESS==lRet)
+ lstrcpy(pszClass, szClass);
+ else
+ dw=0L;
+
+ RegCloseKey(hKey);
+ return (UINT)dw;
+ }
+
+
+
+
+
+
+
+
+/*
+ * UDescriptionFromClass
+ *
+ * Purpose:
+ * Looks up the actual OLE descriptive name name in the registration
+ * database for the given class name.
+ *
+ * Parameters:
+ * pszClass LPSTR to the class name.
+ * psz LPSTR in which to store the descriptive name.
+ * cb UINT maximum length of psz.
+ *
+ * Return Value:
+ * UINT Number of characters copied to pszClass. 0 on failure.
+ */
+
+UINT WINAPI UDescriptionFromClass(LPTSTR pszClass, LPTSTR psz, UINT cb)
+ {
+ DWORD dw;
+ HKEY hKey;
+ LONG lRet;
+
+ if (NULL==pszClass || NULL==psz)
+ return 0;
+
+ //Open up the root key.
+ lRet=RegOpenKey(HKEY_CLASSES_ROOT, NULL, &hKey);
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return 0;
+
+ //Get the descriptive name using the class name.
+ dw=(DWORD)cb;
+ lRet=RegQueryValue(hKey, pszClass, psz, &dw);
+
+ RegCloseKey(hKey);
+
+ psz+=lstrlen(psz)+1;
+ *psz=0;
+
+ if ((LONG)ERROR_SUCCESS!=lRet)
+ return 0;
+
+ return (UINT)dw;
+ }
+
+
+
+// returns width of line of text. this is a support routine for ChopText
+static LONG GetTextWSize(HDC hDC, LPTSTR lpsz)
+{
+ SIZE size;
+
+ if (GetTextExtentPoint(hDC, lpsz, lstrlen(lpsz), (LPSIZE)&size))
+ return size.cx;
+ else {
+ return 0;
+ }
+}
+
+
+/*
+ * ChopText
+ *
+ * Purpose:
+ * Parse a string (pathname) and convert it to be within a specified
+ * length by chopping the least significant part
+ *
+ * Parameters:
+ * hWnd window handle in which the string resides
+ * nWidth max width of string in pixels
+ * use width of hWnd if zero
+ * lpch pointer to beginning of the string
+ *
+ * Return Value:
+ * pointer to the modified string
+ */
+LPTSTR WINAPI ChopText(HWND hWnd, int nWidth, LPTSTR lpch)
+{
+#define PREFIX_SIZE 7 + 1
+#define PREFIX_FORMAT TEXT("%c%c%c...\\")
+
+ TCHAR szPrefix[PREFIX_SIZE];
+ BOOL fDone = FALSE;
+ int i;
+ RECT rc;
+ HDC hdc;
+ HFONT hfont;
+ HFONT hfontOld = NULL;
+
+ if (!hWnd || !lpch)
+ return NULL;
+
+ /* Get length of static field. */
+ if (!nWidth) {
+ GetClientRect(hWnd, (LPRECT)&rc);
+ nWidth = rc.right - rc.left;
+ }
+
+ /* Set up DC appropriately for the static control */
+ hdc = GetDC(hWnd);
+ hfont = (HFONT)SendMessage(hWnd, WM_GETFONT, 0, 0L);
+
+ if (NULL != hfont) // WM_GETFONT returns NULL if window uses system font
+ hfontOld = SelectObject(hdc, hfont);
+
+ /* check horizontal extent of string */
+ if (GetTextWSize(hdc, lpch) > nWidth) {
+
+ /* string is too long to fit in static control; chop it */
+ /* set up new prefix & determine remaining space in control */
+ wsprintf((LPTSTR) szPrefix, PREFIX_FORMAT, lpch[0], lpch[1], lpch[2]);
+ nWidth -= (int)GetTextWSize(hdc, (LPTSTR) szPrefix);
+
+ /*
+ ** advance a directory at a time until the remainder of the
+ ** string fits into the static control after the "x:\...\" prefix
+ */
+ while (!fDone) {
+
+#ifdef DBCS
+ while (*lpch && (*lpch != TEXT('\\')))
+#ifdef WIN32
+ lpch = CharNext(lpch);
+#else
+ lpch = AnsiNext(lpch);
+#endif
+ if (*lpch)
+#ifdef WIN32
+ lpch = CharNext(lpch);
+#else
+ lpch = AnsiNext(lpch);
+#endif
+#else
+ while (*lpch && (*lpch++ != TEXT('\\')));
+#endif
+
+ if (!*lpch || GetTextWSize(hdc, lpch) <= nWidth) {
+ if (!*lpch)
+ /*
+ ** Nothing could fit after the prefix; remove the
+ ** final "\" from the prefix
+ */
+ szPrefix[lstrlen((LPTSTR) szPrefix) - 1] = 0;
+
+ /* rest or string fits -- stick prefix on front */
+ for (i = lstrlen((LPTSTR) szPrefix) - 1; i >= 0; --i)
+ *--lpch = szPrefix[i];
+ fDone = TRUE;
+ }
+ }
+ }
+
+ if (NULL != hfont)
+ SelectObject(hdc, hfontOld);
+ ReleaseDC(hWnd, hdc);
+
+ return(lpch);
+
+#undef PREFIX_SIZE
+#undef PREFIX_FORMAT
+}
+
+
+/*
+ * OpenFileError
+ *
+ * Purpose:
+ * display message for error returned from OpenFile
+ *
+ * Parameters:
+ * hDlg HWND of the dialog.
+ * nErrCode UINT error code returned in OFSTRUCT passed to OpenFile
+ * lpszFile LPSTR file name passed to OpenFile
+ *
+ * Return Value:
+ * None
+ */
+void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile)
+{
+ switch (nErrCode) {
+ case 0x0005: // Access denied
+ ErrorWithFile(hDlg, ghInst, IDS_CIFILEACCESS, lpszFile, MB_OK);
+ break;
+
+ case 0x0020: // Sharing violation
+ ErrorWithFile(hDlg, ghInst, IDS_CIFILESHARE, lpszFile, MB_OK);
+ break;
+
+ case 0x0002: // File not found
+ case 0x0003: // Path not found
+ ErrorWithFile(hDlg, ghInst, IDS_CIINVALIDFILE, lpszFile, MB_OK);
+ break;
+
+ default:
+ ErrorWithFile(hDlg, ghInst, IDS_CIFILEOPENFAIL, lpszFile, MB_OK);
+ break;
+ }
+}
+
+#define chSpace TEXT(' ')
+#define chPeriod TEXT('.')
+#define PARSE_EMPTYSTRING -1
+#define PARSE_INVALIDDRIVE -2
+#define PARSE_INVALIDPERIOD -3
+#define PARSE_INVALIDDIRCHAR -4
+#define PARSE_INVALIDCHAR -5
+#define PARSE_WILDCARDINDIR -6
+#define PARSE_INVALIDNETPATH -7
+#define PARSE_INVALIDSPACE -8
+#define PARSE_EXTENTIONTOOLONG -9
+#define PARSE_DIRECTORYNAME -10
+#define PARSE_FILETOOLONG -11
+
+/*---------------------------------------------------------------------------
+ * ParseFile
+ * Purpose: Determine if the filename is a legal DOS name
+ * Input: Long pointer to a SINGLE file name
+ * Circumstance checked:
+ * 1) Valid as directory name, but not as file name
+ * 2) Empty String
+ * 3) Illegal Drive label
+ * 4) Period in invalid location (in extention, 1st in file name)
+ * 5) Missing directory character
+ * 6) Illegal character
+ * 7) Wildcard in directory name
+ * 8) Double slash beyond 1st 2 characters
+ * 9) Space character in the middle of the name (trailing spaces OK)
+ * 10) Filename greater than 8 characters
+ * 11) Extention greater than 3 characters
+ * Notes:
+ * Filename length is NOT checked.
+ * Valid filenames will have leading spaces, trailing spaces and
+ * terminating period stripped in place.
+ *
+ * Returns: If valid, LOWORD is byte offset to filename
+ * HIWORD is byte offset to extention
+ * if string ends with period, 0
+ * if no extention is given, string length
+ * If invalid, LOWORD is error code suggesting problem (< 0)
+ * HIWORD is approximate offset where problem found
+ * Note that this may be beyond the offending character
+ *--------------------------------------------------------------------------*/
+
+static long ParseFile(LPTSTR lpstrFileName)
+{
+ short nFile, nExt, nFileOffset, nExtOffset;
+ BOOL bExt;
+ BOOL bWildcard;
+ short nNetwork = 0;
+ BOOL bUNCPath = FALSE;
+ LPTSTR lpstr = lpstrFileName;
+
+/* Strip off initial white space. Note that TAB is not checked */
+/* because it cannot be received out of a standard edit control */
+/* 30 January 1991 clarkc */
+ while (*lpstr == chSpace)
+ lpstr++;
+
+ if (!*lpstr)
+ {
+ nFileOffset = PARSE_EMPTYSTRING;
+ goto FAILURE;
+ }
+
+ if (lpstr != lpstrFileName)
+ {
+ lstrcpy(lpstrFileName, lpstr);
+ lpstr = lpstrFileName;
+ }
+
+ if (
+
+#ifdef WIN32
+ *CharNext(lpstr)
+#else
+ *AnsiNext(lpstr)
+#endif
+ == TEXT(':')
+ )
+
+ {
+ TCHAR cDrive = (*lpstr | (BYTE) 0x20); /* make lowercase */
+
+/* This does not test if the drive exists, only if it's legal */
+ if ((cDrive < TEXT('a')) || (cDrive > TEXT('z')))
+ {
+ nFileOffset = PARSE_INVALIDDRIVE;
+ goto FAILURE;
+ }
+#ifdef WIN32
+ lpstr = CharNext(CharNext(lpstr));
+#else
+ lpstr = AnsiNext(AnsiNext(lpstr));
+#endif
+ }
+
+ if ((*lpstr == TEXT('\\')) || (*lpstr == TEXT('/')))
+ {
+ if (*++lpstr == chPeriod) /* cannot have c:\. */
+ {
+ if ((*++lpstr != TEXT('\\')) && (*lpstr != TEXT('/'))) /* unless it's stupid */
+ {
+ if (!*lpstr) /* it's the root directory */
+ goto MustBeDir;
+
+ nFileOffset = PARSE_INVALIDPERIOD;
+ goto FAILURE;
+ }
+ else
+ ++lpstr; /* it's saying top directory (again), thus allowed */
+ }
+ else if ((*lpstr == TEXT('\\')) && (*(lpstr-1) == TEXT('\\')))
+ {
+/* It seems that for a full network path, whether a drive is declared or
+ * not is insignificant, though if a drive is given, it must be valid
+ * (hence the code above should remain there).
+ * 13 February 1991 clarkc
+ */
+ ++lpstr; /* ...since it's the first slash, 2 are allowed */
+ nNetwork = -1; /* Must receive server and share to be real */
+ bUNCPath = TRUE; /* No wildcards allowed if UNC name */
+ }
+ else if (*lpstr == TEXT('/'))
+ {
+ nFileOffset = PARSE_INVALIDDIRCHAR;
+ goto FAILURE;
+ }
+ }
+ else if (*lpstr == chPeriod)
+ {
+ if (*++lpstr == chPeriod) /* Is this up one directory? */
+ ++lpstr;
+ if (!*lpstr)
+ goto MustBeDir;
+ if ((*lpstr != TEXT('\\')) && (*lpstr != TEXT('/')))
+ {
+ nFileOffset = PARSE_INVALIDPERIOD;
+ goto FAILURE;
+ }
+ else
+ ++lpstr; /* it's saying directory, thus allowed */
+ }
+
+ if (!*lpstr)
+ {
+ goto MustBeDir;
+ }
+
+/* Should point to first char in 8.3 filename by now */
+ nFileOffset = nExtOffset = nFile = nExt = 0;
+ bWildcard = bExt = FALSE;
+ while (*lpstr)
+ {
+/*
+ * The next comparison MUST be unsigned to allow for extended characters!
+ * 21 Feb 1991 clarkc
+ */
+ if (*lpstr < chSpace)
+ {
+ nFileOffset = PARSE_INVALIDCHAR;
+ goto FAILURE;
+ }
+ switch (*lpstr)
+ {
+ case TEXT('"'): /* All invalid */
+ case TEXT('+'):
+ case TEXT(','):
+ case TEXT(':'):
+ case TEXT(';'):
+ case TEXT('<'):
+ case TEXT('='):
+ case TEXT('>'):
+ case TEXT('['):
+ case TEXT(']'):
+ case TEXT('|'):
+ {
+ nFileOffset = PARSE_INVALIDCHAR;
+ goto FAILURE;
+ }
+
+ case TEXT('\\'): /* Subdirectory indicators */
+ case TEXT('/'):
+ nNetwork++;
+ if (bWildcard)
+ {
+ nFileOffset = PARSE_WILDCARDINDIR;
+ goto FAILURE;
+ }
+
+ else if (nFile == 0) /* can't have 2 in a row */
+ {
+ nFileOffset = PARSE_INVALIDDIRCHAR;
+ goto FAILURE;
+ }
+ else
+ { /* reset flags */
+ ++lpstr;
+ if (!nNetwork && !*lpstr)
+ {
+ nFileOffset = PARSE_INVALIDNETPATH;
+ goto FAILURE;
+ }
+ nFile = nExt = 0;
+ bExt = FALSE;
+ }
+ break;
+
+ case chSpace:
+ {
+ LPTSTR lpSpace = lpstr;
+
+ *lpSpace = TEXT('\0');
+ while (*++lpSpace)
+ {
+ if (*lpSpace != chSpace)
+ {
+ *lpstr = chSpace; /* Reset string, abandon ship */
+ nFileOffset = PARSE_INVALIDSPACE;
+ goto FAILURE;
+ }
+ }
+ }
+ break;
+
+ case chPeriod:
+ if (nFile == 0)
+ {
+ if (*++lpstr == chPeriod)
+ ++lpstr;
+ if (!*lpstr)
+ goto MustBeDir;
+
+ if ((*lpstr != TEXT('\\')) && (*lpstr != TEXT('/')))
+ {
+ nFileOffset = PARSE_INVALIDPERIOD;
+ goto FAILURE;
+ }
+
+ ++lpstr; /* Flags are already set */
+ }
+ else if (bExt)
+ {
+ nFileOffset = PARSE_INVALIDPERIOD; /* can't have one in ext */
+ goto FAILURE;
+ }
+ else
+ {
+ nExtOffset = 0;
+ ++lpstr;
+ bExt = TRUE;
+ }
+ break;
+
+ case TEXT('*'):
+ case TEXT('?'):
+ if (bUNCPath)
+ {
+ nFileOffset = PARSE_INVALIDNETPATH;
+ goto FAILURE;
+ }
+ bWildcard = TRUE;
+/* Fall through to normal character processing */
+
+ default:
+ if (bExt)
+ {
+ if (++nExt == 1)
+ nExtOffset = lpstr - lpstrFileName;
+ else if (nExt > 3)
+ {
+ nFileOffset = PARSE_EXTENTIONTOOLONG;
+ goto FAILURE;
+ }
+ if ((nNetwork == -1) && (nFile + nExt > 11))
+ {
+ nFileOffset = PARSE_INVALIDNETPATH;
+ goto FAILURE;
+ }
+ }
+ else if (++nFile == 1)
+ nFileOffset = lpstr - lpstrFileName;
+ else if (nFile > 8)
+ {
+ /* If it's a server name, it can have 11 characters */
+ if (nNetwork != -1)
+ {
+ nFileOffset = PARSE_FILETOOLONG;
+ goto FAILURE;
+ }
+ else if (nFile > 11)
+ {
+ nFileOffset = PARSE_INVALIDNETPATH;
+ goto FAILURE;
+ }
+ }
+
+#ifdef WIN32
+ lpstr = CharNext(lpstr);
+#else
+ lpstr = AnsiNext(lpstr);
+#endif
+ break;
+ }
+ }
+
+/* Did we start with a double backslash but not have any more slashes? */
+ if (nNetwork == -1)
+ {
+ nFileOffset = PARSE_INVALIDNETPATH;
+ goto FAILURE;
+ }
+
+ if (!nFile)
+ {
+MustBeDir:
+ nFileOffset = PARSE_DIRECTORYNAME;
+ goto FAILURE;
+ }
+
+ if ((*(lpstr - 1) == chPeriod) && /* if true, no extention wanted */
+ (
+#ifdef WIN32
+ *CharNext(lpstr-2)
+#else
+ *AnsiNext(lpstr-2)
+#endif
+ == chPeriod
+ ))
+ *(lpstr - 1) = TEXT('\0'); /* Remove terminating period */
+ else if (!nExt)
+FAILURE:
+ nExtOffset = lpstr - lpstrFileName;
+
+ return(MAKELONG(nFileOffset, nExtOffset));
+}
+
+
+/*
+ * DoesFileExist
+ *
+ * Purpose:
+ * Determines if a file path exists
+ *
+ * Parameters:
+ * lpszFile LPTSTR - file name
+ * lpOpenBuf OFSTRUCT FAR* - points to the OFSTRUCT structure that
+ * will receive information about the file when the
+ * file is first opened. this field is filled by the
+ * Windows OpenFile API.
+ *
+ * Return Value:
+ * HFILE HFILE_ERROR - file does NOT exist
+ * file handle (as returned from OpenFile) - file exists
+ */
+HFILE WINAPI DoesFileExist(LPTSTR lpszFile, OFSTRUCT FAR* lpOpenBuf)
+{
+ long nRet;
+ int i;
+ static TCHAR *arrIllegalNames[] = {
+ TEXT("LPT1"),
+ TEXT("LPT2"),
+ TEXT("LPT3"),
+ TEXT("COM1"),
+ TEXT("COM2"),
+ TEXT("COM3"),
+ TEXT("COM4"),
+ TEXT("CON"),
+ TEXT("AUX"),
+ TEXT("PRN")
+ };
+
+ // Check if file name is syntactically correct.
+ // (OpenFile sometimes crashes if path is not syntactically correct)
+ nRet = ParseFile(lpszFile);
+ if (LOWORD(nRet) < 0)
+ goto error;
+
+ // Check is the name is an illegal name (eg. the name of a device)
+ for (i=0; i < (sizeof(arrIllegalNames)/sizeof(arrIllegalNames[0])); i++) {
+ if (lstrcmpi(lpszFile, arrIllegalNames[i])==0)
+ goto error; // illegal name FOUND
+ }
+
+ return OpenFile(lpszFile, lpOpenBuf, OF_EXIST);
+
+error:
+ _fmemset(lpOpenBuf, 0, sizeof(OFSTRUCT));
+ lpOpenBuf->nErrCode = 0x0002; // File not found
+ return HFILE_ERROR;
+}
+
diff --git a/private/oleutest/letest/ole2ui/utility.h b/private/oleutest/letest/ole2ui/utility.h
new file mode 100644
index 000000000..10b295cd5
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/utility.h
@@ -0,0 +1,37 @@
+/*
+ * UTILITY.H
+ *
+ * Miscellaneous prototypes and definitions for OLE UI dialogs.
+ *
+ * Copyright (c)1992 Microsoft Corporation, All Right Reserved
+ */
+
+
+#ifndef _UTILITY_H_
+#define _UTILITY_H_
+
+//Function prototypes
+//UTILITY.C
+HCURSOR WINAPI HourGlassOn(void);
+void WINAPI HourGlassOff(HCURSOR);
+
+BOOL WINAPI Browse(HWND, LPTSTR, LPTSTR, UINT, UINT, DWORD);
+int WINAPI ReplaceCharWithNull(LPTSTR, int);
+int WINAPI ErrorWithFile(HWND, HINSTANCE, UINT, LPTSTR, UINT);
+HFILE WINAPI DoesFileExist(LPTSTR lpszFile, OFSTRUCT FAR* lpOpenBuf);
+
+
+HICON FAR PASCAL HIconAndSourceFromClass(REFCLSID, LPTSTR, UINT FAR *);
+BOOL FAR PASCAL FIconFileFromClass(REFCLSID, LPTSTR, UINT, UINT FAR *);
+LPTSTR FAR PASCAL PointerToNthField(LPTSTR, int, TCHAR);
+BOOL FAR PASCAL GetAssociatedExecutable(LPTSTR, LPTSTR);
+HICON WINAPI HIconFromClass(LPTSTR);
+BOOL WINAPI FServerFromClass(LPTSTR, LPTSTR, UINT);
+UINT WINAPI UClassFromDescription(LPTSTR, LPTSTR, UINT);
+UINT WINAPI UDescriptionFromClass(LPTSTR, LPTSTR, UINT);
+BOOL WINAPI FVerbGet(LPTSTR, UINT, LPTSTR);
+LPTSTR WINAPI ChopText(HWND hwndStatic, int nWidth, LPTSTR lpch);
+void WINAPI OpenFileError(HWND hDlg, UINT nErrCode, LPTSTR lpszFile);
+
+
+#endif //_UTILITY_H_
diff --git a/private/oleutest/letest/ole2ui/verlocal.h b/private/oleutest/letest/ole2ui/verlocal.h
new file mode 100644
index 000000000..92b7000c8
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/verlocal.h
@@ -0,0 +1,54 @@
+/*
+ * VERLOCAL.H
+ *
+ * Version resource file for the OLE 2.0 UI Support DLL.
+ *
+ * Copyright (c)1993 Microsoft Corporation, All Rights Reserved.
+ *
+ * This file contains the text that needs to be translated in the version
+ * resource. All of the following variables must be localized:
+ *
+ * wLanguage
+ * szTranslation
+ * szzCompanyName
+ * szzProductName
+ * szzLegalCopyright
+ */
+
+/* wLanguage comes from the table of "langID" values on page 218 of
+ the Windows 3.1 SDK Programmer's Reference, Volume 4: Resources.
+ This page is in Chapter 13, "Resource-Definition Statements", in the
+ description of the "VERSIONINFO" statment.
+
+ For example,
+ 0x0407 German
+ 0x0409 U.S. English
+ 0x0809 U.K. English
+ 0x040C French
+ 0x040A Castilian Spanish
+*/
+#define wLanguage 0x0409 /* U.S. English */
+
+/* The first 4 characters of szTranslation must be the same as wLanguage,
+ without the "0x". The last 4 characters of szTranslation MUST be
+ 04E4. Note that any alphabetic characters in szTranslation must
+ be capitalized. */
+#define szTranslation "040904E4" /* U.S. English */
+
+
+/* The following szz strings must all end with the two characters "\0" */
+/* Note that the "\251" in szzLegalCopyright stands for the "circle c"
+ copyright symbol, and it should be left as \251 rather than
+ substituting the actual ANSI copyright character in the string. */
+#define szzCompanyName "Microsoft Corporation\0"
+#define szzFileDescription "Microsoft Windows(TM) OLE 2.0 User Interface Support\0"
+#define szzLegalCopyright "Copyright \251 1992-1993 Microsoft Corp. All rights reserved.\0"
+
+#ifdef PUBLISHER
+#define szzProductName "Microsoft Publisher for Windows 2.0\0"
+#else
+#define szzProductName szzFileDescription
+#endif
+
+
+/* DO NOT CHANGE ANY LINES BELOW THIS POINT */
diff --git a/private/oleutest/letest/ole2ui/vgares.bmp b/private/oleutest/letest/ole2ui/vgares.bmp
new file mode 100644
index 000000000..496902f9f
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/vgares.bmp
Binary files differ
diff --git a/private/oleutest/letest/ole2ui/wn_dos.h b/private/oleutest/letest/ole2ui/wn_dos.h
new file mode 100644
index 000000000..dbc75a643
--- /dev/null
+++ b/private/oleutest/letest/ole2ui/wn_dos.h
@@ -0,0 +1,174 @@
+/*************************************************************************
+**
+** OLE 2.0 Property Set Utilities
+**
+** wn_dos.h
+**
+** This file contains file contains data structure defintions,
+** function prototypes, constants, etc. for Windows 3.x form of
+** DOS calls. This is used by the SUMINFO OLE 2.0 Property Set
+** utilities used to manage the Summary Info property set.
+**
+** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+**
+*************************************************************************/
+
+#ifndef WN_DOS_H
+#define WN_DOS_H
+
+#include <dos.h>
+
+#define WIN 1
+
+#define cbMaxFile 146 //from inc\path.h
+#define SEEK_FROM_BEGINNING 0
+#define SEEK_FROM_END 2
+#define chDOSPath ('\\') // FUTURE: not used all places it could be
+#define chDOSWildAll '*' /* DOS File name wild card. */
+#define chDOSWildSingle '?'
+
+
+
+// Close, seek, delete, rename, flush, get attributes, read, write
+/* RPC TEMP
+int FCloseOsfnWin(WORD);
+#define FCloseOsfn(osfn) FCloseOsfnWin(osfn)
+long DwSeekDwWin(WORD,LONG,WORD);
+#define DwSeekDw(osfn, dwSeek, bSeekFrom) DwSeekDwWin(osfn, dwSeek, bSeekFrom)
+EC EcDeleteSzFfnameWin(char *);
+#define EcDeleteSzFfname(szFile) EcDeleteSzFfnameWin(szFile)
+EC EcRenameSzFfnameWin(char *,char *);
+#define EcRenameSzFfname(szFileCur,szFileNew) EcRenameSzFfnameWin(szFileCur,szFileNew)
+int FFlushOsfnWin(int);
+#define FFlushOsfn(osfn) FFlushOsfnWin(osfn)
+WORD DaGetFileModeSzWin(char *);
+#define DaGetFileModeSz(szFile) DaGetFileModeSzWin(szFile)
+int CbReadOsfnWin(int, void far *, UINT);
+int CbWriteOsfnWin(int, void far *, UINT);
+#define CbWriteOsfn(osfn,lpch,cbWrite) CbWriteOsfnWin(osfn,lpch,cbWrite)
+*/
+#define WinOpenFile(sz,ofs,n) OpenFile(sz,ofs,n)
+#define SeekHfile(f,off,kind) _llseek(f,off,kind)
+#define CbReadOsfn(osfn,lpch,cbRead) CbReadOsfnWin(osfn,lpch,cbRead)
+#define CbReadHfile(f,buf,n) _lread(f,buf,n)
+#define CbReadOsfnWin(f,buf,n) CbReadHfile(f,buf,n)
+#define EcFindFirst4dm(a,b,c) _dos_findfirst((const char *)(b),c,(struct find_t*)a)
+#define EcFindNext4dm(a) _dos_findnext((struct find_t*)a)
+#define FHfileToSffsDate(handle,date,time) _dos_getftime(handle, (unsigned *)(date), (unsigned *)(time))
+#define SeekHfile(f, off, kind) _llseek(f,off,kind)
+
+/* buffer structure to be used with EcFindFirst() and EcFindNext() */
+typedef struct _SFFS
+ { /* Search Find File Structure */
+ uchar buff[21]; // dos search info
+ uchar wAttr;
+ union
+ {
+ unsigned short timeVariable; /*RPC47*/
+ BF time:16;
+ struct
+ {
+ BF sec : 5;
+ BF mint: 6;
+ BF hr : 5;
+ };
+ };
+ union
+ {
+ unsigned short dateVariable;
+ BF date:16;
+ struct
+ {
+ BF dom : 5;
+ BF mon : 4;
+ BF yr : 7;
+ };
+ };
+ ulong cbFile;
+ uchar szFileName[13];
+ } SFFS;
+
+// find first file/find next file
+#define PszFromPsffs(psffs) ((psffs)->szFileName)
+#define CopySzFilePsffs(psffs,sz) OemToAnsi((char HUGE *)&((psffs)->szFileName[0]),(char HUGE *)(sz))
+#define CbSzFilePsffs(psffs) CbSz((psffs)->szFileName)
+#define CbFileSizePsffs(psffs) (psffs)->cbFile
+#define AttribPsffs(psffs) (psffs)->wAttr
+#define EcFindFirstCore(psffs, sz, wAttr) EcFindFirst(psffs, sz, wAttr) /*RPC22*/
+#define FDotPsffs(psffs) ((psffs)->szFileName[0]=='.') /*RPC23*/
+#define AppendSzWild(sz) {int i=_fstrlen((char FAR *)(sz)); sz[i]='*'; sz[i+1]='.'; sz[i+2]='*'; sz[i+3]='\0';}
+// disk free space
+
+unsigned long LcbDiskFreeSpaceWin(int);
+#define LcbDiskFreeSpace(chDrive) LcbDiskFreeSpaceWin(chDrive)
+
+// date and time /*RPC39*/
+/*
+typedef struct _TIM { // Time structure returned by OsTime
+ CHAR minutes, hour, hsec, sec;
+ } TIM;
+
+typedef struct _DAT { // Date structure returned by OsDate
+ int year;
+ CHAR month, day, dayOfWeek;
+ } DAT;
+*/
+#define TIM dostime_t /*RPC39*/
+#define DAT dosdate_t
+#define OsTimeWin(TIM) _dos_gettime(TIM)
+#define OsDateWin(DAT) _dos_getdate(DAT)
+
+
+/* DOS File Attributes */
+#define DA_NORMAL 0x00
+#define DA_READONLY 0x01
+#define DA_HIDDEN 0x02
+#define DA_SYSTEM 0x04
+#define DA_VOLUME 0x08
+#define DA_SUBDIR 0x10
+#define DA_ARCHIVE 0x20
+#define DA_NIL 0xFFFF /* Error DA */
+#define dosxSharing 32 /* Extended error code for sharing viol. */
+#define nErrNoAcc 5 /* OpenFile error code for Access Denied */
+#define nErrFnf 2 /* OpenFile error code for File Not Found */
+
+/* Components of the Open mode for OpenSzFfname (DOS FUNC 3DH) */
+#define MASK_fINH 0x80
+#define MASK_bSHARE 0x70
+#define MASK_bACCESS 0x07
+
+#define bSHARE_DENYRDWR 0x10
+#define bSHARE_DENYWR 0x20
+#define bSHARE_DENYNONE 0x40
+
+/* Seek-from type codes passed to DOS function 42H */
+
+#define SF_BEGINNING 0 /* Seek from beginning of file */
+#define SF_CURRENT 1 /* Seek from current file pointer */
+#define SF_END 2 /* Seek from end of file */
+
+
+typedef struct _DOSDTTM /* DOS DaTe TiMe */
+ {
+ union
+ {
+ long lDOSDttm;
+ struct
+ {
+ BF day: 5;
+ BF month: 4;
+ BF year: 7;
+ BF sec: 5;
+ BF mint: 6;
+ BF hours: 5;
+ } S1;
+ } U1;
+ } DOSDTTM;
+
+int FOsfnIsFile(int);
+
+void DateStamp(int, LONG *, int);
+int DosxError(void);
+int ShellExec(int, int);
+
+#endif //WN_DOS_H