summaryrefslogtreecommitdiffstats
path: root/private/oleutest/ole1/clidemo
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/oleutest/ole1/clidemo
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/oleutest/ole1/clidemo')
-rw-r--r--private/oleutest/ole1/clidemo/clidemo37
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.c1032
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.def35
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.h62
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.icobin0 -> 766 bytes
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.rc231
-rw-r--r--private/oleutest/ole1/clidemo/clidemo.rcv33
-rw-r--r--private/oleutest/ole1/clidemo/cliver.h9
-rw-r--r--private/oleutest/ole1/clidemo/daytona/makefile6
-rw-r--r--private/oleutest/ole1/clidemo/daytona/sources26
-rw-r--r--private/oleutest/ole1/clidemo/demorc.h180
-rw-r--r--private/oleutest/ole1/clidemo/dialog.c1150
-rw-r--r--private/oleutest/ole1/clidemo/dialog.h85
-rw-r--r--private/oleutest/ole1/clidemo/dirs4
-rw-r--r--private/oleutest/ole1/clidemo/global.h108
-rw-r--r--private/oleutest/ole1/clidemo/object.c1177
-rw-r--r--private/oleutest/ole1/clidemo/object.h40
-rw-r--r--private/oleutest/ole1/clidemo/register.c196
-rw-r--r--private/oleutest/ole1/clidemo/register.h17
-rw-r--r--private/oleutest/ole1/clidemo/stream.c348
-rw-r--r--private/oleutest/ole1/clidemo/stream.h35
-rw-r--r--private/oleutest/ole1/clidemo/utility.c612
-rw-r--r--private/oleutest/ole1/clidemo/utility.h34
23 files changed, 5457 insertions, 0 deletions
diff --git a/private/oleutest/ole1/clidemo/clidemo b/private/oleutest/ole1/clidemo/clidemo
new file mode 100644
index 000000000..3bb04e9ac
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo
@@ -0,0 +1,37 @@
+# Nmake macros for building Windows 32-Bit apps
+
+!include <ntwin32.mak>
+
+my_lib = advapi32.lib olecli32.lib shell32.lib
+
+all: clidemo.exe
+
+# Update the resource if necessary
+
+clidemo.res: clidemo.rc
+ $(rc) $(rcvars) -r clidemo.rc
+
+# Update the object file if necessary
+
+clidemo.obj: clidemo.c
+ $(cc) $(cflags) $(cvars) $(cdebug) clidemo.c
+
+dialog.obj: dialog.c
+ $(cc) $(cflags) $(cvars) $(cdebug) dialog.c
+
+object.obj: object.c
+ $(cc) $(cflags) $(cvars) $(cdebug) object.c
+
+register.obj: register.c
+ $(cc) $(cflags) $(cvars) $(cdebug) register.c
+
+stream.obj: stream.c
+ $(cc) $(cflags) $(cvars) $(cdebug) stream.c
+
+utility.obj: utility.c
+ $(cc) $(cflags) $(cvars) $(cdebug) utility.c
+
+# Update the executable file if necessary, and if so, add the resource back in.
+
+clidemo.exe: clidemo.obj dialog.obj object.obj register.obj stream.obj utility.obj clidemo.res clidemo.def
+ $(link) $(linkdebug) $(guiflags) -out:clidemo.exe clidemo.obj dialog.obj object.obj register.obj stream.obj utility.obj clidemo.res $(guilibs) $(my_lib)
diff --git a/private/oleutest/ole1/clidemo/clidemo.c b/private/oleutest/ole1/clidemo/clidemo.c
new file mode 100644
index 000000000..f1ff6f8ba
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.c
@@ -0,0 +1,1032 @@
+/*
+ * clidemo.c - OLE client application sample code
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ *
+ */
+
+ /***************************************************************************
+ * IMPORTANT - README:
+ * OLE client applications are windows programs which use the OLE client
+ * APIs. Therefore it is imperative that you understand how these APIs
+ * operate. Most importantly it is essential that you keep in mind which
+ * procedure calls result in asynchronous states: a state where the operation
+ * is not truely complete after a return from the call.
+ *
+ * Many functions produce asynchronous states, for example, OleActivate,
+ * OleClose, OleCopyFromLink, OleCreate ... Reference your SDK manual for
+ * a complete list.
+ *
+ * So whenever you call any of these library functions keep in mind that
+ * the operation is not necessarily complete once a return is made.
+ * These operations require communications with a server application. With
+ * OLE the inter-application communication is done through DDE. In order
+ * for a DDE conversation to complete several DDE messages need to be
+ * sent and recieved by both the server and client OLE DLLs. So, the
+ * asynchronous operations will not complete until the client application
+ * enters a message dipatch loop. Therefore, it is necessary to enter
+ * a dispatch loop and wait for completion. It is not necessary to block
+ * all other operation; however, it is very important to coordinate the
+ * user activity to prevent disastrous re-entry cases.
+ *
+ * In this application I have written a macro to prevent re-entry
+ * problems. Namely: ANY_OBJECT_BUSY which prevents a user from initiating
+ * an action which will result in an asynchronous call if there is an object
+ * already in an asynchronous state.
+ *
+ * The following is brief summary of the three macros:
+ *
+ * ANY_OBJECT_BUSY: checks to see if any object in the document is busy.
+ * This prevents a new document from being saved to file if there are
+ * objects in asynchronous states.
+ *
+ * So, the problem is that we have to enter a message dispatch loop in order
+ * to let DDE messages get through so that asynchronous operations can finish.
+ * And while we are in the message dispatch loops (WaitForObject or WaitForAllObjects)
+ * we have to prevent the user from doing things that can't be done when an
+ * object(s) is busy. Yes, it is confusing , but, the end result is a super
+ * cool application that can have linked and embbeded objects!
+ ***************************************************************************/
+
+//*** INCLUDES ***
+
+#include <windows.h> //* WINDOWS
+#include <ole.h> //* OLE structs and defines
+#include <shellapi.h> //* Shell, drag and drop headers
+
+#include "demorc.h" //* header for resource file
+#include "global.h" //* global app variables
+#include "clidemo.h" //* app includes:
+#include "register.h"
+#include "stream.h"
+#include "object.h"
+#include "dialog.h"
+#include "utility.h"
+
+//*** VARIABLES ***
+
+//** Global
+HANDLE hInst;
+BOOL fRetry = FALSE;
+HWND hwndFrame; //* main window
+HANDLE hAccTable; //* accelerator table
+CHAR szFrameClass[] = "CliDemo";//* main window class name
+CHAR szItemClass[] = "ItemClass";//* item window class name
+CHAR szAppName[CBMESSAGEMAX];//* Application name
+INT iObjects = 0; //* object count
+INT iObjectNumber = 0; //* object number for object name
+CHAR szFileName[CBPATHMAX];
+
+extern INT giXppli ;
+extern INT giYppli ;
+ //* ClipBoard formats:
+OLECLIPFORMAT vcfLink; //* "ObjectLink"
+OLECLIPFORMAT vcfNative; //* "Native"
+OLECLIPFORMAT vcfOwnerLink; //* "OwnerLink"
+
+
+/***************************************************************************
+ * WinMain() - Main Windows routine
+ ***************************************************************************/
+int APIENTRY WinMain(
+ HINSTANCE hInstance,
+ HINSTANCE hPrevInst,
+ LPSTR lpCmdLine,
+ INT nCmdLine
+){
+ hInst = hInstance;
+
+ if (!InitApplication(hInst)) //* register window classes
+ return FALSE;
+
+ if (!InitInstance(hInst)) //* create window instance
+ return FALSE;
+
+ OfnInit(hInst); //* setup to use <commdlg.dll>
+
+ //* register clipboard formats
+ //* used for OLE
+ vcfLink = RegisterClipboardFormat("ObjectLink");
+ vcfNative = RegisterClipboardFormat("Native");
+ vcfOwnerLink = RegisterClipboardFormat("OwnerLink");
+
+
+ ShowWindow(hwndFrame, SW_SHOWNORMAL);
+ UpdateWindow(hwndFrame);
+ ProcessCmdLine(lpCmdLine);
+
+ while (ProcessMessage(hwndFrame, hAccTable)) ;
+
+ return FALSE;
+}
+
+/***************************************************************************
+ * InitApplication()
+ *
+ * registers the window classes used by the application.
+ *
+ * Returns BOOL: - TRUE if successful.
+ ***************************************************************************/
+
+static BOOL InitApplication( //* ENTRY:
+ HANDLE hInst //* instance handle
+){ //* LOCAL:
+ WNDCLASS wc; //* temp wind-class structure
+
+ wc.style = 0;
+ wc.lpfnWndProc = (WNDPROC)FrameWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hInst;
+ wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(ID_APPLICATION));
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
+ wc.lpszMenuName = MAKEINTRESOURCE(ID_APPLICATION);
+ wc.lpszClassName = szFrameClass;
+
+ if (!RegisterClass(&wc))
+ return FALSE;
+ //* application item class
+ wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
+ wc.lpfnWndProc = (WNDPROC)ItemWndProc;
+ wc.hIcon = NULL;
+ wc.cbWndExtra = sizeof(APPITEMPTR);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szItemClass;
+
+ if (!RegisterClass(&wc))
+ return FALSE;
+
+ return TRUE;
+
+}
+
+/***************************************************************************
+ * InitInstance()
+ *
+ * create the main application window.
+ *
+ * Returns BOOL: - TRUE if successful else FALSE.
+ ***************************************************************************/
+
+static BOOL InitInstance( //* ENTRY:
+ HANDLE hInst //* instance handel
+){
+ HDC hDC ;
+
+ hAccTable = LoadAccelerators(hInst, MAKEINTRESOURCE(ID_APPLICATION));
+
+ if (!(hwndFrame =
+ CreateWindow(
+ szFrameClass, "",
+ WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL,
+ NULL,
+ hInst,
+ NULL
+ )))
+ return FALSE; //* ERROR return
+
+ LoadString(hInst, IDS_APPNAME, szAppName, CBMESSAGEMAX);
+ DragAcceptFiles(hwndFrame, TRUE); //* allow dragged and dropped files
+
+ hDC = GetDC (NULL); // Get the hDC of the desktop window
+ giXppli = GetDeviceCaps (hDC, LOGPIXELSX);
+ giYppli = GetDeviceCaps (hDC, LOGPIXELSY);
+ ReleaseDC (NULL, hDC);
+
+
+
+ return TRUE; //* SUCCESS return
+
+}
+
+/***************************************************************************
+ * ProcessCmdLine()
+ *
+ * process command line getting any command arguments.
+ ***************************************************************************/
+
+VOID ProcessCmdLine(LPSTR lpCmdLine)
+{ //* LOCAL:
+ OFSTRUCT ofs;
+
+
+ if (*lpCmdLine)
+ { //* look for file extension
+ LPSTR lpstrExt = lpCmdLine; //* pointer to file extension
+
+ while (*lpstrExt && *lpstrExt != '.')
+ lpstrExt = AnsiNext(lpstrExt);
+
+ lstrcpy(szFileName, lpCmdLine);
+ if (!(*lpstrExt)) //* append default extension
+ {
+ lstrcat(szFileName,".");
+ lstrcat(szFileName,szDefExtension);
+ }
+ //* get the files fully
+ OpenFile(szFileName, &ofs, OF_PARSE);//* qualified name
+ lstrcpy(szFileName, ofs.szPathName);
+ }
+ else
+ *szFileName = 0;
+ //* pass filename to main winproc
+ SendMessage(hwndFrame,WM_INIT,(WPARAM)0,(LPARAM)0);
+
+}
+
+
+/***************************************************************************
+ * FrameWndProc()
+ *
+ * Message handler for the application frame window.
+ *
+ * Returns long - Variable, depends on message.
+ ***************************************************************************/
+
+LONG APIENTRY FrameWndProc( //* ENTRY:
+ HWND hwnd, //* standard wind-proc parameters
+ UINT msg,
+ DWORD wParam,
+ LONG lParam
+){ //* LOCAL:
+ //* ^ Document file name
+ static LHCLIENTDOC lhcDoc; //* Document Handle
+ static LPOLECLIENT lpClient; //* pointer to client
+ static LPAPPSTREAM lpStream; //* pointer to stream vtbl
+ APPITEMPTR pItem; //* application item pointer
+
+ switch (msg)
+ {
+ case WM_INIT: //* user defined message
+ if (!InitAsOleClient(hInst, hwnd, szFileName, &lhcDoc, &lpClient, &lpStream))
+ DestroyWindow(hwnd);
+ break;
+ //* the following three messages are
+ //* used to avoid problems with OLE
+ //* see the comment in object.h
+ case WM_DELETE: //* user defined message
+ pItem = (APPITEMPTR) lParam; //* delete object
+ WaitForObject(pItem);
+ ObjDelete(pItem,OLE_OBJ_DELETE);
+ if (wParam)
+ cOleWait--;
+ break;
+
+ case WM_ERROR: //* user defined message
+ ErrorMessage(wParam); //* display error message
+ break;
+
+ case WM_RETRY: //* user defined message
+ RetryMessage((APPITEMPTR)lParam, RD_RETRY | RD_CANCEL);
+ break;
+
+ case WM_INITMENU:
+ UpdateMenu((HMENU)wParam);
+ break;
+
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+
+ pItem = GetTopItem();
+
+ switch (wID)
+ {
+ case IDM_NEW:
+ ANY_OBJECT_BUSY;
+ NewFile(szFileName,&lhcDoc,lpStream);
+ break;
+
+ case IDM_OPEN:
+ ANY_OBJECT_BUSY;
+ MyOpenFile(szFileName,&lhcDoc,lpClient,lpStream);
+ break;
+
+ case IDM_SAVE:
+ ANY_OBJECT_BUSY;
+ SaveFile(szFileName,lhcDoc,lpStream);
+ break;
+
+ case IDM_SAVEAS:
+ ANY_OBJECT_BUSY;
+ SaveasFile(szFileName,lhcDoc,lpStream);
+ break;
+
+ case IDM_ABOUT:
+ AboutBox();
+ break;
+
+ case IDM_INSERT:
+ ANY_OBJECT_BUSY;
+ ObjInsert(lhcDoc, lpClient);
+ break;
+
+ case IDM_INSERTFILE:
+ ANY_OBJECT_BUSY;
+ ObjCreateFromTemplate(lhcDoc,lpClient);
+ break;
+
+ case IDM_PASTE:
+ case IDM_PASTELINK:
+ ANY_OBJECT_BUSY;
+ ObjPaste(wID == IDM_PASTE,lhcDoc,lpClient);
+ break;
+
+ case IDM_LINKS:
+ ANY_OBJECT_BUSY;
+ pItem = GetTopItem();
+ LinkProperties();
+ break;
+
+ case IDM_EXIT:
+ ANY_OBJECT_BUSY;
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
+ break;
+
+ case IDM_COPY:
+ case IDM_CUT:
+ ANY_OBJECT_BUSY;
+
+ if (!ObjCopy(pItem))
+ {
+ ErrorMessage((wParam == IDM_CUT) ?
+ E_CLIPBOARD_CUT_FAILED : E_CLIPBOARD_COPY_FAILED);
+ break;
+ }
+
+ if (wParam == IDM_COPY)
+ break;
+
+ case IDM_CLEAR: //* CUT falls through to clear
+ ANY_OBJECT_BUSY;
+ ClearItem(pItem);
+ break;
+
+ case IDM_CLEARALL:
+ ANY_OBJECT_BUSY;
+ ClearAll(lhcDoc,OLE_OBJ_DELETE);
+ Dirty(DOC_DIRTY);
+ break;
+
+ default:
+ if( (wParam >= IDM_VERBMIN) && (wParam <= IDM_VERBMAX) )
+ {
+ ANY_OBJECT_BUSY;
+ ExecuteVerb(wParam - IDM_VERBMIN,pItem);
+ break;
+ }
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ break;
+ }
+
+ case WM_DROPFILES:
+ ANY_OBJECT_BUSY;
+ ObjCreateWrap((HANDLE)wParam, lhcDoc, lpClient);
+ break;
+
+ case WM_CLOSE:
+ ANY_OBJECT_BUSY;
+ if (!SaveAsNeeded(szFileName, lhcDoc, lpStream))
+ break;
+ DeregDoc(lhcDoc);
+ DestroyWindow(hwnd);
+ break;
+
+ case WM_DESTROY:
+ EndStream(lpStream);
+ EndClient(lpClient);
+ PostQuitMessage(0);
+ break;
+
+ case WM_QUERYENDSESSION: //* don't let windows terminate
+ return (QueryEndSession(szFileName,lhcDoc, lpStream));
+
+ default:
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+ }
+ return 0L;
+
+}
+
+/***************************************************************************
+ * InitAsOleClient()
+ *
+ * Initiates the creation of stream and client vtbls. These vtbls are very
+ * important for the proper operation of this application. The stream vtbl
+ * lets the OLE librarys know where the location of the stream I/O routines
+ * reside. The stream routines are used by OleLoadFromStream and the like.
+ * The client vtbl is used to hold the pointer to the CallBack function.
+ * IMPORTANT: both the client and the stream structures have pointers to
+ * vtbls which have the pointers to the functions. Therefore, it is
+ * necessary to allocate space for the vtbl and the client structure
+ * which has the pointer to the vtbl.
+ **************************************************************************/
+
+static BOOL InitAsOleClient( //* ENTRY:
+ HANDLE hInstance, //* applicaion instance handle
+ HWND hwnd, //* main window handle
+ PSTR pFileName, //* document file name
+ LHCLIENTDOC *lhcDoc, //* pointer to document Handle
+ LPOLECLIENT *lpClient, //* pointer to client pointer
+ LPAPPSTREAM *lpStream //* pointer to APPSTREAM pointer
+){
+ //* initiate client vtbl creation
+ if (!(*lpClient = InitClient(hInstance)))
+ {
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
+ return FALSE; //* ERROR return
+ }
+ //* initiate stream vtbl creation
+ if (!(*lpStream = InitStream(hInstance)))
+ {
+ SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
+ return FALSE; //* ERROR return
+ }
+
+ if (*pFileName && RegDoc(pFileName,lhcDoc)
+ && LoadFile(pFileName,*lhcDoc,*lpClient,*lpStream))
+ {
+ SetTitle(pFileName);
+ return TRUE; //* SUCCESS return
+ }
+
+ NewFile(pFileName, lhcDoc, *lpStream);
+ return TRUE; //* SUCCESS return
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * InitClient()
+ *
+ * Initialize the OLE client structure, create and fill the OLECLIENTVTBL
+ * structure.
+ *
+ * Returns LPOLECLIENT - if successful a pointer to a client structure
+ * , otherwise NULL.
+ ***************************************************************************/
+
+static LPOLECLIENT InitClient( //* ENTRY:
+ HANDLE hInstance //* application instance handle
+){ //* LOCAL:
+ LPOLECLIENT lpClient=NULL; //* pointer to client struct
+ //* Allocate vtbls
+ if (!(lpClient = (LPOLECLIENT)GlobalLock(
+ GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLECLIENT))
+ )))
+ goto Error; //* ERROR jump
+
+ if (!(lpClient->lpvtbl = (LPOLECLIENTVTBL)GlobalLock(
+ GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLECLIENTVTBL))
+ )))
+ goto Error; //* ERROR jump
+ //* set the CALLBACK function
+ //* pointer
+ lpClient->lpvtbl->CallBack = CallBack;
+
+ return lpClient; //* SUCCESS return
+
+Error: //* ERROR Tag
+
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ EndClient(lpClient); //* free any allocated space
+
+ return NULL; //* ERROR return
+
+}
+
+/****************************************************************************
+ * InitStream()
+ *
+ * Create and fill the STREAMVTBL. Create a stream structure and initialize
+ * pointer to stream vtbl.
+ *
+ * Returns LPAPPSTREAM - if successful a pointer to a stream structure
+ * , otherwise NULL .
+ ***************************************************************************/
+
+static LPAPPSTREAM InitStream( //* ENTRY:
+ HANDLE hInstance //* handle to application instance
+){ //* LOCAL:
+ LPAPPSTREAM lpStream = NULL; //* pointer to stream structure
+
+ if (!(lpStream = (LPAPPSTREAM)GlobalLock(
+ GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(APPSTREAM))
+ )))
+ goto Error; //* ERROR jump
+
+ if (!(lpStream->olestream.lpstbl = (LPOLESTREAMVTBL)GlobalLock(
+ GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLESTREAMVTBL))
+ )))
+ goto Error; //* ERROR jump
+
+ //* set stream func. pointers
+ lpStream->olestream.lpstbl->Get = (DWORD ( CALLBACK *)(LPOLESTREAM, VOID FAR *, DWORD)) ReadStream;
+ lpStream->olestream.lpstbl->Put = (DWORD ( CALLBACK *)(LPOLESTREAM, OLE_CONST VOID FAR *, DWORD)) WriteStream;
+
+ return lpStream; //* SUCCESS return
+
+Error: //* ERROR Tag
+
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ EndStream(lpStream);
+
+ return NULL; //* ERROR return
+
+}
+
+/***************************************************************************
+ * UpdateMenu()
+ *
+ * Enabling or disable menuitems based upon program state.
+ ***************************************************************************/
+
+static VOID UpdateMenu( //* ENTRY:
+ HMENU hMenu //* menu handle to updated
+){ //* LOCAL:
+ INT mf; //* generic menu flag
+ APPITEMPTR paItem; //* app item pointer
+ HMENU hSub;
+ //* there must be at least on object
+ //* for the following to be enabled
+
+ paItem = GetTopItem() ;
+
+ mf = (paItem ? MF_ENABLED : MF_GRAYED);
+ EnableMenuItem(hMenu, IDM_CUT, mf); //* i.e. Cut,Copy,Clear,Clearall...
+ EnableMenuItem(hMenu, IDM_COPY, mf);
+ EnableMenuItem(hMenu, IDM_CLEAR, mf);
+ EnableMenuItem(hMenu, IDM_CLEARALL, mf);
+ //* enable links option only if there
+ //* is at least one linked object
+ EnableMenuItem(hMenu, IDM_LINKS, MF_GRAYED);
+ for (; paItem; paItem = GetNextItem(paItem))
+ {
+ if (paItem->otObject == OT_LINK)
+ {
+ EnableMenuItem(hMenu, IDM_LINKS, MF_ENABLED);
+ break;
+ }
+ }
+
+ if (hSub = GetSubMenu(hMenu,POS_EDITMENU))
+ UpdateObjectMenuItem(hSub);
+
+ if (OleQueryCreateFromClip(STDFILEEDITING, olerender_draw, 0) == OLE_OK)
+ EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
+ else if (OleQueryCreateFromClip(STATICP, olerender_draw, 0) == OLE_OK)
+ EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
+ else
+ EnableMenuItem(hMenu, IDM_PASTE, MF_GRAYED);
+
+ if (OleQueryLinkFromClip(STDFILEEDITING, olerender_draw, 0) == OLE_OK)
+ EnableMenuItem(hMenu, IDM_PASTELINK, MF_ENABLED);
+ else
+ EnableMenuItem(hMenu, IDM_PASTELINK, MF_GRAYED);
+
+}
+
+/***************************************************************************
+ * NewFile()
+ *
+ * Save the present document and open a new blank one.
+ ***************************************************************************/
+
+static VOID NewFile( //* ENTRY:
+ PSTR pFileName, //* open file name
+ LHCLIENTDOC *lhcptrDoc, //* pointer to client doc. handle
+ LPAPPSTREAM lpStream //* pointer to stream structure
+){ //* LOCAL:
+ static CHAR szUntitled[CBMESSAGEMAX] = "";//* "(Untitled)" string
+ LHCLIENTDOC lhcDocNew; //* handle for new doc.
+
+ if (!(*szUntitled))
+ LoadString(hInst, IDS_UNTITLED, (LPSTR)szUntitled, CBMESSAGEMAX);
+
+ if (SaveAsNeeded(pFileName, *lhcptrDoc, lpStream))
+ { //* try to register new document
+ if (!RegDoc(szUntitled, &lhcDocNew))
+ return; //* before deregistring the old one
+ DeregDoc(*lhcptrDoc);
+ *lhcptrDoc = lhcDocNew;
+ Dirty(DOC_CLEAN); //* new document is clean
+ lstrcpy(pFileName,szUntitled);
+ SetTitle(pFileName);
+ iObjectNumber = 0;
+ }
+
+}
+
+/***************************************************************************
+ * MyOpenFile()
+ *
+ * Open a file and load it. Notice that the new file is loaded before
+ * the old is removed. This is done to assure a succesful file load
+ * before removing an existing document.
+ ***************************************************************************/
+
+static VOID MyOpenFile( //* ENTRY:
+ PSTR pFileName, //* open file name
+ LHCLIENTDOC *lhcptrDoc, //* pointer to document handle
+ LPOLECLIENT lpClient, //* pointer to client structure
+ LPAPPSTREAM lpStream //* pointer to stream structure
+){ //* LOCAL:
+ CHAR szNewFile[CBPATHMAX];//* new file name buffer
+ LHCLIENTDOC lhcDocNew; //* handle of new document
+ APPITEMPTR pItem; //* hold top item
+
+ if (SaveAsNeeded(pFileName, *lhcptrDoc, lpStream))
+ {
+ *szNewFile = 0;
+
+ if (!OfnGetName(hwndFrame, szNewFile, IDM_OPEN))
+ return; //* ERROR return
+
+ if (!RegDoc(szNewFile,&lhcDocNew))
+ return; //* ERROR return
+
+ pItem = GetTopItem();
+ ShowDoc(*lhcptrDoc,0); //* make old doc objects hidden.
+ //* try to load the new file before
+ if (!LoadFile(szNewFile, lhcDocNew, lpClient, lpStream))
+ { //* before removing the old.
+ DeregDoc(lhcDocNew); //* restore old document if new
+ SetTopItem(pItem); //* file did not load
+ ShowDoc(*lhcptrDoc,1);
+ return; //* ERROR return
+ }
+
+ DeregDoc(*lhcptrDoc); //* deregister old document
+ *lhcptrDoc = lhcDocNew;
+ lstrcpy(pFileName,szNewFile);
+ SetTitle(pFileName); //* set new title
+ Dirty(DOC_CLEAN);
+ }
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * SaveasFile()
+ *
+ * Prompt the user for a new file name. Write the document to the new
+ * filename.
+ ***************************************************************************/
+
+static VOID SaveasFile( //* ENTRY:
+ PSTR pFileName, //* old filename
+ LHCLIENTDOC lhcDoc, //* document handle
+ LPAPPSTREAM lpStream //* pointer to stream structure
+){
+ CHAR szNewFile[CBPATHMAX];//* new file name
+
+ *szNewFile = 0; //* prompt user for new file name
+ if (!OfnGetName(hwndFrame, szNewFile, IDM_SAVEAS))
+ return; //* ERROR return
+ //* rename document
+ if (!SaveFile(szNewFile, lhcDoc, lpStream))
+ return;
+
+ if (Error(OleRenameClientDoc(lhcDoc, szNewFile)))
+ {
+ ErrorMessage(W_FAILED_TO_NOTIFY);
+ return; //* ERROR return
+ }
+
+ lstrcpy(pFileName,szNewFile);
+ SetTitle(pFileName);
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * SaveFile()
+ *
+ * Save a compound document file. If the file is untitled, ask the user
+ * for a name and save the document to that file.
+ ***************************************************************************/
+
+static BOOL SaveFile( //* ENTRY:
+ PSTR pFileName, //* file to save document to
+ LHCLIENTDOC lhcDoc, //* OLE document handle
+ LPAPPSTREAM lpStream //* pointer to app. stream struct
+){ //* LOCAL:
+ CHAR szNewFile[CBPATHMAX];//* New file name strings
+ CHAR szOemFileName[2*CBPATHMAX];
+ static CHAR szUntitled[CBMESSAGEMAX] = "";
+ int fh; //* file handle
+
+ *szNewFile = 0;
+ if (!(*szUntitled))
+ LoadString(hInst, IDS_UNTITLED, (LPSTR)szUntitled, CBMESSAGEMAX);
+
+ if (!lstrcmp(szUntitled, pFileName))//* get filename for the untitled case
+ {
+ if (!OfnGetName(hwndFrame, szNewFile, IDM_SAVEAS))
+ return FALSE; //* CANCEL return
+ lstrcpy(pFileName,szNewFile);
+ SetTitle(pFileName);
+ }
+
+ AnsiToOem(pFileName, szOemFileName);
+ if ((fh = _lcreat((LPSTR)szOemFileName, 0)) <= 0)
+ {
+ ErrorMessage(E_INVALID_FILENAME);
+ return FALSE; //* ERROR return
+ }
+
+ lpStream->fh = fh;
+ //* save file on disk
+ if (!WriteToFile(lpStream))
+ {
+ _lclose(fh);
+ ErrorMessage(E_FAILED_TO_SAVE_FILE);
+ return FALSE; //* ERROR return
+ }
+ _lclose(fh);
+
+ if (Error(OleSavedClientDoc(lhcDoc)))
+ {
+ ErrorMessage(W_FAILED_TO_NOTIFY);
+ return FALSE; //* ERROR return
+ }
+
+ Dirty(DOC_CLEAN);
+ return TRUE; //* SUCCESS return
+
+}
+
+/***************************************************************************
+ * LoadFile()
+ *
+ * Load a document file from disk.
+ ***************************************************************************/
+
+static BOOL LoadFile( //* ENTRY:
+ PSTR pFileName, //* file name
+ LHCLIENTDOC lhcDoc, //* document handle
+ LPOLECLIENT lpClient, //* pointer to client structure
+ LPAPPSTREAM lpStream //* pointer to stream structure
+){ //* LOCAL:
+ //* OEM file name
+ CHAR szOemFileName[2*CBPATHMAX];
+ int fh; //* file handle
+ INT iObjectNumberHold; //* hold object number
+
+ AnsiToOem(pFileName, szOemFileName);
+ if ((fh = _lopen(szOemFileName, OF_READ | OF_SHARE_DENY_WRITE)) == -1)
+ {
+ ErrorMessage(E_FAILED_TO_READ_FILE);
+ return FALSE; //* ERROR return
+ }
+
+ lpStream->fh = fh;
+
+ iObjectNumberHold = iObjectNumber; //* save object number so it can
+ iObjectNumber = 0; //* be restored if read from file
+ //* fails
+ if (!ReadFromFile(lpStream, lhcDoc, lpClient))
+ {
+ _lclose(fh);
+ ErrorMessage(E_FAILED_TO_READ_FILE);
+ iObjectNumber = iObjectNumberHold;
+ return FALSE; //* ERROR return
+ }
+ _lclose(fh);
+ return TRUE; //* SUCCESS return
+
+}
+
+/***************************************************************************
+ * RegDoc()
+ *
+ * Register the client document with the OLE library.
+ **************************************************************************/
+
+static BOOL RegDoc( //* ENTRY:
+ PSTR pFileName, //* file name
+ LHCLIENTDOC *lhcptrDoc //* pointer to client document handle
+){
+
+ if (Error(OleRegisterClientDoc(szAppName, (LPSTR)pFileName, 0L, lhcptrDoc)))
+ {
+ ErrorMessage(W_FAILED_TO_NOTIFY);
+ return FALSE; //* ERROR return
+ }
+ return TRUE; //* SUCCESS return
+
+}
+
+/****************************************************************************
+ * DeregDoc()
+ *
+ * This function initiates the removal of all OLE objects from the
+ * current document and deregisters the document with the OLE library.
+ ***************************************************************************/
+
+static VOID DeregDoc( //* ENTRY:
+ LHCLIENTDOC lhcDoc //* client document handle
+){
+
+ if (lhcDoc)
+ { //* release all OLE objects
+ ClearAll(lhcDoc,OLE_OBJ_RELEASE); //* and remove them from the screen
+ WaitForAllObjects();
+ if (Error(OleRevokeClientDoc(lhcDoc)))
+ ErrorMessage(W_FAILED_TO_NOTIFY);
+ }
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * ClearAll()
+ *
+ * This function will destroy all of the item windows in the current
+ * document and delete all OLE objects. The loop is basically an enum
+ * of all child windows.
+ **************************************************************************/
+
+static VOID ClearAll( //* ENTRY:
+ LHCLIENTDOC lhcDoc, //* application document handle
+ BOOL fDelete //* Delete / Release
+){ //* LOCAL:
+ APPITEMPTR pItemNext; //* working handles
+ APPITEMPTR pItem; //* pointer to application item
+
+ pItem = GetTopItem();
+
+ while (pItem)
+ {
+ pItemNext = GetNextItem(pItem);
+ if (pItem->lhcDoc == lhcDoc)
+ ObjDelete(pItem, fDelete);
+ pItem = pItemNext;
+ }
+
+}
+ //* SUCCESS return
+/***************************************************************************
+ * ClearItem()
+ *
+ * This function will destroy an item window, and make the
+ * next window active.
+ **************************************************************************/
+
+VOID FAR ClearItem( //* ENTRY:
+ APPITEMPTR pItem //* application item pointer
+){
+
+ pItem->fVisible = FALSE;
+ SetTopItem(GetNextActiveItem());
+ ObjDelete(pItem, OLE_OBJ_DELETE);
+ Dirty(DOC_DIRTY);
+
+}
+
+/****************************************************************************
+ * SaveAsNeeded()
+ *
+ * This function will have the file saved if and only
+ * if the document has been modified. If the fDirty flag has
+ * been set to TRUE, then the document needs to be saved.
+ *
+ * Returns: BOOL - TRUE if document doesn't need saving or if the
+ * document has been saved successfully.
+ ***************************************************************************/
+
+static BOOL SaveAsNeeded( //* ENTRY:
+ PSTR pFileName, //* file to save
+ LHCLIENTDOC lhcDoc, //* OLE doc handle
+ LPAPPSTREAM lpStream //* pointer to OLE stream vtbl ...
+){ //* LOCAL:
+ CHAR sz[CBMESSAGEMAX]; //* work strings
+ CHAR sz2[CBMESSAGEMAX + CBPATHMAX];
+
+ if (Dirty(DOC_QUERY)) //* if doc is clean don't bother
+ {
+
+ LoadString(hInst, IDS_MAYBESAVE, sz, CBMESSAGEMAX);
+ wsprintf(sz2, sz, (LPSTR)pFileName );
+
+ switch (MessageBox(hwndFrame, sz2, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION))
+ {
+
+ case IDCANCEL:
+ return FALSE; //* CANCEL return
+
+ case IDYES:
+ return (SaveFile(pFileName,lhcDoc,lpStream));
+
+ default:
+ break;
+ }
+ }
+ return TRUE; //* SUCCESS return
+
+}
+
+/****************************************************************************
+ * SetTitle()
+ *
+ * Set the window caption to the current file name. If szFileName is
+ * NULL, the caption will be set to "(Untitled)".
+ ***************************************************************************/
+
+static VOID SetTitle( //* ENTRY:
+ PSTR pFileName //* file name
+){ //* LOCAL
+ //* window title string
+ CHAR szTitle[CBMESSAGEMAX + CBPATHMAX];
+
+ wsprintf(szTitle, "%s - %s", (LPSTR)szAppName, (LPSTR)pFileName);
+ SetWindowText(hwndFrame, szTitle);
+
+}
+
+/***************************************************************************
+ * EndClient()
+ *
+ * Perform cleanup prior to app termination. The OLECLIENT
+ * memory blocks and procedure instance thunks freed.
+ **************************************************************************/
+
+static VOID EndStream( //* ENTRY:
+ LPAPPSTREAM lpStream //* pointer to stream structure
+){ //* LOCAL:
+ HANDLE hGeneric; //* temp handle
+
+ if (lpStream) //* is there a STREAM struct?
+ {
+ if (lpStream->olestream.lpstbl)
+ {
+ FreeProcInstance((FARPROC)lpStream->olestream.lpstbl->Get);
+ FreeProcInstance((FARPROC)lpStream->olestream.lpstbl->Put);
+ hGeneric = GlobalHandle((LPSTR)lpStream->olestream.lpstbl);
+ GlobalUnlock(hGeneric);
+ GlobalFree(hGeneric);
+ }
+ hGeneric = GlobalHandle((LPSTR)lpStream);
+ GlobalUnlock(hGeneric);
+ GlobalFree(hGeneric);
+ }
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * EndClient()
+ *
+ * Perform cleanup prior to app termination. The OLECLIENT
+ * memory blocks and procedure instance thunks are freed.
+ **************************************************************************/
+
+static VOID EndClient( //* ENTRY:
+ LPOLECLIENT lpClient //* pointer to client structure
+){ //* LOCAL:
+ HANDLE hGeneric; //* temp handle
+
+ if (lpClient) //* is there a client structure
+ {
+ if (lpClient->lpvtbl)
+ {
+ FreeProcInstance(lpClient->lpvtbl->CallBack);
+ hGeneric = GlobalHandle((LPSTR)lpClient->lpvtbl);
+ GlobalUnlock(hGeneric);
+ GlobalFree(hGeneric);
+ }
+ hGeneric = GlobalHandle((LPSTR)lpClient);
+ GlobalUnlock(hGeneric);
+ GlobalFree(hGeneric);
+ }
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * QueryEndSession()
+ ***************************************************************************/
+
+static LONG QueryEndSession( //* ENTRY:
+ PSTR pFileName, //* document name
+ LHCLIENTDOC lhcDoc, //* client document handle
+ LPAPPSTREAM lpStream //* application stream pointer
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ if (OleQueryOpen(pItem->lpObject) == OLE_OK)
+ {
+ MessageBox(hwndFrame,"Exit CliDemo1 before closing Windows",
+ szAppName, MB_OK | MB_ICONSTOP);
+ return 0L;
+ }
+
+ if (!SaveAsNeeded(pFileName, lhcDoc, lpStream))
+ return 0L;
+ DeregDoc(lhcDoc);
+ return 1L;
+
+}
+
diff --git a/private/oleutest/ole1/clidemo/clidemo.def b/private/oleutest/ole1/clidemo/clidemo.def
new file mode 100644
index 000000000..faecf4704
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.def
@@ -0,0 +1,35 @@
+NAME clidemo
+
+DESCRIPTION 'Microsoft OLE Sample Client Application'
+
+EXETYPE WINDOWS
+
+CODE PRELOAD MOVEABLE DISCARDABLE
+DATA PRELOAD MOVEABLE MULTIPLE
+
+HEAPSIZE 16000
+STACKSIZE 32000
+
+EXPORTS
+; Window procedures
+;
+ FrameWndProc @1
+ ItemWndProc @2
+
+; Dialog procedures
+;
+ fnProperties @3
+ fnInsertNew @4
+ fnAbout @5
+ fnRetry @6
+ fnInvalidLink @7
+
+; OLE Client callbacks
+;
+ CallBack @8
+ ReadStream @9
+ WriteStream @10
+
+; timer callback
+;
+ fnTimerBlockProc @11
diff --git a/private/oleutest/ole1/clidemo/clidemo.h b/private/oleutest/ole1/clidemo/clidemo.h
new file mode 100644
index 000000000..a7535359e
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.h
@@ -0,0 +1,62 @@
+/*
+ * clidemo.h
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** CONSTANTS ***
+
+#define CXDEFAULT 400 //* Default object size: 400 x 300
+#define CYDEFAULT 300
+#define COBJECTSMAX 50 //* max number of objects in our app
+
+//*** PROTOTYPES ***
+
+//*** Exported window procedures
+
+LONG APIENTRY FrameWndProc(HWND, UINT, DWORD, LONG);
+
+//*** FAR
+
+VOID FAR FixObjectBounds(LPRECT lprc);
+
+//*** Local
+
+static LPOLECLIENT InitClient(HANDLE);
+static VOID EndClient(LPOLECLIENT);
+static LPAPPSTREAM InitStream(HANDLE);
+static VOID EndStream(LPAPPSTREAM);
+static VOID ProcessCmdLine(LPSTR);
+static BOOL InitApplication(HANDLE);
+static BOOL InitInstance(HANDLE);
+static VOID SetTitle(PSTR);
+static VOID MyOpenFile(PSTR,LHCLIENTDOC *, LPOLECLIENT, LPAPPSTREAM);
+static VOID NewFile(PSTR,LHCLIENTDOC *, LPAPPSTREAM);
+static BOOL SaveFile(PSTR, LHCLIENTDOC, LPAPPSTREAM);
+static VOID SaveasFile(PSTR, LHCLIENTDOC, LPAPPSTREAM);
+static BOOL LoadFile(PSTR, LHCLIENTDOC, LPOLECLIENT, LPAPPSTREAM);
+static VOID ClearAll(LHCLIENTDOC, BOOL);
+static VOID EndInstance(VOID);
+static BOOL SaveAsNeeded(PSTR,LHCLIENTDOC,LPAPPSTREAM);
+static VOID UpdateMenu(HMENU);
+static BOOL RegDoc(PSTR, LHCLIENTDOC *);
+static VOID DeregDoc(LHCLIENTDOC);
+static BOOL InitAsOleClient(HANDLE, HWND, PSTR, LHCLIENTDOC *, LPOLECLIENT *, LPAPPSTREAM *);
+VOID FAR ClearItem(APPITEMPTR);
+static LONG QueryEndSession(PSTR, LHCLIENTDOC, LPAPPSTREAM);
+
+//*** MACROS ***
+
+/*
+ * ANY_OBJECT_BUSY
+ * checks to see if any object in the document is busy. This prevents
+ * a new document from being saved to file if there are objects in
+ * asynchronous states.
+ */
+
+#define ANY_OBJECT_BUSY {\
+ if (ObjectsBusy()) \
+ break; \
+}
+
diff --git a/private/oleutest/ole1/clidemo/clidemo.ico b/private/oleutest/ole1/clidemo/clidemo.ico
new file mode 100644
index 000000000..114e1c58c
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.ico
Binary files differ
diff --git a/private/oleutest/ole1/clidemo/clidemo.rc b/private/oleutest/ole1/clidemo/clidemo.rc
new file mode 100644
index 000000000..88aa4b04a
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.rc
@@ -0,0 +1,231 @@
+/*
+ * clidemo.rc - OLE Client Demonstration application resource file
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+#include <windows.h>
+#include "demorc.h"
+#include "clidemo.rcv"
+
+ID_APPLICATION ICON CLIDEMO.ICO
+
+ID_APPLICATION MENU
+BEGIN
+ POPUP "&File"
+ BEGIN
+ MENUITEM "&New", IDM_NEW
+ MENUITEM "&Open...", IDM_OPEN
+ MENUITEM "&Save", IDM_SAVE
+ MENUITEM "Save &As...", IDM_SAVEAS
+ MENUITEM SEPARATOR
+
+ MENUITEM "E&xit", IDM_EXIT
+ MENUITEM "A&bout...", IDM_ABOUT
+ END
+
+ POPUP "&Edit"
+ BEGIN
+ MENUITEM "Cu&t\tShift+Del", IDM_CUT
+ MENUITEM "&Copy\tCtrl+Ins", IDM_COPY
+ MENUITEM "&Paste\tShift+Ins", IDM_PASTE
+ MENUITEM "Paste &Link", IDM_PASTELINK
+ MENUITEM SEPARATOR
+ MENUITEM "Clea&r\tDel", IDM_CLEAR
+ MENUITEM "Clear &All", IDM_CLEARALL
+ MENUITEM SEPARATOR
+ MENUITEM "Lin&ks...", IDM_LINKS
+ MENUITEM "&Objects", IDM_VERBMIN
+ END
+
+ POPUP "&Insert"
+ BEGIN
+ MENUITEM "&Object...", IDM_INSERT
+ MENUITEM "&Template...", IDM_INSERTFILE
+ END
+END
+
+ID_APPLICATION ACCELERATORS
+BEGIN
+ VK_DELETE, IDM_CLEAR, VIRTKEY
+ VK_DELETE, IDM_CUT, VIRTKEY, SHIFT
+ VK_INSERT, IDM_COPY, VIRTKEY, CONTROL
+ VK_INSERT, IDM_PASTE, VIRTKEY, SHIFT
+END
+
+/*
+ * Dialog for Link Properties...
+ */
+
+DTPROP DIALOG 45, 38, 292, 103
+STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Links"
+BEGIN
+ LISTBOX IDD_LINKNAME, 2, 14, 240, 43, LBS_EXTENDEDSEL |
+ LBS_MULTIPLESEL | WS_VSCROLL
+ LTEXT "Update:", -1, 3, 58, 44, 8
+ RADIOBUTTON "&Automatic", IDD_AUTO, 31, 56, 46, 12, WS_TABSTOP
+ RADIOBUTTON "&Manual", IDD_MANUAL, 78, 56, 42, 12, WS_TABSTOP
+ PUSHBUTTON "&Update Now", IDD_UPDATE, 40, 75, 48, 14
+ PUSHBUTTON "&Cancel Link", IDD_FREEZE, 98, 75, 45, 14
+ PUSHBUTTON "C&hange Link...", IDD_CHANGE, 153, 75, 52, 14
+ PUSHBUTTON "OK", IDOK, 254, 12, 32, 14
+ DEFPUSHBUTTON "Cancel", IDCANCEL, 254, 30, 32, 14
+ LTEXT "&Links:", 5, 2, 4, 27, 8
+END
+
+INVALIDLINK DIALOG 9, 25, 155, 55
+STYLE MB_ICONEXCLAMATION | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "CliDemo"
+BEGIN
+ LTEXT "Some linked files were unavailable", -1, 30, 5, 140, 8, NOT WS_GROUP
+ LTEXT "and could not be updated.", -1, 30, 14, 112, 8, NOT WS_GROUP
+ PUSHBUTTON "OK", IDOK, 30, 33, 36, 14
+ PUSHBUTTON "&Links...", IDD_CHANGE, 85, 33, 40, 14
+ CONTROL 32515, -1, "static", SS_ICON | WS_CHILD, 7, 7, 18, 26
+END
+
+DTCREATE DIALOG 50, 26, 183, 62
+STYLE DS_MODALFRAME| WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Insert New Object"
+BEGIN
+ LTEXT "Object Type:", -1, 7, 5, 123, 8, NOT WS_GROUP
+ LISTBOX IDD_LISTBOX, 5, 15, 125, 41, LBS_SORT | WS_TABSTOP | WS_VSCROLL
+ PUSHBUTTON "OK", IDOK, 140, 8, 35, 14, WS_TABSTOP
+ PUSHBUTTON "Cancel", IDCANCEL, 140, 25, 35, 14, WS_TABSTOP
+END
+
+
+STRINGTABLE LOADONCALL {
+ IDS_APPNAME, "CliDemo"
+ IDS_UNTITLED, "(Untitled)"
+ IDS_MAYBESAVE, "Save Changes to %s?"
+ IDS_OPENFILE, "File Open"
+ IDS_SAVEFILE, "File Save As"
+ IDS_INSERTFILE, "Insert Object from File"
+ IDS_FILTER, "OLE Object(s)"
+ IDS_EXTENSION, "OLE"
+ IDS_CHANGELINK, "Change Link"
+ IDS_ALLFILTER, "All Files (*.*)"
+ IDS_EMBEDDED, "Embedded %s"
+ IDS_UPDATELINKS, "This file contains links to other\ndocuments.\n\nUpdate links now?"
+ IDS_RENAME, "The selected links to %s have been \nupdated. %s contains additional links \nto %s\n\n Update additional links?"
+ IDS_INVALID_LINK, "Link is invalid!\n Modify Links?"
+ IDS_SAVE_CHANGES, "Save changes made to links?"
+ IDS_UPDATE_OBJ, "This object has been changed.\nUpdate %s before proceeding?"
+ IDS_RETRY_TEXT1, """%.20s"" is busy. You may 'Switch to'"
+ IDS_RETRY_TEXT2, """%.20s"" and correct the problem."
+
+ E_FAILED_TO_OPEN_FILE, "Failed to open file."
+ E_FAILED_TO_READ_FILE, "Failed to read file."
+ E_FAILED_TO_SAVE_FILE, "Failed to save file."
+ E_INVALID_FILENAME, "Invalid filename."
+ E_FAILED_TO_DELETE_OBJECT, "Failed to delete object."
+ E_FAILED_TO_RELEASE_OBJECT, "Failed to release object."
+ E_CLIPBOARD_CUT_FAILED, "Cut to clipboard failed."
+ E_CLIPBOARD_COPY_FAILED, "Copy to clipboard failed."
+ E_GET_FROM_CLIPBOARD_FAILED, "Failed to paste object from clipboard."
+ E_CREATE_FROM_TEMPLATE, "Failed to create object from file."
+ E_FAILED_TO_WRITE_OBJECT, "Failed to write object."
+ E_FAILED_TO_READ_OBJECT, "Failed to read object."
+ E_FAILED_TO_CREATE_CHILD_WINDOW,"Failed to create child window."
+ E_FAILED_TO_CREATE_OBJECT, "Failed to create new object."
+ E_OBJECT_BUSY, "Object is currently busy."
+ E_UNEXPECTED_RELEASE, "DDE conversation is invalid."
+ E_FAILED_TO_LAUNCH_SERVER, "Failed to launch server application."
+ E_FAILED_TO_UPDATE, "Failed to update object."
+ E_FAILED_TO_FREEZE, "Failed to freeze object."
+ E_FAILED_TO_UPDATE_LINK, "Failed to update link options."
+ E_SERVER_BUSY, "Unable to process command, server busy."
+ E_FAILED_TO_RECONNECT_OBJECT, "Failed to reconnect link to server."
+ E_FAILED_TO_CONNECT, "Failed to connect;\nLink may be broken."
+ E_FAILED_TO_ALLOC, "Memory Allocation Failed."
+ E_FAILED_TO_LOCK, "Fail to lock OLE data."
+ E_FAILED_TO_DO_VERB, "Could not Edit / Play object."
+
+ W_IMPROPER_LINK_OPTIONS, "Warning: Improper link options."
+ W_STATIC_OBJECT, "Warning: Static object"
+ W_FAILED_TO_CLONE_UNDO, "Warning: Couldn't clone object."
+ W_FAILED_TO_NOTIFY, "Warning: Failed to notify library."
+
+ SZAUTO, "Automatic"
+ SZMANUAL, "Manual"
+ SZFROZEN, "Canceled"
+
+ E_OLE_ERROR_MEMORY, "OLE - Could not alloc or lock memory"
+ E_OLE_ERROR_STREAM, "OLE - (OLESTREAM) stream error"
+ E_OLE_ERROR_STATIC, "OLE - Non static object expected"
+ E_OLE_ERROR_BLANK, "OLE - Critical data missing"
+ E_OLE_ERROR_DRAW, "OLE - Error while drawing"
+ E_OLE_ERROR_METAFILE, "OLE - Invalid metafile"
+ E_OLE_ERROR_ABORT, "OLE - Client chose to abort metafile drawing"
+ E_OLE_ERROR_CLIPBOARD, "OLE - Failed to get/set clipboard data"
+ E_OLE_ERROR_FORMAT, "OLE - Requested format is not available"
+ E_OLE_ERROR_OBJECT, "OLE - Not a valid object"
+ E_OLE_ERROR_OPTION, "OLE - Invalid option (link update / render)"
+ E_OLE_ERROR_PROTOCOL, "OLE - Invalid protocol"
+ E_OLE_ERROR_ADDRESS, "OLE - One of the pointers is invalid"
+ E_OLE_ERROR_NOT_EQUAL, "OLE - Objects are not equal"
+ E_OLE_ERROR_HANDLE, "OLE - Invalid handle encountered"
+ E_OLE_ERROR_GENERIC, "OLE - Some general error"
+ E_OLE_ERROR_CLASS, "OLE - Invalid class"
+ E_OLE_ERROR_SYNTAX, "OLE - Command syntax is invalid"
+ E_OLE_ERROR_DATATYPE, "OLE - Data format is not supported"
+ E_OLE_ERROR_PALETTE, "OLE - Invalid color palette"
+ E_OLE_ERROR_NOT_LINK, "OLE - Not a linked object"
+ E_OLE_ERROR_NOT_EMPTY, "OLE - Client doc contains objects"
+ E_OLE_ERROR_SIZE, "OLE - Incorrect buffer size passed to E_OLE api"
+ E_OLE_ERROR_DRIVE, "OLE - Drive letter in doc name is invalid"
+ E_OLE_ERROR_NETWORK, "OLE - Failed to establish connection to network"
+ E_OLE_ERROR_NAME, "OLE - Invalid name (doc name, object name)"
+ E_OLE_ERROR_TEMPLATE, "OLE - Server failed to load template"
+ E_OLE_ERROR_NEW, "OLE - Server failed to create new doc"
+ E_OLE_ERROR_EDIT, "OLE - Server failed to edit object"
+ E_OLE_ERROR_OPEN, "OLE - Server failed to open document"
+ E_OLE_ERROR_NOT_OPEN, "OLE - Object is not open for editing"
+ E_OLE_ERROR_LAUNCH, "OLE - Failed to launch server"
+ E_OLE_ERROR_COMM, "OLE - Failed to communicate with server"
+ E_OLE_ERROR_TERMINATE, "OLE - Error in termination"
+ E_OLE_ERROR_COMMAND, "OLE - Error in execute"
+ E_OLE_ERROR_SHOW, "OLE - Error in show"
+ E_OLE_ERROR_DOVERB, "OLE - Error in doing verb"
+ E_OLE_ERROR_ADVISE_NATIVE, "OLE - Item could be missing"
+ E_OLE_ERROR_ADVISE_PICT, "OLE - Server can't recognize item format"
+ E_OLE_ERROR_ADVISE_RENAME, "OLE - Server doesn't support rename"
+ E_OLE_ERROR_POKE_NATIVE, "OLE - Failure of poking native data to server"
+ E_OLE_ERROR_REQUEST_NATIVE, "OLE - Server failed to render native data"
+ E_OLE_ERROR_REQUEST_PICT, "OLE - Server failed to render presentation data"
+ E_OLE_ERROR_SERVER_BLOCKED, "OLE - Server is blocked"
+ E_OLE_ERROR_REGISTRATION, "OLE - Server is not registered"
+ E_OLE_ERROR_ALREADY_REGISTERED, "OLE - Trying to register same doc multiple times"
+ E_OLE_ERROR_TASK, "OLE - Server or client task is invalid"
+ E_OLE_ERROR_OUTOFDATE, "OLE - Object is out of date"
+ E_OLE_ERROR_CANT_UPDATE_CLIENT, "OLE - embed doc's client doesn't accept"
+ E_OLE_ERROR_UPDATE, "OLE - error while trying to update object"
+
+}
+
+AboutBox DIALOG LOADONCALL MOVEABLE DISCARDABLE 22, 17, 160, 75
+CAPTION "About Clidemo1"
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+BEGIN
+ CTEXT "Microsoft Windows" -1, 0, 5, 160, 8
+ CTEXT "OLE 1.0 Client Test Application" -1, 0, 14, 160, 8
+ CTEXT "Version 1.00" -1, 0, 23, 160, 8
+ CTEXT "(c) Copyright Microsoft Corp. 1990 - 1992" -1, 0, 39, 160, 8
+ DEFPUSHBUTTON "OK" IDOK, 61, 59, 32, 14, WS_GROUP
+END
+
+RetryBox DIALOG 26, 26, 220, 78
+CAPTION "CLIDEMO"
+FONT 8, "Helv"
+STYLE WS_SYSMENU | WS_CAPTION | WS_VISIBLE | DS_MODALFRAME | WS_POPUP
+BEGIN
+ PUSHBUTTON "&Switch To...", IDD_SWITCH, 35, 55, 50, 14
+ DEFPUSHBUTTON "&Cancel", IDCANCEL, 120, 55, 50, 14
+ LTEXT "This action cannot be completed because", -1, 35, 9, 160, 8
+ LTEXT "", IDD_RETRY_TEXT1, 35, 18, 180, 8
+ LTEXT "", IDD_RETRY_TEXT2, 35, 27, 180, 8
+ CONTROL 32515, -1, "static", SS_ICON | WS_CHILD, 7, 15, 18, 26
+END
diff --git a/private/oleutest/ole1/clidemo/clidemo.rcv b/private/oleutest/ole1/clidemo/clidemo.rcv
new file mode 100644
index 000000000..5dbf54f35
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/clidemo.rcv
@@ -0,0 +1,33 @@
+#include "cliver.h"
+
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION CLIVER_FILEVERSION
+PRODUCTVERSION CLIVER_PRODUCTVERSION
+FILEFLAGSMASK 0x0000003FL
+FILEFLAGS CLIVER_FILEFLAGS
+FILEOS CLIVER_FILEOS
+FILETYPE VFT_APP
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", "Microsoft Corporation\0"
+ VALUE "FileDescription", "Object Linking and Embedding Client Demo Application\0"
+ VALUE "FileVersion", "1.00.000\0"
+ VALUE "InternalName", "CliDemo\0"
+ VALUE "LegalCopyright", "Copyright \251 Microsoft Corp. 1991-1992\0"
+ VALUE "ProductName", "Microsoft Object Linking and Embedding Demo Client for Windows"
+ VALUE "ProductVersion", "1.01.000\0"
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 1252
+ END
+
+END
+
diff --git a/private/oleutest/ole1/clidemo/cliver.h b/private/oleutest/ole1/clidemo/cliver.h
new file mode 100644
index 000000000..97238b195
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/cliver.h
@@ -0,0 +1,9 @@
+#define CLIVER_DEBUG 0
+#define CLIVER_PRERELEASE 1
+
+#define CLIVER_FILEFLAGS (CLIVER_PRERELEASE|CLIVER_DEBUG)
+
+#define CLIVER_FILEOS VOS_DOS_WINDOWS16
+#define CLIVER_FILEVERSION 1,01
+#define CLIVER_PRODUCTVERSION 1,01,0,00
+
diff --git a/private/oleutest/ole1/clidemo/daytona/makefile b/private/oleutest/ole1/clidemo/daytona/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/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/ole1/clidemo/daytona/sources b/private/oleutest/ole1/clidemo/daytona/sources
new file mode 100644
index 000000000..568bae5a3
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/daytona/sources
@@ -0,0 +1,26 @@
+TARGETNAME=clidemo1
+TARGETPATH=obj
+TARGETTYPE=PROGRAM
+TARGETLIBS=
+
+INCLUDES= .
+C_DEFINES = -DWIN32 -DSTRICT
+NTDEBUG=
+
+SOURCES=..\clidemo.c \
+ ..\object.c \
+ ..\utility.c \
+ ..\dialog.c \
+ ..\register.c \
+ ..\stream.c \
+ ..\clidemo.rc
+
+UMTYPE=windows
+UMENTRY=winmain
+UMLIBS= \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\olecli32.lib \
+ obj\*\clidemo.res
+
diff --git a/private/oleutest/ole1/clidemo/demorc.h b/private/oleutest/ole1/clidemo/demorc.h
new file mode 100644
index 000000000..e87a5b345
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/demorc.h
@@ -0,0 +1,180 @@
+/*
+ * demorc.h - Header file for OLE demo's resource file.
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+/* Application resource ID */
+
+#define ID_APPLICATION 1
+
+#define POS_FILEMENU 0
+/* File menu */
+#define IDM_NEW 0x100
+#define IDM_OPEN 0x101
+#define IDM_SAVE 0x102
+#define IDM_SAVEAS 0x103
+#define IDM_EXIT 0x104
+#define IDM_ABOUT 0x105
+
+#define POS_EDITMENU 1
+/* Edit menu */
+#define IDM_CUT 0x200
+#define IDM_COPY 0x201
+#define IDM_PASTE 0x202
+#define IDM_PASTELINK 0x203
+#define IDM_CLEAR 0x204
+#define IDM_CLEARALL 0x205
+#define IDM_LINKS 0x206
+
+/* Object popup menu */
+#define POS_OBJECT 9 // position of Object item in Edit menu
+#define IDM_OBJECT 0x210
+#define IDM_VERBMIN 0x211
+#define IDM_VERBMAX 0x220 // Put this up to 220 (15 verbs) !!!
+#define CVERBSMAX (IDM_VERBMAX - IDM_VERBMIN + 1)
+
+#define POS_OBJECTMENU 2
+#define IDM_INSERT 0x300
+#define IDM_INSERTFILE 0x301
+
+#define IDM_UNDO 0x400 /* Only used internally */
+#define IDM_LOAD 0x401
+#define IDM_UPDATE 0x402
+
+
+/* Dialog box ids */
+#define DTPROP 1
+#define DTINVALIDLINK 2
+#define DTCREATE 3
+
+#define IDD_LINKNAME 0x200
+#define IDD_AUTO 0x201 // Auto update
+#define IDD_MANUAL 0x202 // Manual update
+#define IDD_EDIT 0x203 // Edit Object button
+#define IDD_FREEZE 0x204 // Cancel Link button
+#define IDD_UPDATE 0x205 // Update Now Button
+#define IDD_CHANGE 0x206 // Change Links Button
+#define IDD_LINKDONE 0x207 // ???
+#define IDD_PLAY 0x208 // Activate Button
+#define IDD_LISTBOX 0x209 // List of Links List Box
+#define IDD_DESTROY 0x20A
+
+#define IDD_YES 0x210
+#define IDD_NO 0x211
+#define IDD_RETRY 0x212
+#define IDD_SWITCH 0x213
+#define IDD_RETRY_TEXT1 0x214
+#define IDD_RETRY_TEXT2 0x215
+
+/* String table constants */
+#define CBMESSAGEMAX 80
+#define IDS_APPNAME 0x100
+#define IDS_UNTITLED 0x101
+#define IDS_MAYBESAVE 0x102
+#define IDS_OPENFILE 0x103
+#define IDS_SAVEFILE 0x104
+#define IDS_INSERTFILE 0x105
+#define IDS_FILTER 0x106
+#define IDS_EXTENSION 0x107
+#define IDS_CHANGELINK 0x108
+#define IDS_ALLFILTER 0x109
+#define IDS_EMBEDDED 0x10a
+#define IDS_UPDATELINKS 0x10b
+#define IDS_RENAME 0x10c
+#define IDS_INVALID_LINK 0x10d
+#define IDS_SAVE_CHANGES 0x10e
+#define IDS_UPDATE_OBJ 0x110
+#define IDS_RETRY_TEXT1 0x111
+#define IDS_RETRY_TEXT2 0x112
+
+/* Error messages */
+#define E_FAILED_TO_OPEN_FILE 0x200
+#define E_FAILED_TO_READ_FILE 0x201
+#define E_FAILED_TO_SAVE_FILE 0x202
+#define E_INVALID_FILENAME 0x203
+#define E_CREATE_FROM_TEMPLATE 0x204
+#define E_FAILED_TO_WRITE_OBJECT 0x205
+#define E_FAILED_TO_READ_OBJECT 0x206
+#define E_FAILED_TO_DELETE_OBJECT 0x207
+#define E_CLIPBOARD_CUT_FAILED 0x208
+#define E_CLIPBOARD_COPY_FAILED 0x209
+#define E_GET_FROM_CLIPBOARD_FAILED 0x20a
+#define E_FAILED_TO_CREATE_CHILD_WINDOW 0x20b
+#define E_FAILED_TO_CREATE_OBJECT 0x20c
+#define E_OBJECT_BUSY 0x20d
+#define E_UNEXPECTED_RELEASE 0x20e
+#define E_FAILED_TO_LAUNCH_SERVER 0x20f
+#define E_FAILED_TO_UPDATE 0x210
+#define E_FAILED_TO_FREEZE 0x211
+#define E_FAILED_TO_UPDATE_LINK 0x212
+#define E_SERVER_BUSY 0x213
+#define E_FAILED_TO_RECONNECT_OBJECT 0x214
+#define E_FAILED_TO_CONNECT 0x215
+#define E_FAILED_TO_RELEASE_OBJECT 0x216
+#define E_FAILED_TO_ALLOC 0x217
+#define E_FAILED_TO_LOCK 0x218
+#define E_FAILED_TO_DO_VERB 0x219
+
+#define W_IMPROPER_LINK_OPTIONS 0x300
+#define W_STATIC_OBJECT 0x301
+#define W_FAILED_TO_CLONE_UNDO 0x302
+#define W_FAILED_TO_NOTIFY 0x303
+
+#define SZAUTO 0x400
+#define SZMANUAL 0x401
+#define SZFROZEN 0x402
+
+#define E_OLE_ERROR_PROTECT_ONLY 3
+#define E_OLE_ERROR_MEMORY 4
+#define E_OLE_ERROR_STREAM 5
+#define E_OLE_ERROR_STATIC 6
+#define E_OLE_ERROR_BLANK 7
+#define E_OLE_ERROR_DRAW 8
+#define E_OLE_ERROR_METAFILE 9
+#define E_OLE_ERROR_ABORT 10
+#define E_OLE_ERROR_CLIPBOARD 11
+#define E_OLE_ERROR_FORMAT 12
+#define E_OLE_ERROR_OBJECT 13
+#define E_OLE_ERROR_OPTION 14
+#define E_OLE_ERROR_PROTOCOL 15
+#define E_OLE_ERROR_ADDRESS 16
+#define E_OLE_ERROR_NOT_EQUAL 17
+#define E_OLE_ERROR_HANDLE 18
+#define E_OLE_ERROR_GENERIC 19
+#define E_OLE_ERROR_CLASS 20
+#define E_OLE_ERROR_SYNTAX 21
+#define E_OLE_ERROR_DATATYPE 22
+#define E_OLE_ERROR_PALETTE 23
+#define E_OLE_ERROR_NOT_LINK 24
+#define E_OLE_ERROR_NOT_EMPTY 25
+#define E_OLE_ERROR_SIZE 26
+#define E_OLE_ERROR_DRIVE 27
+#define E_OLE_ERROR_NETWORK 28
+#define E_OLE_ERROR_NAME 29
+#define E_OLE_ERROR_TEMPLATE 30
+#define E_OLE_ERROR_NEW 31
+#define E_OLE_ERROR_EDIT 32
+#define E_OLE_ERROR_OPEN 33
+#define E_OLE_ERROR_NOT_OPEN 34
+#define E_OLE_ERROR_LAUNCH 35
+#define E_OLE_ERROR_COMM 36
+#define E_OLE_ERROR_TERMINATE 37
+#define E_OLE_ERROR_COMMAND 38
+#define E_OLE_ERROR_SHOW 39
+#define E_OLE_ERROR_DOVERB 40
+#define E_OLE_ERROR_ADVISE_NATIVE 41
+#define E_OLE_ERROR_ADVISE_PICT 42
+#define E_OLE_ERROR_ADVISE_RENAME 43
+#define E_OLE_ERROR_POKE_NATIVE 44
+#define E_OLE_ERROR_REQUEST_NATIVE 45
+#define E_OLE_ERROR_REQUEST_PICT 46
+#define E_OLE_ERROR_SERVER_BLOCKED 47
+#define E_OLE_ERROR_REGISTRATION 48
+#define E_OLE_ERROR_ALREADY_REGISTERED 49
+#define E_OLE_ERROR_TASK 50
+#define E_OLE_ERROR_OUTOFDATE 51
+#define E_OLE_ERROR_CANT_UPDATE_CLIENT 52
+#define E_OLE_ERROR_UPDATE 53
+
diff --git a/private/oleutest/ole1/clidemo/dialog.c b/private/oleutest/ole1/clidemo/dialog.c
new file mode 100644
index 000000000..1e5eb6cc0
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/dialog.c
@@ -0,0 +1,1150 @@
+/*
+ * dialog.c - Handles the Windows 3.1 common dialogs.
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** INCLUDES ****
+
+#include <windows.h> //* WINDOWS
+#include <ole.h> //* OLE
+
+#include "global.h" //* global
+#include "demorc.h" //* String table constants
+#include "register.h" //* Class registration library
+#include "utility.h"
+#include "dialog.h"
+#include "object.h"
+
+//*** GLOBALS ***
+ //* strings used with commdlg
+CHAR szDefExtension[CBMESSAGEMAX];
+CHAR szFilterSpec[CBFILTERMAX];
+CHAR szInsertFilter[CBFILTERMAX];
+CHAR szLastDir[CBPATHMAX];
+OPENFILENAME OFN;
+HWND hwndProp = NULL;
+HWND hRetry;
+
+/***************************************************************************
+ * OfnInit()
+ * Initializes the standard file dialog OFN structure.
+ **************************************************************************/
+
+VOID FAR OfnInit( //* ENTRY:
+ HANDLE hInst //* instance handle
+){ //* LOCAL:
+ LPSTR lpstr; //* string pointer
+
+ LoadString(hInst, IDS_FILTER, szFilterSpec, CBMESSAGEMAX);
+ LoadString(hInst, IDS_EXTENSION, szDefExtension, CBMESSAGEMAX);
+
+ OFN.lStructSize = sizeof(OPENFILENAME);
+ OFN.hInstance = hInst;
+ OFN.nMaxCustFilter = CBFILTERMAX;
+ OFN.nMaxFile = CBPATHMAX;
+ OFN.lCustData = 0;
+ OFN.lpfnHook = NULL;
+ OFN.lpTemplateName = NULL;
+ OFN.lpstrFileTitle = NULL;
+ //* Construct the filter string
+ //* for the Open and Save dialogs
+ lpstr = (LPSTR)szFilterSpec;
+ lstrcat(lpstr, " (*.");
+ lstrcat(lpstr, szDefExtension);
+ lstrcat(lpstr, ")");
+ lpstr += lstrlen(lpstr) + 1;
+
+ lstrcpy(lpstr, "*.");
+ lstrcat(lpstr, szDefExtension);
+ lpstr += lstrlen(lpstr) + 1;
+ *lpstr = 0;
+
+ RegMakeFilterSpec(NULL, NULL, (LPSTR)szInsertFilter);
+
+}
+
+/***************************************************************************
+ * OfnGetName()
+ *
+ * Calls the standard file dialogs to get a file name
+ **************************************************************************/
+
+BOOL FAR OfnGetName( //* ENTRY:
+ HWND hwnd, //* parent window handle
+ LPSTR szFileName, //* File name
+ WORD msg //* operation
+){ //* LOCAL:
+ BOOL frc; //* return flag
+ CHAR szCaption[CBMESSAGEMAX];//* dialog caption
+
+ OFN.hwndOwner = hwnd; //* window
+ OFN.nFilterIndex = 1;
+ OFN.lpstrInitialDir = (LPSTR)szLastDir;
+ OFN.Flags = OFN_HIDEREADONLY;
+
+ switch (msg) //* message
+ {
+ case IDM_OPEN: //* open file
+ Normalize(szFileName);
+ OFN.lpstrDefExt = (LPSTR)szDefExtension;
+ OFN.lpstrFile = (LPSTR)szFileName;
+ OFN.lpstrFilter = (LPSTR)szFilterSpec;
+ LoadString(hInst, IDS_OPENFILE, szCaption, CBMESSAGEMAX);
+ OFN.lpstrTitle = (LPSTR)szCaption;
+ OFN.Flags |= OFN_FILEMUSTEXIST;
+ return GetOpenFileName((LPOPENFILENAME)&OFN);
+ break;
+
+ case IDM_SAVEAS: //* save as file
+ Normalize(szFileName);
+ OFN.lpstrDefExt = (LPSTR)szDefExtension;
+ OFN.lpstrFile = (LPSTR)szFileName;
+ OFN.lpstrFilter = (LPSTR)szFilterSpec;
+ LoadString(hInst, IDS_SAVEFILE, szCaption, CBMESSAGEMAX);
+ OFN.lpstrTitle = (LPSTR)szCaption;
+ OFN.Flags |= OFN_PATHMUSTEXIST;
+ return GetSaveFileName((LPOPENFILENAME)&OFN);
+ break;
+
+ case IDM_INSERTFILE: //* insert file
+ OFN.lpstrDefExt = NULL;
+ OFN.lpstrFile = (LPSTR)szFileName;
+ OFN.lpstrFilter = (LPSTR)szInsertFilter;
+ LoadString(hInst, IDS_INSERTFILE, szCaption, CBMESSAGEMAX);
+ OFN.lpstrTitle = (LPSTR)szCaption;
+ OFN.Flags |= OFN_FILEMUSTEXIST;
+ frc = GetOpenFileName((LPOPENFILENAME)&OFN);
+ AddExtension(&OFN);
+ return frc;
+ break;
+
+ default: //* default
+ break;
+ }
+
+}
+
+/***************************************************************************
+ * OfnGetNewLinkName() - Sets up the "Change Link..." dialog box
+ *
+ * returns LPSTR - fully qualified filename
+ **************************************************************************/
+
+LPSTR FAR OfnGetNewLinkName( //* ENTRY:
+ HWND hwnd, //* calling window or dialog
+ LPSTR lpstrData //* link data
+){ //* LOCAL:
+ LPSTR lpReturn = NULL; //* return string
+ LPSTR lpstrFile = NULL; //* non-qualified file name
+ LPSTR lpstrPath = NULL; //* pathname
+ LPSTR lpstrTemp = NULL; //* work string
+ CHAR szDocFile[CBPATHMAX];//* document name
+ CHAR szDocPath[CBPATHMAX];//* document path name
+ CHAR szServerFilter[CBPATHMAX];
+ CHAR szCaption[CBMESSAGEMAX];
+
+ //* Figure out the link's path
+ //* name and file name
+ lpstrTemp = lpstrData;
+ while (*lpstrTemp++);
+ lpstrPath = lpstrFile = lpstrTemp;
+
+ while (*(lpstrTemp = AnsiNext(lpstrTemp)))
+ if (*lpstrTemp == '\\')
+ lpstrFile = lpstrTemp + 1;
+ //* Copy the document name
+ lstrcpy(szDocFile, lpstrFile);
+ *(lpstrFile - 1) = 0;
+ //* Copy the path name
+ lstrcpy(szDocPath, ((lpstrPath != lpstrFile) ? lpstrPath : ""));
+ if (lpstrPath != lpstrFile) //* Restore the backslash
+ *(lpstrFile - 1) = '\\';
+ while (*lpstrFile != '.' && *lpstrFile)//* Get the extension
+ lpstrFile++;
+ //* Make a filter that respects
+ //* the link's class name
+ OFN.hwndOwner = hwnd;
+ OFN.nFilterIndex = RegMakeFilterSpec(lpstrData, lpstrFile, szServerFilter);
+ OFN.lpstrDefExt = NULL;
+ OFN.lpstrFile = (LPSTR)szDocFile;
+ OFN.lpstrFilter = (LPSTR)szServerFilter;
+ OFN.lpstrInitialDir = (LPSTR)szDocPath;
+ LoadString(hInst, IDS_CHANGELINK, szCaption, CBMESSAGEMAX);
+ OFN.lpstrTitle = (LPSTR)szCaption;
+ OFN.lpstrCustomFilter = NULL;
+ OFN.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
+
+ //* If we get a file... */
+ if (GetOpenFileName((LPOPENFILENAME)&OFN))
+ {
+ if (!(lpReturn = GlobalLock(GlobalAlloc(LHND, CBPATHMAX))))
+ goto Error;
+
+ AddExtension(&OFN);
+ lstrcpy(lpReturn, szDocFile);
+
+ OFN.lpstrInitialDir = (LPSTR)szLastDir;
+ }
+
+ return lpReturn; //* SUCCESS return
+
+Error: //* ERROR Tag
+
+ return NULL; //* ERROR return
+
+}
+
+/***************************************************************************
+ * Normalize()
+ * Removes the path specification from the file name.
+ *
+ * Note: It isn't possible to get "<drive>:<filename>" as input because
+ * the path received will always be fully qualified.
+ **************************************************************************/
+
+VOID Normalize( //* ENTRY:
+ LPSTR lpstrFile //* file name
+){ //* LOCAL:
+ LPSTR lpstrBackslash = NULL;//* back slash
+ LPSTR lpstrTemp = lpstrFile;//* file name
+
+ while (*lpstrTemp)
+ {
+ if (*lpstrTemp == '\\')
+ lpstrBackslash = lpstrTemp;
+
+ lpstrTemp = AnsiNext(lpstrTemp);
+ }
+ if (lpstrBackslash)
+ lstrcpy(lpstrFile, lpstrBackslash + 1);
+
+}
+
+/***************************************************************************
+ * AddExtension()
+ *
+ * Adds the extension corresponding to the filter dropdown.
+ **************************************************************************/
+
+VOID AddExtension( //* ENTRY:
+ LPOPENFILENAME lpOFN //* open file structure
+){
+
+ if (lpOFN->nFileExtension == (WORD)lstrlen(lpOFN->lpstrFile)
+ && lpOFN->nFilterIndex)
+ {
+ LPSTR lpstrFilter = (LPSTR)lpOFN->lpstrFilter;
+
+ while (*lpstrFilter && --lpOFN->nFilterIndex)
+ {
+ while (*lpstrFilter++) ;
+ while (*lpstrFilter++) ;
+ }
+ //* If we got to the filter,
+ if (*lpstrFilter) //* retrieve the extension
+ {
+ while (*lpstrFilter++) ;
+ lpstrFilter++;
+ //* Copy the extension
+ if (lpstrFilter[1] != '*')
+ lstrcat(lpOFN->lpstrFile, lpstrFilter);
+ }
+ }
+
+}
+/****************************************************************************
+ * fnInsertNew()
+ *
+ * Dialog procedure for the Insert New dialog.
+ *
+ * Returns int - TRUE if message processed, FALSE otherwise
+ ***************************************************************************/
+
+BOOL APIENTRY fnInsertNew( //* ENTRY:
+ HWND hDlg, //* standard dialog box paramters
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam //* (LPSTR) class name
+){ //* LOCAL:
+ HWND hwndList; //* handle to listbox
+ static LPSTR lpClassName; //* classname for return value
+
+ hwndList = GetDlgItem(hDlg, IDD_LISTBOX);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ if (!RegGetClassNames(hwndList))
+ EndDialog(hDlg, IDCANCEL);
+
+ lpClassName = (LPSTR)lParam;
+ SetFocus(hwndList);
+ SendMessage(hwndList, LB_SETCURSEL, 0, 0L);
+ return (FALSE);
+
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+ WORD wCmd = HIWORD(wParam);
+
+ switch (wID)
+ {
+ case IDD_LISTBOX:
+ if (wCmd != LBN_DBLCLK)
+ break;
+
+ case IDOK:
+ if (!RegCopyClassName(hwndList, lpClassName))
+ wParam = IDCANCEL;
+
+ case IDCANCEL:
+ EndDialog(hDlg, wParam);
+ break;
+ }
+ break;
+ }
+ }
+ return FALSE;
+
+}
+
+/***************************************************************************
+ * LinkProperties();
+ *
+ * Manage the link properties dialog box.
+ **************************************************************************/
+
+VOID FAR LinkProperties()
+{ //* LOCAL
+
+ DialogBox (
+ hInst,
+ MAKEINTRESOURCE(DTPROP),
+ hwndFrame,
+ (DLGPROC)fnProperties
+ );
+
+}
+
+/***************************************************************************
+ * fnProperties()
+ *
+ * Dialog procedure for link properties. The Links dialog allows the user to
+ * change the link options, edit/play the object, cancel the link as
+ * well change links.
+ *
+ * returns BOOL - TRUE if processed, FALSE otherwise
+ **************************************************************************/
+
+BOOL APIENTRY fnProperties( //* ENTRY:
+ HWND hDlg, //* standard dialog box parameters
+ UINT msg,
+ WPARAM wParam,
+ LPARAM lParam //* (HWND) child window with focus
+){ //* LOCAL:
+ static APPITEMPTR *pLinks; //* pointer to links (associated windows)
+ static INT nLinks; //* number of links
+ static HWND hwndList; //* handle to listbox window
+ static BOOL fTry;
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ hwndProp = hDlg;
+ hwndList = GetDlgItem(hDlg, IDD_LINKNAME);
+ if (!(InitLinkDlg(hDlg, &nLinks, hwndList, &pLinks)))
+ EndDialog(hDlg, TRUE);
+ UpdateLinkButtons(hDlg,nLinks,hwndList,pLinks);
+ break;
+
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+
+ switch (wID)
+ {
+ case IDD_CHANGE: //* change links
+ BLOCK_BUSY(fTry);
+ if (ChangeLinks(hDlg,nLinks,hwndList,pLinks))
+ DisplayUpdate(nLinks,hwndList,pLinks, FALSE);
+ return TRUE;
+
+ case IDD_FREEZE: //* cancel links
+ BLOCK_BUSY(fTry);
+ CancelLinks(hDlg,nLinks,hwndList,pLinks);
+ UpdateLinkButtons(hDlg,nLinks,hwndList,pLinks);
+ return TRUE;
+
+ case IDD_UPDATE: //* update links
+ BLOCK_BUSY(fTry);
+ DisplayUpdate(nLinks,hwndList,pLinks,TRUE);
+ UpdateLinkButtons(hDlg,nLinks,hwndList,pLinks);
+ return TRUE;
+
+ case IDD_AUTO:
+ case IDD_MANUAL: //* change link update options
+ BLOCK_BUSY(fTry);
+ if (!SendMessage(GetDlgItem(hDlg,wParam),BM_GETCHECK, 0, 0L))
+ {
+ CheckRadioButton(hDlg, IDD_AUTO ,IDD_MANUAL ,wParam);
+ ChangeUpdateOptions(hDlg,nLinks,hwndList,pLinks,
+ (wParam == IDD_AUTO ? oleupdate_always : oleupdate_oncall));
+ UpdateLinkButtons(hDlg,nLinks,hwndList,pLinks);
+ }
+ return TRUE;
+
+ case IDD_LINKNAME:
+ if (HIWORD(wParam) == LBN_SELCHANGE)
+ UpdateLinkButtons(hDlg,nLinks,hwndList,pLinks);
+ return TRUE;
+
+ case IDCANCEL:
+ BLOCK_BUSY(fTry);
+ UndoObjects();
+ END_PROP_DLG(hDlg,pLinks);
+ return TRUE;
+
+ case IDOK:
+ BLOCK_BUSY(fTry);
+ DelUndoObjects(FALSE);
+ END_PROP_DLG(hDlg,pLinks);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+/****************************************************************************
+ * InitLinkDlg();
+ *
+ * Initialize the list box of links.
+ ***************************************************************************/
+
+static BOOL InitLinkDlg ( //* ENTRY:
+ HWND hDlg, //* dialog box handle
+ INT *nLinks, //* pointer to number of links
+ HWND hwndList, //* listbox handle
+ APPITEMPTR **pLinks //* list of window handles of links
+){ //* LOCAL
+ APPITEMPTR pItem; //* application item pointer
+ LPSTR lpstrData = NULL; //* pointer to link data
+ CHAR szFull[CBMESSAGEMAX * 4];//* list box entry string
+ CHAR pLinkData[OBJECT_LINK_MAX];//* holder of link data
+ BOOL fSelect = FALSE; //* item selected flag
+ HANDLE hWork; //* working memory handle
+ APPITEMPTR pTop; //* pointer to the top object
+
+ if (!(*pLinks = (APPITEMPTR *)LocalLock(LocalAlloc(LHND,sizeof(APPITEMPTR)*10))))
+ {
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ return 0;
+ }
+ *nLinks = 0;
+ //* set tabs
+ SendMessage(hwndList,WM_SETREDRAW,FALSE,0L);
+ //* enumerate child windows
+ for (pTop = pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ {
+ if (pItem->otObject == OT_LINK && pItem->fVisible)
+ {
+ *(*pLinks + *nLinks) = pItem;
+ if (!((*nLinks += 1)%10))
+ { //* add blocks of ten
+ hWork = LocalHandle((LPSTR)(*pLinks));
+ LocalUnlock(hWork);
+ if (!(hWork = LocalReAlloc(hWork,(*nLinks+10)*sizeof(APPITEMPTR),0)))
+ {
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ return FALSE; //* ERROR return
+ }
+ *pLinks = (APPITEMPTR *)LocalLock(hWork);
+ }
+
+ if (pTop == pItem)
+ fSelect = TRUE;
+
+ if (!ObjGetData(pItem, pLinkData))
+ continue;
+ //* make listbox entry
+ MakeListBoxString(pLinkData, szFull, pItem->uoObject);
+ //* add listbox entry
+ SendMessage(hwndList, LB_ADDSTRING, 0, (LONG)(LPSTR)szFull);
+ }
+ }
+
+ if (fSelect)
+ SendMessage(hwndList, LB_SETSEL, 1, 0L);
+
+ SendMessage(hwndList,WM_SETREDRAW,TRUE,0L);
+ UpdateWindow(hwndList);
+
+ return TRUE; //* SUCCESS return
+
+}
+
+/****************************************************************************
+ * MakeListBoxString()
+ *
+ * build an listbox entry string
+ ***************************************************************************/
+
+static VOID MakeListBoxString( //* ENTRY:
+ LPSTR lpLinkData, //* pointer to link data
+ LPSTR lpBoxData, //* return string
+ OLEOPT_UPDATE oleopt_update //* OLE update option
+){ //* LOCAL:
+ CHAR szType[CBMESSAGEMAX];//* holds update option string
+ LPSTR lpTemp; //* working string pointer
+ INT i; //* index
+
+ //* get classname
+ RegGetClassId(lpBoxData, lpLinkData);
+ lstrcat(lpBoxData, " - "); //* ads tab
+
+ while (*lpLinkData++); //* skip to document name
+
+ lpTemp = lpLinkData;
+ while (*lpTemp) //* copy document name;
+ { //* strip drive an directory
+ if (*lpTemp == '\\' || *lpTemp == ':')
+ lpLinkData = lpTemp + 1;
+ lpTemp = AnsiNext(lpTemp);
+ }
+ lstrcat(lpBoxData, lpLinkData);
+ lstrcat(lpBoxData, " - ");
+
+ while (*lpLinkData++); //* copy item data
+ lstrcat(lpBoxData, lpLinkData);
+ lstrcat(lpBoxData, " - ");
+ //* add update option string
+ switch (oleopt_update)
+ {
+ case oleupdate_always: i = SZAUTO; break;
+ case oleupdate_oncall: i = SZMANUAL; break;
+ default: i = SZFROZEN;
+ }
+ LoadString(hInst, i, szType, CBMESSAGEMAX);
+ lstrcat(lpBoxData, szType);
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * UpdateLinkButtons()
+ *
+ * Keep link buttons active as appropriate. This routine is called after
+ * a selection is made so the buttons reflect the selected items.
+ **************************************************************************/
+
+static VOID UpdateLinkButtons( //* ENTRY:
+ HWND hDlg, //* dialog box handle
+ INT nLinks, //* number of links
+ HWND hwndList, //* listbox handle
+ APPITEMPTR *pLinks //* pointer to link's window handles
+){ //* LOCAL:
+ ATOM aCurName=0; //* atom of current doc
+ BOOL fChangeLink = TRUE; //* enable/disable changelink button
+ INT iAuto,iManual,i; //* count of manual and auto links
+ APPITEMPTR pItem; //* application item pointer
+ INT iStatic;
+
+ iStatic = iAuto = iManual = 0;
+
+ for (i = 0; i < nLinks; i++) //* enum selected links
+ {
+ if (SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ if (pItem->otObject == OT_STATIC)
+ iStatic++;
+ else
+ {
+ switch(pItem->uoObject)
+ { //* count number of manual and
+ case oleupdate_always: //* automatic links selected
+ iAuto++;
+ break;
+ case oleupdate_oncall:
+ iManual++;
+ break;
+ }
+ //* check if all selected links are
+ if (!aCurName) //* linked to same file
+ aCurName = pItem->aLinkName;
+ else if (aCurName != pItem->aLinkName)
+ fChangeLink = FALSE;
+ }
+ }
+ }
+
+ if (!(iAuto || iManual || iStatic) //* if no links disable all buttons
+ || (!iAuto && !iManual && iStatic))
+ {
+ EnableWindow(GetDlgItem(hDlg, IDD_FREEZE), FALSE );
+ EnableWindow(GetDlgItem(hDlg, IDD_CHANGE), FALSE );
+ EnableWindow(GetDlgItem(hDlg, IDD_UPDATE), FALSE );
+ CheckDlgButton(hDlg, IDD_AUTO, FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDD_AUTO),FALSE);
+ CheckDlgButton(hDlg, IDD_MANUAL, FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDD_MANUAL),FALSE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hDlg, IDD_UPDATE), TRUE );
+ EnableWindow(GetDlgItem(hDlg, IDD_FREEZE), TRUE );
+
+ if (iAuto && iManual || !(iAuto || iManual))
+ { //* Set update buttons
+ CheckDlgButton(hDlg, IDD_AUTO, FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDD_AUTO),FALSE);
+ CheckDlgButton(hDlg, IDD_MANUAL, FALSE);
+ EnableWindow(GetDlgItem(hDlg, IDD_MANUAL),FALSE);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hDlg, IDD_MANUAL), TRUE);
+ EnableWindow(GetDlgItem(hDlg, IDD_AUTO), TRUE);
+ if (iAuto)
+ {
+ CheckDlgButton(hDlg, IDD_AUTO, TRUE);
+ CheckDlgButton(hDlg, IDD_MANUAL, FALSE);
+ }
+ else
+ {
+ CheckDlgButton(hDlg, IDD_AUTO, FALSE);
+ CheckDlgButton(hDlg, IDD_MANUAL, TRUE);
+ }
+ }
+ }
+
+ EnableWindow(GetDlgItem(hDlg, IDD_CHANGE),fChangeLink && aCurName);
+
+}
+
+/****************************************************************************
+ * ChangeLinks()
+ *
+ * This routine changes the linked data if the user chooses a new file to
+ * replace the old document data portion of the linked date. The routine
+ * does nothing if the user cancels.
+ *
+ * returns TRUE - if data changed FALSE if user cancel or err.
+ ***************************************************************************/
+
+static BOOL ChangeLinks( //* ENTRY:
+ HWND hDlg, //* dialog handle
+ INT nLinks, //* number of links in listbox
+ HWND hwndList, //* listbox
+ APPITEMPTR *pLinks //* list of application link handles
+){ //* LOCAL
+ INT i; //* general index
+ HANDLE hWork; //* work
+ APPITEMPTR pItem; //* application item
+ LPSTR lpNewDoc = NULL; //* new document
+ ATOM aOldDoc; //* atom of old doc. name
+ ATOM aCurDoc = 0; //* atom of change-to doc. name
+ BOOL fMessage = FALSE; //* error message flag
+ LPSTR lpLinkData; //* pointer to link data
+
+ lpLinkData = NULL;
+ //* This loop finds all selected links
+ for (i = 0; i < nLinks; i++) //* and updates them
+ {
+ if (SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ CHECK_IF_STATIC(pItem);
+
+ pItem->lpLinkData = lpLinkData;
+ if (!ObjGetData(pItem,NULL))
+ continue;
+
+ if (!lpNewDoc)
+ {
+ if (!(lpNewDoc = OfnGetNewLinkName(hDlg, pItem->lpLinkData)))
+ return FALSE; //* ERROR jump
+ aOldDoc = pItem->aLinkName;
+ aCurDoc = AddAtom(lpNewDoc);
+ SendMessage(hwndList,WM_SETREDRAW,FALSE,0L);
+ }
+
+ ObjSaveUndo(pItem);
+ ObjChangeLinkData(pItem,lpNewDoc);
+ pItem->aLinkName = aCurDoc;
+ lpLinkData = pItem->lpLinkData;
+
+ CHANGE_LISTBOX_STRING(hwndList, i, pItem, pItem->lpLinkData);
+
+ pItem->lpLinkData = NULL;
+ }
+ }
+
+ /*************************************************************************
+ * now deal with non-selected links and look for a match...
+ *************************************************************************/
+
+ //* this loop finds non-selected links
+ for (i = 0; i < nLinks; i++) //* and asks the user to update these?
+ {
+ if (!SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ if (pItem->otObject == OT_STATIC)
+ continue;
+
+ if (!ObjGetData(pItem,NULL))
+ continue;
+
+ if (pItem->aLinkName == aOldDoc)
+ {
+ if (!fMessage)
+ {
+ CHAR szMessage[2*CBMESSAGEMAX+3*CBPATHMAX];
+ CHAR szRename[2*CBMESSAGEMAX];
+ CHAR szOldDoc[CBMESSAGEMAX];
+ LPSTR pOldDoc;
+
+ GetAtomName(aOldDoc,szOldDoc,CBMESSAGEMAX);
+ pOldDoc =(LPSTR)UnqualifyPath(szOldDoc);
+ LoadString(hInst, IDS_RENAME, szRename, 2*CBMESSAGEMAX);
+ wsprintf(
+ szMessage,
+ szRename,
+ pOldDoc,
+ (LPSTR)UnqualifyPath(szFileName),
+ pOldDoc
+ );
+
+ if (MessageBox(hDlg, szMessage,
+ szAppName, MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
+ break;
+ fMessage = TRUE;
+ }
+
+ ObjSaveUndo(pItem);
+ ObjChangeLinkData(pItem,lpNewDoc);
+ CHANGE_LISTBOX_STRING(hwndList, i, pItem, pItem->lpLinkData);
+
+ pItem->aLinkName = aCurDoc;
+ }
+ }
+ }
+
+ if(lpNewDoc)
+ {
+ hWork = GlobalHandle(lpNewDoc);
+ GlobalUnlock(hWork);
+ GlobalFree(hWork);
+ }
+
+#if 0
+// This is bogus -- this memory is owned by OLECLI32.DLL, not this app,
+// so it should not be freed here.
+ if (lpLinkData)
+ FreeLinkData(lpLinkData);
+#endif
+
+ SendMessage(hwndList,WM_SETREDRAW,TRUE,0L);
+ InvalidateRect(hwndList,NULL,TRUE);
+ UpdateWindow(hwndList);
+
+ WaitForAllObjects();
+
+ if (aCurDoc)
+ DeleteAtom(aCurDoc);
+
+ return(TRUE);
+}
+
+/****************************************************************************
+ * DisplayUpdate()
+ *
+ * Get the most up to date rendering information and show it.
+ ***************************************************************************/
+
+static VOID DisplayUpdate( //* ENTRY:
+ INT nLinks, //* number of links in listbox
+ HWND hwndList, //* listbox
+ APPITEMPTR *pLinks, //* list of application link handles
+ BOOL fSaveUndo //* save undo objects
+){ //* LOCAL:
+ INT i; //* index
+ APPITEMPTR pItem; //* temporary item pointer
+
+
+ for (i = 0; i < nLinks; i++)
+ if (SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ CHECK_IF_STATIC(pItem);
+ if (fSaveUndo)
+ ObjSaveUndo(pItem);
+ Error(OleUpdate(pItem->lpObject));
+ }
+
+ WaitForAllObjects();
+
+}
+
+/****************************************************************************
+ * UndoObjects()
+ *
+ * Bring objects back to their original state.
+ ***************************************************************************/
+
+static VOID UndoObjects()
+{
+ APPITEMPTR pItem; //* application item pointer
+ //* enum objects
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ if (pItem->lpObjectUndo)
+ ObjUndo(pItem);
+
+ WaitForAllObjects();
+
+}
+
+
+/****************************************************************************
+ * DelUndoObjects()
+ *
+ * remove all objects created for undo operation.
+ ***************************************************************************/
+
+static VOID DelUndoObjects( //* ENTRY:
+ BOOL fPrompt //* prompt user?
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+ BOOL fPrompted = FALSE; //* prompted user?
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ {
+ if (pItem->lpObjectUndo)
+ {
+ if (fPrompt && !fPrompted) //* prompt user in activation case
+ {
+ CHAR szPrompt[CBMESSAGEMAX];
+
+ LoadString(hInst, IDS_SAVE_CHANGES, szPrompt, CBMESSAGEMAX);
+
+ if (MessageBox(hwndFrame, szPrompt,
+ szAppName, MB_YESNO | MB_ICONEXCLAMATION) == IDNO)
+ {
+ UndoObjects();
+ return; //* user canceled operation
+ }
+ fPrompted = TRUE;
+ }
+ ObjDelUndo(pItem); //* delete udo object
+ }
+ }
+
+ WaitForAllObjects();
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * CancelLinks()
+ ***************************************************************************/
+
+static VOID CancelLinks( //* ENTRY:
+ HWND hDlg, //* calling dialog
+ INT nLinks, //* number of links in listbox
+ HWND hwndList, //* listbox
+ APPITEMPTR *pLinks //* list of application link handles
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+ INT i; //* index
+ CHAR pLinkData[OBJECT_LINK_MAX];//* holder of link data
+
+ SendMessage(hwndList,WM_SETREDRAW,FALSE,0L);
+ for (i = 0; i < nLinks; i++)
+ if (SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ CHECK_IF_STATIC(pItem);
+ ObjGetData(pItem,pLinkData);
+ ObjSaveUndo(pItem);
+ ObjFreeze(pItem);
+
+ CHANGE_LISTBOX_STRING(hwndList, i, pItem, pLinkData);
+ }
+
+ SendMessage(hwndList,WM_SETREDRAW,TRUE,0L);
+ InvalidateRect(hwndList,NULL,TRUE);
+ UpdateWindow(hwndList);
+
+}
+
+
+/****************************************************************************
+ * ChangeUpdateOptions()
+ *
+ * Change the update options for all selected objects.
+ ***************************************************************************/
+
+static VOID ChangeUpdateOptions( //* ENTRY:
+ HWND hDlg, //* calling dialog
+ INT nLinks, //* number of links in listbox
+ HWND hwndList, //* listbox
+ APPITEMPTR *pLinks, //* list of application link handles
+ OLEOPT_UPDATE lUpdate //* update option
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item
+ INT i; //* index
+ CHAR pLinkData[OBJECT_LINK_MAX];
+
+ SendMessage(hwndList,WM_SETREDRAW,FALSE,0L);
+
+ for (i = 0; i < nLinks; i++) //* enum selected objects
+ {
+ if (SendMessage(hwndList, LB_GETSEL, i, 0L))
+ {
+ pItem = *(pLinks+i);
+ CHECK_IF_STATIC(pItem);
+ ObjGetData(pItem,pLinkData);
+ ObjSaveUndo(pItem);
+ if (Error(OleSetLinkUpdateOptions(pItem->lpObject,lUpdate)))
+ continue;
+ pItem->uoObject = lUpdate;
+
+ CHANGE_LISTBOX_STRING(hwndList, i, pItem, pLinkData);
+ }
+ }
+
+ SendMessage(hwndList,WM_SETREDRAW,TRUE,0L);
+ InvalidateRect(hwndList,NULL,TRUE);
+ UpdateWindow(hwndList);
+ WaitForAllObjects();
+
+}
+/****************************************************************************
+ * InvalidLink()
+ *
+ * Deal with letting the user know that the program has inadvertently come
+ * across an invalid link.
+ *
+ * Global fPropBoxActive - flag to determine whether or not the link dialog
+ * box is active. If it is not active we give the
+ * user an opportunity to enter the links property
+ * dialog directly from here.
+ ***************************************************************************/
+
+VOID FAR InvalidLink()
+{
+
+ if (!hwndProp)
+ DialogBox(hInst, "InvalidLink", hwndFrame, (DLGPROC)fnInvalidLink);
+ else
+ ErrorMessage(E_FAILED_TO_CONNECT);
+
+}
+
+/****************************************************************************
+ * fnABout()
+ *
+ * About box dialog box procedure.
+ ***************************************************************************/
+
+BOOL APIENTRY fnInvalidLink( //* ENTRY:
+ HWND hDlg, //* standard windows dialog box
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+){
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ return (TRUE);
+
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDD_CHANGE)
+ LinkProperties();
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ return (FALSE);
+
+}
+
+/****************************************************************************
+ * AboutBox()
+ *
+ * Show the About Box dialog.
+ ***************************************************************************/
+
+VOID FAR AboutBox()
+{
+
+ DialogBox(hInst, "AboutBox", hwndFrame, (DLGPROC)fnAbout);
+
+}
+
+/****************************************************************************
+ * fnABout()
+ *
+ * About box dialog box procedure.
+ ***************************************************************************/
+
+BOOL APIENTRY fnAbout( //* ENTRY:
+ HWND hDlg, //* standard windows dialog box
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+){
+
+ switch (message)
+ {
+ case WM_INITDIALOG:
+ return (TRUE);
+
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+
+ if (wID == IDOK || wID == IDCANCEL)
+ {
+ EndDialog(hDlg, TRUE);
+ return (TRUE);
+ }
+ break;
+ }
+ }
+ return (FALSE);
+
+}
+
+
+
+/***************************************************************************
+ * RetryMessage()
+ *
+ * give the user the chance to abort when a server is in retry case.
+ *
+ * Returns BOOL - TRUE if user chooses to cancel
+ **************************************************************************/
+
+VOID FAR RetryMessage ( //* ENTRY:
+ APPITEMPTR paItem, //* application item pointer
+ LONG lParam
+){
+ RETRYPTR pRetry;
+ LONG objectType;
+ HANDLE hData;
+ static CHAR szServerName[KEYNAMESIZE];
+ HWND hwnd; //* window handle
+
+ if (IsWindow(hwndProp))
+ hwnd = hwndProp;
+ else if (IsWindow(hwndFrame))
+ hwnd = hwndFrame;
+ else
+ return; //* should not happen
+ //* get the busy servers name
+ lstrcpy(szServerName, "server application");
+
+ if (paItem)
+ {
+ if (!paItem->aServer)
+ {
+ OleQueryType(paItem->lpObject, &objectType );
+ if (OLE_OK == OleGetData(paItem->lpObject, (OLECLIPFORMAT) (objectType == OT_LINK ? vcfLink : vcfOwnerLink), &hData ))
+ {
+ RegGetClassId(szServerName, GlobalLock(hData));
+ paItem->aServer = AddAtom(szServerName);
+ GlobalUnlock( hData );
+ }
+ }
+ else
+ GetAtomName(paItem->aServer,szServerName,KEYNAMESIZE);
+
+ }
+
+ hData = LocalAlloc(LHND,sizeof(RETRYSTRUCT));
+ if(!(pRetry = (RETRYPTR)LocalLock(hData)))
+ return;
+
+ pRetry->lpserver = (LPSTR)szServerName;
+ pRetry->bCancel = (BOOL)(lParam & RD_CANCEL);
+ pRetry->paItem = paItem;
+
+ DialogBoxParam(hInst, "RetryBox", hwnd, (DLGPROC)fnRetry, (LONG)pRetry );
+
+ LocalUnlock(hData);
+ LocalFree(hData);
+
+ hRetry = NULL;
+
+}
+
+/****************************************************************************
+ * fnRetry()
+ *
+ * Retry message box nothing to tricky; however, when a server becomes
+ * unbusy a message is posted to automatically get rid of this dialog.
+ * I send a no.
+ ***************************************************************************/
+
+BOOL APIENTRY fnRetry( //* ENTRY
+ HWND hDlg, //* standard dialog entry
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam
+){
+ static RETRYPTR pRetry;
+
+ switch (message)
+ {
+ case WM_COMMAND:
+ {
+ WORD wID = LOWORD(wParam);
+
+ switch (wParam)
+ {
+ case IDD_SWITCH:
+ DefWindowProc( hDlg, WM_SYSCOMMAND, SC_TASKLIST, 0);
+ break;
+
+ case IDCANCEL:
+ if (pRetry->paItem)
+ pRetry->paItem->fRetry = FALSE;
+ EndDialog(hDlg, TRUE);
+ return TRUE;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ case WM_INITDIALOG:
+ {
+ CHAR szBuffer[CBMESSAGEMAX];
+ CHAR szText[2*CBMESSAGEMAX];
+
+ pRetry = (RETRYPTR)lParam;
+ hRetry = hDlg;
+
+ LoadString(hInst, IDS_RETRY_TEXT1, szBuffer, CBMESSAGEMAX);
+ wsprintf(szText, szBuffer, pRetry->lpserver);
+ SetWindowText (GetDlgItem(hDlg, IDD_RETRY_TEXT1), szText);
+
+ LoadString(hInst, IDS_RETRY_TEXT2, szBuffer, CBMESSAGEMAX);
+ wsprintf(szText, szBuffer, pRetry->lpserver);
+ SetWindowText (GetDlgItem(hDlg, IDD_RETRY_TEXT2), szText);
+
+ EnableWindow (GetDlgItem(hDlg, IDCANCEL), pRetry->bCancel);
+
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
diff --git a/private/oleutest/ole1/clidemo/dialog.h b/private/oleutest/ole1/clidemo/dialog.h
new file mode 100644
index 000000000..9768fad1a
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/dialog.h
@@ -0,0 +1,85 @@
+/*
+ * dialog.h
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** INCLUDES ***
+
+#include <commdlg.h>
+
+//*** PROTOTYPES ***
+
+//*** FAR
+BOOL FAR FullyQualify(LPSTR, LPSTR);
+BOOL FAR OfnGetName(HWND, LPSTR, WORD);
+LPSTR FAR OfnGetNewLinkName(HWND, LPSTR);
+VOID FAR OfnInit(HANDLE);
+BOOL APIENTRY fnInsertNew(HWND, UINT, WPARAM, LPARAM);
+BOOL APIENTRY fnProperties(HWND, UINT, WPARAM, LPARAM);
+VOID FAR LinkProperties(VOID);
+VOID FAR AboutBox(VOID);
+BOOL APIENTRY fnAbout( HWND, UINT, WPARAM, LPARAM);
+VOID FAR RetryMessage (APPITEMPTR,LONG);
+BOOL APIENTRY fnRetry(HWND, UINT, WPARAM, LPARAM);
+VOID FAR InvalidLink(VOID);
+BOOL APIENTRY fnInvalidLink(HWND, UINT, WPARAM, LPARAM);
+
+//*** Local
+static VOID AddExtension(LPOPENFILENAME);
+static VOID Normalize(LPSTR);
+static BOOL InitLinkDlg (HWND, INT *, HWND, APPITEMPTR **);
+static VOID UpdateLinkButtons(HWND, INT, HWND, APPITEMPTR *);
+static BOOL ChangeLinks(HWND, INT, HWND, APPITEMPTR *);
+static VOID CancelLinks(HWND, INT, HWND, APPITEMPTR *);
+static VOID DisplayUpdate(INT, HWND, APPITEMPTR *, BOOL);
+static VOID UndoObjects(VOID);
+static VOID DelUndoObjects(BOOL);
+static VOID ChangeUpdateOptions(HWND, INT, HWND, APPITEMPTR *, OLEOPT_UPDATE);
+static VOID MakeListBoxString(LPSTR, LPSTR, OLEOPT_UPDATE);
+
+//*** MACROS ***
+
+#define END_PROP_DLG(hDlg,pLinks) { \
+ HANDLE handle; \
+ handle = LocalHandle((LPSTR)pLinks); \
+ LocalUnlock(handle); \
+ LocalFree(handle); \
+ Hourglass(FALSE); \
+ hwndProp = (HWND)NULL; \
+ EndDialog(hDlg, TRUE); \
+}
+
+#define CHANGE_LISTBOX_STRING(hwnd,i,pItem,lpLinkData) {\
+ char pString[CBMESSAGEMAX*4];\
+ MakeListBoxString(lpLinkData,pString,pItem->uoObject);\
+ SendMessage(hwndList,LB_DELETESTRING, i , 0L);\
+ SendMessage(hwndList,LB_INSERTSTRING, i , (long)((LPSTR)pString));\
+ SendMessage(hwndList,LB_SETSEL, 1, (long)i);\
+}
+
+#define CHECK_IF_STATIC(pItem) {\
+ if (pItem->otObject == OT_STATIC)\
+ continue;\
+}
+
+#define BLOCK_BUSY(fTest) {\
+ if (fTest)\
+ {\
+ fTest = FALSE;\
+ return TRUE;\
+ }\
+ if (cOleWait)\
+ {\
+ fTest = TRUE;\
+ RetryMessage(NULL,RD_CANCEL);\
+ fTest = FALSE;\
+ return TRUE;\
+ }\
+}
+
+
+
+
+
diff --git a/private/oleutest/ole1/clidemo/dirs b/private/oleutest/ole1/clidemo/dirs
new file mode 100644
index 000000000..606df65eb
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/dirs
@@ -0,0 +1,4 @@
+DIRS=
+OPTIONAL_DIRS= \
+ \
+ daytona
diff --git a/private/oleutest/ole1/clidemo/global.h b/private/oleutest/ole1/clidemo/global.h
new file mode 100644
index 000000000..f2cbabd8b
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/global.h
@@ -0,0 +1,108 @@
+/*
+ * global.h
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** CONSTANTS ***
+
+#define PROTOCOL_STRLEN 15 //* protocol name string size
+#define CFILTERMAX 20 //* Max # filters
+ //* Max # chars/filter
+#define CBFILTERMAX (100 * CFILTERMAX)
+#define CBPATHMAX 250 //* max qualified file name
+#define CBOBJNAMEMAX 14 //* maximum length of object name
+#define CBVERBTEXTMAX 30 //* maximum length of verb text
+#define CBVERBNUMBMAX 8 //* maximum number of verbs
+#define OBJECT_LINK_MAX 256*3 //* maximum size of object link data
+#define CDIGITSMAX 5
+#define KEYNAMESIZE 300 //* Maximum registration key length
+#define RETRY 3
+ //* protocol name strings
+#define STDFILEEDITING ((LPSTR)"StdFileEditing")
+#define STATICP ((LPSTR)"Static")
+ //* object name prefixes
+#define OBJPREFIX ((LPSTR)"CliDemo #")
+#define OBJCLONE ((LPSTR)"CliDemo1#")
+#define OBJTEMP ((LPSTR)"CliDemo2#")
+
+#define DOC_CLEAN 0 //* Dirty() methods
+#define DOC_DIRTY 1
+#define DOC_UNDIRTY 2
+#define DOC_QUERY 3
+
+#define OLE_OBJ_RELEASE FALSE //* object deletion type
+#define OLE_OBJ_DELETE TRUE
+
+#define WM_ERROR WM_USER + 1 //* user defined messages
+#define WM_INIT WM_USER + 2
+#define WM_DELETE WM_USER + 3
+#define WM_RETRY WM_USER + 4
+#define WM_CHANGE WM_USER + 5
+
+#define RD_CANCEL 0x00000001
+#define RD_RETRY 0x00000002
+
+//*** TYPES ***
+
+typedef struct _APPSTREAM FAR *LPAPPSTREAM;
+
+typedef struct _APPSTREAM {
+ OLESTREAM olestream;
+ INT fh;
+} APPSTREAM;
+
+typedef struct _APPITEM *APPITEMPTR;
+
+typedef struct _APPITEM { //* Application item
+ OLECLIENT oleclient;
+ HWND hwnd;
+ LPOLEOBJECT lpObject; //* OLE object pointers
+ LPOLEOBJECT lpObjectUndo; //* undo object
+ LONG otObject; //* OLE object type
+ LONG otObjectUndo;
+ OLEOPT_UPDATE uoObject; //* OLE object update option
+ OLEOPT_UPDATE uoObjectUndo; //* link name atom
+ ATOM aLinkName; //* Save the link's document name
+ ATOM aLinkUndo; //* Save the link's document name
+ LPSTR lpLinkData; //* pointer to link data
+ BOOL fVisible; //* TRUE: item is to be displayed
+ BOOL fOpen; //* server open? --for undo objects
+ BOOL fRetry; //* retry flag for busy servers
+ BOOL fNew;
+ BOOL fServerChangedBounds;
+ RECT rect; //* bounding rectangle
+ LHCLIENTDOC lhcDoc; //* client document handle
+ ATOM aServer;
+} APPITEM;
+
+
+typedef struct _RETRY *RETRYPTR;
+
+typedef struct _RETRY { //* Application item
+ LPSTR lpserver;
+ BOOL bCancel;
+ APPITEMPTR paItem;
+} RETRYSTRUCT;
+
+//*** GLOBALS ***
+
+extern OLECLIPFORMAT vcfLink; //* ObjectLink clipboard format
+extern OLECLIPFORMAT vcfNative; //* Native clipboard format
+extern OLECLIPFORMAT vcfOwnerLink; //* OwnerLink clipboard format
+
+extern HANDLE hInst; //* instance handle
+extern HWND hwndFrame; //* main window handle
+extern HANDLE hAccTable; //* accelerator table
+extern HWND hwndProp; //* link properties dialog
+extern HWND hRetry; //* retry dialog box handle
+extern INT cOleWait; //* wait for asyncc commands
+extern INT iObjects; //* object count
+extern INT iObjectNumber; //* unique name id
+extern CHAR szItemClass[]; //* item class name
+extern CHAR szDefExtension[]; //* default file extension
+extern CHAR szAppName[]; //* application name
+extern BOOL fLoadFile; //* load file flag
+extern CHAR szFileName[]; //* open file name
+extern FARPROC lpfnTimerProc; //* pointer to timer callback function
diff --git a/private/oleutest/ole1/clidemo/object.c b/private/oleutest/ole1/clidemo/object.c
new file mode 100644
index 000000000..5e8bc8583
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/object.c
@@ -0,0 +1,1177 @@
+/*
+ * object.c - OLE object support routines
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** INCLUDES ****
+
+#include <windows.h> //* WINDOWS
+#include <shellapi.h> //* SHELL
+#include <ole.h> //* OLE
+
+#include "global.h" //* global variables and structures
+#include "stream.h" //* application includes:
+#include "dialog.h"
+#include "object.h"
+#include "clidemo.h"
+#include "demorc.h"
+#include "utility.h"
+#include "register.h"
+
+#define HIMETRIC_PER_INCH 2540
+
+//*** VARIABLES ***
+
+//*** Globals
+INT cOleWait = 0;
+
+INT giXppli ;
+INT giYppli ;
+
+
+
+/***************************************************************************
+ * CallBack()
+ *
+ * This routine will be called whenever an object has been changed,
+ * saved, renamed, is being painted, or an asynchronous operation has
+ * completed. This routine is called by the OLE client DLL in the
+ * above situations. A pointer to this function is kept in the client
+ * vtbl. It is our obligation as a client application to insure that a
+ * pointer to this procedure is in the vtbl.
+ *
+ * IMMPORTANT: notice that we are posting messages here rather that doing
+ * the work right away. Well, this is done to avoid any possibility of
+ * getting into another dispatch message loop. A MessageBox woul do this!
+ *
+ * Returns int - see below
+ *
+ * The return value is generally ignored, except for these notifications:
+ * OLE_QUERY_PAINT and OLE_QUERY_RETRY. For these two notifications,
+ * returning TRUE means continue the current operation(eg painting or retry)
+ * Returning FALSE means stop the current operation. This is useful as an
+ * object which takes a long time to paint can be interrupted in order to
+ * perform other operations.
+ ***************************************************************************/
+
+INT APIENTRY CallBack( //* ENTRY:
+ LPOLECLIENT lpClient, //* client application pointer
+ OLE_NOTIFICATION flags, //* notification code being sent
+ LPOLEOBJECT lpObject //* OLE object pointer
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+
+
+ pItem = (APPITEMPTR)lpClient;
+ switch (flags)
+ {
+ case OLE_CLOSED: //* server has closed
+ if (!pItem->fVisible)
+ {
+ PostMessage(hwndFrame, WM_DELETE, 0L, (DWORD)pItem);
+ Dirty(DOC_UNDIRTY);
+ }
+ SetFocus( hwndFrame );
+ break;
+
+ case OLE_SAVED: //* server has saved object
+ case OLE_CHANGED: //* object has changes
+ cOleWait++;
+ pItem->fServerChangedBounds = pItem->fVisible = TRUE;
+ PostMessage(pItem->hwnd, WM_CHANGE, 0, 0L);
+ break;
+
+ case OLE_RELEASE: //* notification that an asynchronous
+ ToggleBlockTimer(FALSE); //* toggle timer off
+ if (hRetry)
+ PostMessage(hRetry,WM_COMMAND,IDCANCEL,0L);
+
+ if (cOleWait) //* operation has completed
+ {
+ pItem->fRetry = TRUE;
+ if (!--cOleWait)
+ Hourglass(FALSE);
+ Release(pItem);
+ }
+ break;
+
+ case OLE_QUERY_RETRY: //* Continue retrying.
+ ToggleBlockTimer(FALSE); //* toggle timer off
+ if (!hRetry && pItem->fRetry)
+ PostMessage(hwndFrame,WM_RETRY,0L, (DWORD)pItem);
+ return (pItem->fRetry);
+
+ case OLE_QUERY_PAINT: //* continue repainting
+ return TRUE; //* a false return terminates either
+
+ default:
+ break;
+ }
+ return 0; //* return value is ignored in
+ //* most cases, see header
+}
+
+/***************************************************************************
+ * Release()
+ *
+ * Check for an error on the OLE_RELEASE notification.
+ **************************************************************************/
+
+static VOID Release( //* ENTRY:
+ APPITEMPTR pItem //* Item pointer
+){ //* LOCAL:
+ DWORD wParam; //* error code parameter
+
+ if ((wParam = OleQueryReleaseError(pItem->lpObject)) == OLE_OK)
+ return;
+
+ switch (OleQueryReleaseMethod(pItem->lpObject))
+ {
+ case OLE_LNKPASTE:
+ pItem->fVisible = FALSE;
+ break;
+
+ case OLE_CREATEFROMTEMPLATE:
+ case OLE_CREATE:
+ pItem->fVisible = FALSE;
+ cOleWait++;
+ PostMessage(hwndFrame, WM_DELETE,1L, (DWORD)pItem);
+ Dirty(DOC_UNDIRTY);
+ }
+ //* post a message to the main window
+ //* which will display a message box
+ PostMessage(hwndFrame,WM_ERROR,wParam,0);
+
+}
+
+/***************************************************************************
+ * Error()
+ *
+ * This function checks for error conditions
+ * generated by OLE API callsFor OLE_WAIT_FOR_RELEASE,
+ * we keep track of the number of objects waiting, when
+ * this count is zero, it is safe to exit the application.
+ *
+ * Returns OLESTATUS - 0 if OLE_WAIT_FOR_RELEASE or OLE_OK
+ * otherwise the OLESTATUS returned after an action
+ * is taken.
+ *************************************************************************/
+
+OLESTATUS FAR Error( //* ENTRY
+ OLESTATUS olestat //* OLE status
+){
+
+ switch (olestat)
+ {
+ case OLE_WAIT_FOR_RELEASE:
+ if (!cOleWait)
+ Hourglass(TRUE);
+ cOleWait++; //* increment wait count
+
+ case OLE_OK:
+ return 0;
+
+ case OLE_ERROR_STATIC: //* static object
+ ErrorMessage(W_STATIC_OBJECT);
+ break;
+
+ case OLE_ERROR_REQUEST_PICT:
+ case OLE_ERROR_ADVISE_RENAME:
+ case OLE_ERROR_DOVERB:
+ case OLE_ERROR_SHOW:
+ case OLE_ERROR_OPEN:
+ case OLE_ERROR_NETWORK:
+ case OLE_ERROR_ADVISE_PICT:
+ case OLE_ERROR_COMM: //* Invalid links
+ InvalidLink();
+ break;
+
+ case OLE_BUSY:
+ RetryMessage(NULL,RD_CANCEL);
+
+ default:
+ break;
+ }
+ return olestat;
+}
+
+
+/****************************************************************************
+ * PreItemCreate()
+ *
+ * This routine allocates an application item structure. A pointer to this
+ * structure is passed as the client structure, therefore we need to
+ * have a pointer to the vtbl as the first entry. We are doing this
+ * to allow acess to the application item information during a OLE
+ * DLL callback. This approach simplifies matters.
+ *
+ * Returns APPITEMPTR - a pointer to a new application item structure
+ * which can operate as a client structure.
+ ***************************************************************************/
+
+APPITEMPTR FAR PreItemCreate( //* ENTRY:
+ LPOLECLIENT lpClient, //* OLE client pointer
+ BOOL fShow, //* show/no-show flag
+ LHCLIENTDOC lhcDoc //* client document handle
+){ //* LOCAL:
+ HANDLE hitem; //* temp handle for new item
+ APPITEMPTR pItem; //* application item pointer
+
+
+ if (hitem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, sizeof(APPITEM)))
+ if (pItem = (APPITEMPTR)LocalLock(hitem))
+ { //* set the vtbl pointer
+ pItem->oleclient.lpvtbl = lpClient->lpvtbl;
+ pItem->lpObjectUndo = NULL;
+ pItem->fVisible = fShow;
+ pItem->fServerChangedBounds = FALSE;
+ pItem->lhcDoc = lhcDoc;
+
+ return pItem; //* SUCCESS return
+ }
+
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ return NULL; //* ERROR return
+
+}
+
+
+/***************************************************************************
+ * ItemWndProc()
+ *
+ * This function handles item window message processing.
+ * There is an item window for each OLE object. This was done to
+ * to simplify hit testing and repainting. These windows are child
+ * windows.
+
+ * returns long - standard child routine
+ **************************************************************************/
+
+LONG APIENTRY ItemWndProc( //* ENTRY:
+ HWND hwnd, //* standard windows parameters
+ UINT msg,
+ DWORD wParam,
+ LONG lParam
+){ //* LOCAL:
+ static POINT dragPt; //* Mouse drag point
+ static RECT dragRect; //* Mouse drag rectangle
+ static BOOL fCaptured; //* captured flag
+ APPITEMPTR pItem; //* application item pointer
+ PAINTSTRUCT ps; //* paint structure
+ POINT pt; //* point
+ RECT rc; //* bounding rectangle
+// char lpstr[256];
+
+ switch (msg)
+ {
+ case WM_SIZE:
+ if (pItem = (APPITEMPTR)GetWindowLong(hwnd,0))
+ {
+ if (!pItem->fServerChangedBounds && pItem->otObject == OT_EMBEDDED)
+ ObjSetBounds(pItem);
+ else
+ pItem->fServerChangedBounds = FALSE;
+ }
+ break;
+
+ case WM_CHANGE:
+ --cOleWait;
+ pItem = (APPITEMPTR)GetWindowLong(hwnd,0);
+ if (!Error(OleQueryBounds(pItem->lpObject, &rc)))
+ {
+ ConvertToClient(&rc);
+
+ SetWindowPos(
+ hwnd,
+ NULL,
+ 0,
+ 0,
+ rc.right - rc.left + 2*GetSystemMetrics(SM_CXFRAME),
+ rc.bottom - rc.top + 2*GetSystemMetrics(SM_CYFRAME),
+ SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
+ );
+
+ if (!pItem->fNew && !fLoadFile)
+ ShowNewWindow(pItem);
+ else
+ InvalidateRect(hwnd, NULL, TRUE);
+
+ Dirty(DOC_DIRTY);
+ }
+ break;
+
+ case WM_NCLBUTTONDOWN:
+ SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
+ return (DefWindowProc(hwnd, msg, wParam, lParam));
+
+ case WM_PAINT:
+ BeginPaint(hwnd, (LPPAINTSTRUCT)&ps);
+ GetClientRect(hwnd, &rc);
+ pItem = (APPITEMPTR)GetWindowLong(hwnd, 0);
+ //* Call OLE draw
+ Error(OleDraw(pItem->lpObject, ps.hdc, &rc, NULL, NULL));
+
+ EndPaint(hwnd, (LPPAINTSTRUCT)&ps);
+ break;
+
+ case WM_LBUTTONDBLCLK: //* execute a verb
+ ANY_OBJECT_BUSY;
+ ExecuteVerb(OLEVERB_PRIMARY,(APPITEMPTR)GetWindowLong(hwnd,0));
+ break;
+
+ case WM_LBUTTONDOWN:
+ GetWindowRect(hwnd, (LPRECT)&dragRect);
+ ScreenToClient(hwndFrame, (LPPOINT)&dragRect);
+ ScreenToClient(hwndFrame, (LPPOINT)&dragRect.right);
+
+ dragPt.x = (LONG)(SHORT)LOWORD(lParam);
+ dragPt.y = (LONG)(SHORT)HIWORD(lParam);
+
+ ClientToScreen(hwnd, (LPPOINT)&dragPt);
+ ScreenToClient(hwndFrame, (LPPOINT)&dragPt);
+
+ SetCapture(hwnd);
+ fCaptured = TRUE;
+ SetTopItem((APPITEMPTR)GetWindowLong(hwnd,0));
+ break;
+
+ case WM_LBUTTONUP:
+ if (!fCaptured)
+ break;
+ ReleaseCapture();
+ fCaptured = FALSE;
+ Dirty(DOC_DIRTY);
+ break;
+
+ case WM_MOUSEMOVE:
+ if (!fCaptured)
+ break;
+ pt.x = (LONG)(SHORT)LOWORD(lParam);
+ pt.y = (LONG)(SHORT)HIWORD(lParam);
+
+ ClientToScreen(hwnd, (LPPOINT)&pt);
+ ScreenToClient(hwndFrame, (LPPOINT)&pt);
+
+ OffsetRect(
+ (LPRECT)&dragRect,
+ pt.x - dragPt.x,
+ pt.y - dragPt.y
+ );
+
+ MoveWindow(
+ hwnd,
+ dragRect.left, dragRect.top,
+ dragRect.right - dragRect.left,
+ dragRect.bottom - dragRect.top, TRUE
+ );
+
+ dragPt.x = pt.x;
+ dragPt.y = pt.y;
+ break;
+
+ default:
+ return (DefWindowProc(hwnd, msg, wParam, lParam));
+ }
+ return 0L;
+
+}
+
+/****************************************************************************
+ * PostItemCreate()
+ *
+ * This function creates a child window which will contain the newly
+ * created OLE object. A pointer to our item information is stored in the
+ * extra bytes of this window. This is where we internally keep track
+ * of information related to the object as well as the
+ * pointer to the object for subsequent OLE API calls. This routine is
+ * called after an OLE object has been created by the client library.
+ *
+ * Returns BOOL - TRUE if application item has been created.
+ ****************************************************************************/
+
+BOOL FAR PostItemCreate( //* ENTRY:
+ LPOLEOBJECT lpObject, //* OLE object pointer
+ LONG otObject, //* OLE object type
+ LPRECT lprcObject, //* object bounding rect
+ APPITEMPTR pItem //* application item pointer
+){ //* LOCAL:
+ INT i; //* index
+ RECT rc; //* bounding rectangle
+ CHAR pData[OBJECT_LINK_MAX];//* copy of link data
+
+ if (lprcObject) //* if the size of the objects
+ rc = *lprcObject; //* bounding rectangle is not
+ else if (OleQueryBounds(lpObject, &rc) == OLE_OK)
+ ConvertToClient(&rc);
+ else
+ SetRect(&rc, 0, 0, 0, 0);
+
+ if (!(pItem->hwnd = CreateWindow( //* Create the child window
+ szItemClass, "",
+ WS_BORDER | WS_CHILD | WS_CLIPSIBLINGS | WS_THICKFRAME,
+ rc.left,rc.top,
+ rc.right - rc.left + 2 * GetSystemMetrics(SM_CXFRAME),
+ rc.bottom - rc.top + 2 * GetSystemMetrics(SM_CYFRAME),
+ hwndFrame, NULL, hInst, NULL
+ ))) goto Error;
+
+ //* in windows extra bytes
+ SetWindowLong(pItem->hwnd, 0, (LONG)pItem);
+
+ pItem->otObject = otObject;
+ pItem->lpObject = lpObject;
+ pItem->fRetry = TRUE;
+
+ if( pItem->otObject == OT_EMBEDDED )//* if object is embedded tell library
+ { //* the container name and object name.
+ UINT cb=CBOBJNAMEMAX; //* The name will be the server window title.
+ CHAR sz[CBOBJNAMEMAX]; //* when the object is edited.
+
+ OleQueryName(lpObject, (LPSTR)sz, (UINT FAR *)&cb );
+
+
+ WaitForObject(pItem);
+ Error(OleSetHostNames(lpObject, (LPSTR)szAppName, (LPSTR)sz ));
+ WaitForObject(pItem);
+ }
+ else if (pItem->otObject == OT_LINK)//* if the object is linked
+ { //* retrieve update options
+
+ WaitForObject(pItem);
+ if(Error(OleGetLinkUpdateOptions(pItem->lpObject, &pItem->uoObject)))
+ goto Error;
+
+ if (ObjGetData(pItem,pData))
+ {
+ for (i=0; pData[i];i++); //* Skip past the server name
+ pItem->aLinkName = AddAtom(&pData[++i]);
+ }
+ else
+ pItem->aLinkName = AddAtom("");
+ }
+ iObjects++;
+ Dirty(DOC_DIRTY);
+ //* a user interface recommendations.
+ return TRUE; //* SUCCESS return
+
+Error: //* ERROR Tag
+
+ ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
+ FreeAppItem(pItem);
+
+ return FALSE; //* ERROR return
+
+}
+
+/***************************************************************************
+ * ConvertToClient()
+ *
+ * This function will convert to client from himetric.
+ **************************************************************************/
+
+VOID FAR ConvertToClient( //* ENTRY:
+ LPRECT lprc //* pointer to bounding rectangle
+){ //* LOCAL
+
+ //* If we have an empty rectangle then set the default size
+ if (!(lprc->left || lprc->top || lprc->right || lprc->bottom))
+ SetRect(lprc, 0, 0, CXDEFAULT, CYDEFAULT);
+ else
+ {
+ //* We got the himetric units, converts them to pixels now.
+ lprc->right = MulDiv (giXppli, (lprc->right - lprc->left),
+ HIMETRIC_PER_INCH);
+
+ lprc->bottom = MulDiv (giYppli, (lprc->top - lprc->bottom),
+ HIMETRIC_PER_INCH);
+
+ lprc->left = 0;
+ lprc->top = 0;
+ }
+}
+
+/***************************************************************************
+ * ObjInsert()
+ *
+ * Query the user for object type to insert and insert the new OLE object
+ ***************************************************************************/
+
+VOID FAR ObjInsert( //* ENTRY:
+ LHCLIENTDOC lhcDoc, //* OLE document handle
+ LPOLECLIENT lpClient //* pointer to OLE client structure
+){ //* LOCAL:
+ LPOLEOBJECT lpObject; //* pointer to OLE object
+ APPITEMPTR pItem; //* item pointer
+ CHAR szServerName[CBPATHMAX];//* Class name for OleCreate()
+ CHAR szClassName[CBPATHMAX];//* Class name for OleCreate()
+ CHAR szTmp[CBOBJNAMEMAX]; //* buffer to unique object name
+
+ if (DialogBoxParam(hInst, MAKEINTRESOURCE(DTCREATE),hwndFrame,
+ (DLGPROC) fnInsertNew, (LONG)((LPSTR)szClassName)) != IDCANCEL)
+ {
+ if (pItem = PreItemCreate(lpClient, FALSE, lhcDoc))
+ {
+ RegGetClassId(szServerName, szClassName);
+ pItem->aServer = AddAtom(szServerName);
+ if ( Error( OleCreate(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),
+ (LPSTR)szClassName, lhcDoc,CreateNewUniqueName(szTmp),
+ &lpObject,olerender_draw, 0)))
+ {
+ ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
+ FreeAppItem(pItem);
+ }
+ else
+ PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
+ }
+ }
+
+
+}
+
+/***************************************************************************
+ * ObjDelete()
+ *
+ * Delete an OLE object. For this application, all OLE objects
+ * are associated with a child window; therefore the window must be
+ * destroyed.
+ *
+ * NOTE: There is one case when we call OleRelease and the other when
+ * we call OleDelete. We call OleRelease when we are deregistering
+ * a document and OleDelete when removing an object from a document.
+ **************************************************************************/
+
+VOID FAR ObjDelete( //* ENTRY:
+ APPITEMPTR pItem, //* pointer to application item
+ BOOL fDelete //* delete or release flag
+){ //* LOCAL:
+
+ if (pItem->lpObjectUndo)
+ {
+ Error(OleDelete(pItem->lpObjectUndo));
+ //* wait for asynchronous operation
+ WaitForObject(pItem);
+ }
+
+ if (fDelete ? Error(OleDelete(pItem->lpObject))
+ : Error(OleRelease(pItem->lpObject)))
+ {
+ ErrorMessage(E_FAILED_TO_DELETE_OBJECT);
+ return; //* ERROR return
+ }
+
+ if (pItem->fVisible)
+ {
+ ShowWindow(pItem->hwnd, SW_HIDE);
+ pItem->fVisible = FALSE;
+ }
+ //* the operation has to complete
+ WaitForObject(pItem); //* before the application structure
+
+ FreeAppItem(pItem);
+ iObjects--;
+
+}
+
+
+/***************************************************************************
+ * ObjPaste()
+ *
+ * This function obtains an object from the clipboard.
+ * Handles both embedded and linked objects. An item window is
+ * created for each new object.
+ *
+ * Returns BOOL - TRUE if object was pasted succesfully.
+ **************************************************************************/
+
+VOID FAR ObjPaste( //* ENTRY:
+ BOOL fPaste, //* Paste/PasteLink flag
+ LHCLIENTDOC lhcDoc, //* client document handle
+ LPOLECLIENT lpClient //* pointer to client
+){ //* LOCAL:
+ LPOLEOBJECT lpObject; //* object pointer
+ LONG otObject; //* object type
+ APPITEMPTR pItem; //* application item pointer
+ CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
+
+ if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
+ return; //* ERROR return
+
+ if (!OpenClipboard(hwndFrame))
+ goto Error; //* ERROR jump
+
+
+ if (fPaste) //* PASTE the object.
+ { //* Try "StdFileEditing" protocol
+ if (Error(OleCreateFromClip(STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient),lhcDoc,
+ CreateNewUniqueName(szTmp),&lpObject, olerender_draw,0)))
+ {
+ //* next try "Static" protocol
+ if (Error(OleCreateFromClip(
+ STATICP, (LPOLECLIENT)&(pItem->oleclient), lhcDoc,
+ CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
+ goto Error; //* ERROR jump
+ }
+ }
+ else
+ { //* LINK therefore must be
+ // "STdFileEditing" protocol
+ if (Error(OleCreateLinkFromClip(
+ STDFILEEDITING,(LPOLECLIENT)&(pItem->oleclient), lhcDoc,
+ CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
+ goto Error; //* ERROR jump
+ }
+
+ OleQueryType(lpObject, &otObject);
+ CloseClipboard();
+
+ if (!PostItemCreate(lpObject, otObject, NULL, pItem))
+ return; //* ERROR return
+
+ ShowNewWindow(pItem);
+ return; //* SUCCESS return
+
+
+Error: //* TAG Error
+
+ ErrorMessage(E_GET_FROM_CLIPBOARD_FAILED);
+ CloseClipboard();
+ FreeAppItem(pItem);
+
+ return; //* ERROR return
+
+}
+
+/***************************************************************************
+ * ObjCopy()
+ *
+ * This function places an OLE object on the clipboard via the \
+ * OleCopyToClipboard() function.
+ *
+ * Returns BOOL - TRUE if object successfully placed on clipboard
+ **************************************************************************/
+
+BOOL FAR ObjCopy( //* ENTRY:
+ APPITEMPTR pItem //* pointer to app item
+){ //* LOCAL:
+ BOOL fReturn = TRUE; //* return value
+
+ if (!OpenClipboard(hwndFrame))
+ return FALSE; //* ERROR return
+
+ EmptyClipboard();
+
+ if (Error(OleCopyToClipboard(pItem->lpObject)))
+ fReturn = FALSE; //* prepare for ERROR out
+
+ CloseClipboard();
+ return fReturn; //* ERROR or SUCCESS
+
+}
+
+/***************************************************************************
+ * ObjCreateFromTemplate()
+ *
+ * Creates an embedded object from file.
+ **************************************************************************/
+
+VOID FAR ObjCreateFromTemplate( //* ENTRY:
+ LHCLIENTDOC lhcDoc, //* client document handle
+ LPOLECLIENT lpClient //* client vtbl. pointer
+){ //* LOCAL:
+ LPOLEOBJECT lpObject; //* OLE object pointer
+ APPITEMPTR pItem; //* application item pointer
+ CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name string
+ CHAR szFileName[CBPATHMAX];//* file name string
+
+ *szFileName = 0;
+
+ if (!OfnGetName(hwndFrame, szFileName, IDM_INSERTFILE))
+ return; //* ERROR operation aborted by user
+
+ if (!(pItem = PreItemCreate(lpClient, FALSE, lhcDoc)))
+ return; //* ERROR
+
+ if (Error(OleCreateFromTemplate(STDFILEEDITING, (LPOLECLIENT)pItem, szFileName,
+ lhcDoc, CreateNewUniqueName(szTmp), &lpObject, olerender_draw, 0)))
+ {
+ ErrorMessage(E_CREATE_FROM_TEMPLATE);
+ FreeAppItem(pItem);
+ return; //* ERROR
+ }
+
+ PostItemCreate(lpObject, OT_EMBEDDED, NULL, pItem);
+
+} //* SUCCESS
+
+
+/****************************************************************************
+ * ObjGetData()
+ *
+ * Get the object link data. The data that is retrieved from OLE is copied
+ * into lpLinkData if lpLinkData is not NULL. Otherwise, space is dynamically
+ * allocated or reallocated; space is allocated if pItem->lpLinkData is NULL
+ * otherwise the pointer is reallocated. The data is returned is freed if
+ * there has been an OLE_WARN_DELETE_DATA error.
+ ***************************************************************************/
+
+BOOL FAR ObjGetData( //* ENTRY:
+ APPITEMPTR pItem, //* OLE object
+ LPSTR lpLinkData //* pointer to linkdata
+){ //* LOCAL:
+ HANDLE hData; //* handle to OLE link data
+ LPSTR lpData; //* pointer to OLE link data
+ LPSTR lpWork; //* copy of OLE link data
+ BOOL fFree = FALSE; //* free OLE memory flag
+ LONG lSize; //* size of OLE link data
+ INT i;
+
+ switch (Error(OleGetData(pItem->lpObject,
+ (OLECLIPFORMAT)(pItem->otObject == OT_LINK ? vcfLink : vcfOwnerLink), &hData)))
+ {
+ case OLE_WARN_DELETE_DATA:
+ fFree = TRUE;
+ case OLE_OK:
+ if(lpData = GlobalLock(hData))
+ {
+ //* copy the link data to new buffer
+ lSize=SizeOfLinkData(lpData);
+
+ if (!lpLinkData)
+ {
+ if (!pItem->lpLinkData) //* allocate
+ AllocLinkData(pItem,lSize);
+ else //* otherwise reallocate
+ ReallocLinkData(pItem,lSize);
+ lpWork = pItem->lpLinkData;
+ }
+ else
+ lpWork = lpLinkData;
+
+ if (lpWork)
+ for (i=0L; i<(INT)lSize; i++)
+ *(lpWork+i)=*(lpData+i);
+
+ GlobalUnlock(hData); //* free the linked data as needed
+ if (fFree)
+ GlobalFree(hData);
+
+ return TRUE; //* SUCCESS
+ }
+ default:
+ return FALSE; //* FAILURE
+ }
+
+}
+
+/***************************************************************************
+ * ObjChangeLink()
+ *
+ * Change the linkdata. This routine will change the document portion of
+ * link data to lpDoc. The old linkdata is expected to be in
+ * lpaItem->lpLinkData
+ **************************************************************************/
+
+VOID FAR ObjChangeLinkData( //* ENTRY:
+ APPITEMPTR pItem, //* OLE object
+ LPSTR lpDoc //* document name
+){ //* LOCAL:
+ LONG lSize; //* used to link data size
+ LPSTR lpLinkData; //* OLE link data pointer
+ static CHAR pWork[OBJECT_LINK_MAX]; //* used to construct new link data
+ INT i; //* index
+ HANDLE hData;
+
+ pItem->aLinkName = AddAtom(lpDoc);
+
+ for (
+ lpLinkData = pItem->lpLinkData, i=0;
+ pWork[i] = *lpLinkData;
+ lpLinkData++, i++
+ );
+ //* into working buffer.
+ lstrcpy((LPSTR)&pWork[++i],lpDoc); //* copy new document name.
+
+ for (; pWork[i]; i++); //* skip to end of document name
+ for (++lpLinkData;*lpLinkData;lpLinkData++);
+ //* copy item name.
+ lstrcpy((LPSTR)&pWork[++i],++lpLinkData);
+ for (; pWork[i]; i++); //* skip to end of buffer
+ //* which is the end of item info.
+ pWork[++i] = 0; //* add extra null.
+
+ lSize = SizeOfLinkData(pWork); //* reallocate space so there is
+ ReallocLinkData(pItem,lSize); //* a properly sized block of info
+ //* to send the linked data to the
+ if (lpLinkData = pItem->lpLinkData) //* OLE DLL.
+ for (i=0; i<(INT)lSize; i++) //* copy new linkdata into this space
+ *lpLinkData++ = pWork[i];
+ else
+ return; //* ERROR return
+
+ Error(OleSetData(pItem->lpObject, vcfLink, GlobalHandle(pItem->lpLinkData)));
+
+ /*
+ * The handle passed into OleSetData is owned by the OLE client library
+ * and should not be used after the call. On win32s, it is inaccessible
+ * after the call, so restore it by calling OleGetData. Note that the
+ * data is *still* owned by the library, but we will now have access
+ * to the memory.
+ */
+ Error(OleGetData(pItem->lpObject, vcfLink, &hData));
+ if (hData) {
+ pItem->lpLinkData = GlobalLock(hData);
+ }
+} //* SUCCESS return
+
+/****************************************************************************
+ * ObjSaveUndo()
+ *
+ * Clone the OLE object so that any changes to object can be undone if the
+ * user choses to exit without update.
+ ***************************************************************************/
+
+VOID FAR ObjSaveUndo( //* ENTRY:
+ APPITEMPTR pItem //* application item
+){ //* LOCAL:
+ CHAR szTmp[CBOBJNAMEMAX]; //* holder of object name
+ LPSTR lpClone; //* pointer to clond object name
+ UINT i=CBOBJNAMEMAX;
+
+ if (!pItem->lpObjectUndo)
+ {
+ OleQueryName(pItem->lpObject, szTmp, &i);
+ //* give clone a unique name by
+ //* altering object name prefix.
+ for (lpClone = OBJCLONE, i=0; *lpClone; szTmp[i++] = *lpClone++);
+
+ if (Error(OleClone(pItem->lpObject, (LPOLECLIENT)pItem,
+ pItem->lhcDoc, szTmp, &(pItem->lpObjectUndo))))
+ return; //* ERROR return
+
+ pItem->otObjectUndo = pItem->otObject;
+ pItem->uoObjectUndo = pItem->uoObject;
+ pItem->aLinkUndo = pItem->aLinkName;
+
+ GetClientRect(pItem->hwnd, &pItem->rect);
+
+ if (OleQueryOpen(pItem->lpObject) == OLE_OK)
+ pItem->fOpen = TRUE;
+
+ }
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * ObjUndo()
+ *
+ * Restore an object to its state before changes. The lpObject Undo is a
+ * clone to the original object with a different name, therefore, all we
+ * have to do is rename that object and ditch the changed object.
+ ***************************************************************************/
+
+VOID FAR ObjUndo( //* ENTRY:
+ APPITEMPTR pItem //* application item
+){ //* LOCAL:
+ CHAR szTmp[CBOBJNAMEMAX]; //* object name holder
+ UINT i = CBOBJNAMEMAX;
+
+ OleQueryName(pItem->lpObject, szTmp, &i);
+ if (Error(OleDelete(pItem->lpObject)))
+ return; //* ERROR return
+ //* reset app item vars
+ pItem->lpObject = pItem->lpObjectUndo;
+ pItem->otObject = pItem->otObjectUndo;
+ pItem->uoObject = pItem->uoObjectUndo;
+ pItem->aLinkName = pItem->aLinkUndo;
+ pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
+ pItem->otObjectUndo = (LONG)NULL;
+
+ if (Error(OleRename(pItem->lpObject,szTmp)))
+ return; //* ERROR return
+
+ if (pItem->fOpen)
+ {
+ Error(OleReconnect(pItem->lpObject));
+ pItem->fOpen = FALSE;
+ }
+
+ SetWindowPos(
+ pItem->hwnd,
+ NULL, 0, 0,
+ pItem->rect.right - pItem->rect.left + 2*GetSystemMetrics(SM_CXFRAME),
+ pItem->rect.bottom - pItem->rect.top + 2*GetSystemMetrics(SM_CYFRAME),
+ SWP_NOZORDER | SWP_NOMOVE | SWP_DRAWFRAME
+ );
+
+ InvalidateRect(pItem->hwnd,NULL,TRUE);
+
+} //* SUCCESS return
+
+
+/****************************************************************************
+ * ObjDelUndo()
+ *
+ * Delete the undo object if the user is happy with the changes he/she made.
+ ***************************************************************************/
+
+VOID FAR ObjDelUndo( //* ENTRY:
+ APPITEMPTR pItem //* application item
+){
+
+ if (Error(OleDelete(pItem->lpObjectUndo)))
+ return; //* ERROR return
+
+ pItem->lpObjectUndo = (LPOLEOBJECT)NULL;
+ pItem->otObjectUndo = (LONG)NULL;
+ DeleteAtom(pItem->aLinkUndo);
+ pItem->lpObjectUndo = NULL;
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * ObjFreeze()
+ *
+ * Convert an object to a static object.
+ ***************************************************************************/
+
+VOID FAR ObjFreeze( //* ENTRY:
+ APPITEMPTR pItem //* application item
+){ //* LOCAL:
+ CHAR szTmp[CBOBJNAMEMAX]; //* temporary object name
+ LPSTR lpTemp; //* temporary prefix string
+ LPOLEOBJECT lpObjectTmp; //* temporary object pointer
+ UINT i=CBOBJNAMEMAX;
+
+ OleQueryName(pItem->lpObject, szTmp, &i);
+ //* create a unique name by changing
+ //* the object name prefix
+ for (lpTemp = OBJTEMP, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
+
+ //* this API creates a static object
+ if (Error(OleObjectConvert(pItem->lpObject, STATICP, (LPOLECLIENT)pItem,
+ pItem->lhcDoc, szTmp, &lpObjectTmp)))
+ return;
+ //* delete old object
+ if (Error(OleDelete(pItem->lpObject)))
+ return;
+
+ WaitForObject(pItem);
+
+ pItem->lpObject = lpObjectTmp;
+ pItem->otObject = OT_STATIC;
+ pItem->uoObject = -1L;
+
+ for (lpTemp = OBJPREFIX, i=0; *lpTemp; szTmp[i++] = *lpTemp++);
+ if (Error(OleRename(pItem->lpObject,szTmp)))
+ return;
+
+
+}
+
+/***************************************************************************
+ * ObjCreateWrap()
+ *
+ * Create a wrapped object from the drag and drop feature of the 3.1 shell.
+ * NOTE: We are assuming that only one file has been dropped. See the SDK
+ * documentation for instructions on how to deal with multiple files.
+ ***************************************************************************/
+
+VOID FAR ObjCreateWrap( //* ENTRY:
+ HANDLE hdrop, //* handle to dropped object
+ LHCLIENTDOC lhcDoc, //* document handle
+ LPOLECLIENT lpClient //* pointer to client structure
+){ //* LOCAL:
+ CHAR szDragDrop[CBPATHMAX];//* Drag and drop file name
+ LPOLEOBJECT lpObject; //* pointer to OLE object
+ POINT pt; //* position of dropped object
+ RECT rc; //* object size and position
+ CHAR szTmp[CBOBJNAMEMAX]; //* buffer for unique object name
+ APPITEMPTR pItem; //* application item pointer
+ INT x,y; //* icon sizes
+
+ x = GetSystemMetrics(SM_CXICON) / 2;
+ y = GetSystemMetrics(SM_CYICON) / 2;
+ //* Get the drag and drop filename
+ //* position
+ DragQueryPoint(hdrop, &pt);
+ DragQueryFile(hdrop, 0, szDragDrop, CBPATHMAX);
+ DragFinish(hdrop);
+
+ SetRect(&rc, pt.x - x, pt.y - y, pt.x + x, pt.y + y);
+
+ if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
+ return; //* ERROR return
+ //* create OLE object
+ if (Error(OleCreateFromFile(STDFILEEDITING, (LPOLECLIENT)pItem,
+ "Package", szDragDrop, lhcDoc, CreateNewUniqueName(szTmp),
+ &lpObject, olerender_draw, 0)))
+ {
+ ErrorMessage(E_FAILED_TO_CREATE_OBJECT);
+ FreeAppItem(pItem);
+ return; //* ERROR return
+ }
+
+ if (PostItemCreate(lpObject, OT_EMBEDDED, &rc, pItem))
+ ShowNewWindow(pItem);
+
+} //* SUCCESS return
+
+/***************************************************************************
+ * UpdateObjectMenuItem()
+ *
+ * Add an object popup menu for the chosen object if multiple verbs exist.
+ * The registration system is used to determine which verbs exist for the
+ * given object.
+ **************************************************************************/
+
+VOID FAR UpdateObjectMenuItem( //* ENTRY:
+ HMENU hMenu //* main menu
+){ //* LOCAL
+ INT cVerbs; //* verb
+ APPITEMPTR pItem; //* application item ponter
+ DWORD dwSize = KEYNAMESIZE;
+ CHAR szClass[KEYNAMESIZE], szBuffer[200];
+ CHAR szVerb[KEYNAMESIZE];
+ HMENU hPopupNew=NULL;
+ HKEY hkeyTemp;
+ CHAR pLinkData[OBJECT_LINK_MAX];
+ //* delete current item and submenu
+ DeleteMenu(hMenu, POS_OBJECT, MF_BYPOSITION );
+
+ if (!(pItem = GetTopItem()) )
+ goto Error; //* ERROR jump
+ else if (!pItem->fVisible)
+ goto Error; //* ERROR jump
+ //* if STATIC ?
+ if ((pItem->otObject != OT_EMBEDDED) && (pItem->otObject != OT_LINK))
+ goto Error; //* ERROR jump
+
+ if (!ObjGetData(pItem, pLinkData)) //* get linkdata as key reg database
+ goto Error; //* ERROR jump
+ //* open reg database
+ szClass[0] = 0;
+ if (RegOpenKey(HKEY_CLASSES_ROOT, szClass, &hkeyTemp))
+ goto Error; //* ERROR jump
+ //* check if class is reg-db
+ if (RegQueryValue(HKEY_CLASSES_ROOT, pLinkData, szClass, &dwSize))
+ {
+ RegCloseKey(hkeyTemp);
+ goto Error; //* ERROR jump
+ }
+
+ for (cVerbs=0; ;++cVerbs) //* extract all verbs from reg-db
+ {
+ dwSize = KEYNAMESIZE;
+ wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d",
+ (LPSTR)pLinkData,cVerbs);
+
+ if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
+ break;
+
+ if (!hPopupNew)
+ hPopupNew = CreatePopupMenu();
+
+ InsertMenu(hPopupNew, (UINT)-1, MF_BYPOSITION, IDM_VERBMIN+cVerbs, szVerb);
+ }
+
+ //* NOTE: For International versions the following verb menu
+ //* may need to be formatted differently.
+
+ switch (cVerbs) //* determine how many verbs found
+ {
+ case 0: //* none
+ wsprintf(szBuffer, "Edit %s %s", (LPSTR)szClass, (LPSTR)"&Object");
+ InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
+ break;
+
+ case 1: //* one
+ wsprintf(szBuffer, "%s %s %s", (LPSTR)szVerb, (LPSTR)szClass,
+ (LPSTR)"&Object");
+ DestroyMenu(hPopupNew);
+ InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, IDM_VERBMIN, szBuffer);
+ break;
+
+ default: //* > 1
+ wsprintf(szBuffer, "%s %s", (LPSTR)szClass, (LPSTR)"&Object");
+ InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION | MF_POPUP, (UINT)hPopupNew, szBuffer);
+ EnableMenuItem(hMenu, POS_OBJECT, MF_ENABLED|MF_BYPOSITION);
+ break;
+ }
+
+ RegCloseKey(hkeyTemp); //* close reg-db
+ return; //* SUCCESS return
+
+Error: //* ERROR tag
+ InsertMenu(hMenu, POS_OBJECT, MF_BYPOSITION, 0, "&Object");
+ EnableMenuItem(hMenu, POS_OBJECT, MF_GRAYED | MF_BYPOSITION);
+
+} //* ERROR return
+
+/***************************************************************************
+ * ExecuteVerb()
+ *
+ * Execute the verb for the given object.
+ ***************************************************************************/
+
+VOID FAR ExecuteVerb( //* ENTRY:
+ UINT iVerb, //* verb
+ APPITEMPTR pItem //* application item pointer
+){ //* LOCAL
+ RECT rc; //* holds client area bounding rect
+
+ if (pItem->otObject == OT_STATIC) //* if the object is static beep
+ {
+ ErrorMessage(W_STATIC_OBJECT);
+ return; //* return
+ }
+ //* get cliet area rectangle
+ GetClientRect(hwndFrame, (LPRECT)&rc);
+ //* execute OLE verb
+ if (Error(OleActivate(pItem->lpObject, iVerb, TRUE, TRUE, hwndFrame, &rc)))
+ return;
+
+ WaitForObject(pItem); //* wait for async. operation
+
+ ObjSetBounds(pItem);
+
+
+} //* SUCCESS return
+
+/****************************************************************************
+ * ObjSetBounds
+ *
+ * Set the object bounds. The object bounds are the child windos bounding
+ * rectangle. OLE servers recieve need the bounding rectangle in HIMETRIC
+ * coordinates. So, we convert from screen coordinates to HIMETRIC.
+ *
+ * Returns BOOL - TRUE if successful.
+ ***************************************************************************/
+BOOL FAR ObjSetBounds( //* ENTRY:
+ APPITEMPTR pItem //* application item pointer
+){ //* LOCAL:
+ RECT itemRect; //* bounding rectangle
+
+ GetWindowRect(pItem->hwnd,&itemRect);//* get item window react
+
+ itemRect.right -= GetSystemMetrics(SM_CXFRAME);
+ itemRect.left += GetSystemMetrics(SM_CXFRAME);
+ itemRect.top += GetSystemMetrics(SM_CYFRAME);
+ itemRect.bottom -= GetSystemMetrics(SM_CYFRAME);
+
+ itemRect.right = MulDiv ((itemRect.right - itemRect.left),
+ HIMETRIC_PER_INCH, giXppli);
+ itemRect.bottom = - MulDiv((itemRect.bottom - itemRect.top),
+ HIMETRIC_PER_INCH, giYppli);
+ itemRect.top = 0;
+ itemRect.left = 0;
+ //* set the rect for the server
+ if (Error(OleSetBounds(pItem->lpObject,(LPRECT)&itemRect)))
+ return FALSE; //* ERROR return
+
+ WaitForObject(pItem); //* wait for async. operation
+ return TRUE; //* SUCCESS return
+
+}
+
diff --git a/private/oleutest/ole1/clidemo/object.h b/private/oleutest/ole1/clidemo/object.h
new file mode 100644
index 000000000..e928d9882
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/object.h
@@ -0,0 +1,40 @@
+/*
+ * object.h
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** PROTOTYPES ***
+
+//* OLE Callbacks
+
+INT APIENTRY CallBack(LPOLECLIENT, OLE_NOTIFICATION, LPOLEOBJECT);
+
+//* Exported Windows procedures
+
+LONG APIENTRY ItemWndProc(HWND, UINT, DWORD, LONG);
+
+//* Far
+VOID FAR ObjDelete(APPITEMPTR, BOOL);
+VOID FAR ConvertToClient(LPRECT);
+OLESTATUS FAR Error(OLESTATUS);
+APPITEMPTR FAR PreItemCreate(LPOLECLIENT, BOOL, LHCLIENTDOC);
+BOOL FAR PostItemCreate(LPOLEOBJECT, LONG, LPRECT, APPITEMPTR);
+VOID FAR ObjPaste(BOOL, LHCLIENTDOC, LPOLECLIENT);
+BOOL FAR ObjCopy(APPITEMPTR);
+BOOL FAR ObjGetData (APPITEMPTR, LPSTR);
+VOID FAR ObjChangeLinkData(APPITEMPTR, LPSTR);
+VOID FAR ObjSaveUndo(APPITEMPTR);
+VOID FAR ObjDelUndo(APPITEMPTR);
+VOID FAR ObjUndo(APPITEMPTR);
+VOID FAR ObjFreeze(APPITEMPTR);
+VOID FAR ObjInsert(LHCLIENTDOC, LPOLECLIENT);
+VOID FAR ObjCreateFromTemplate(LHCLIENTDOC, LPOLECLIENT);
+VOID FAR ObjCreateWrap(HANDLE, LHCLIENTDOC, LPOLECLIENT);
+VOID FAR UpdateObjectMenuItem(HMENU);
+VOID FAR ExecuteVerb(UINT, APPITEMPTR);
+
+//* Local
+static VOID Release(APPITEMPTR);
+BOOL FAR ObjSetBounds(APPITEMPTR);
diff --git a/private/oleutest/ole1/clidemo/register.c b/private/oleutest/ole1/clidemo/register.c
new file mode 100644
index 000000000..9a7b7ae90
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/register.c
@@ -0,0 +1,196 @@
+/*
+ * register.c - Handles the Win 3.1 registration library.
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** INCLUDES ***
+
+#include <windows.h>
+#include <ole.h>
+
+#include "global.h"
+#include "register.h"
+#include "clidemo.h"
+#include "demorc.h"
+
+/****************************************************************************
+ * RegGetClassId() - Retrieves the string name of a class.
+ *
+ * Retrieve the string name of a class. Classes are guarenteed to be
+ * in ASCII, but should not be used directly as a rule because they
+ * might be meaningless if running non-English Windows.
+ ***************************************************************************/
+
+VOID FAR RegGetClassId( //* ENTRY:
+ LPSTR lpstrName, //* destination string name of class
+ LPSTR lpstrClass //* source name of class
+){ //* LOCAL:
+ DWORD dwSize = KEYNAMESIZE; //* size of keyname string
+ CHAR szName[KEYNAMESIZE]; //* string name for class
+
+ if (!RegQueryValue(HKEY_CLASSES_ROOT, lpstrClass, (LPSTR)szName, &dwSize))
+ lstrcpy(lpstrName, (LPSTR)szName);
+ else
+ lstrcpy(lpstrName, lpstrClass);
+
+}
+
+
+
+/***************************************************************************
+ * RegMakeFilterSpec() - Retrieves class-associated default extensions.
+ *
+ * Get the class-associated default extensions, and build a filter spec,
+ * to be used in the "Change Link" standard dialog box, which contains
+ * all the default extensions which are associated with the given class
+ * name. Again, the class names are guaranteed to be in ASCII.
+ *
+ * Returns int - The index idFilterIndex states which filter item
+ * matches the extension, or 0 if none is found.
+ ***************************************************************************/
+
+INT FAR RegMakeFilterSpec( //* ENTRY:
+ LPSTR lpstrClass, //* class name
+ LPSTR lpstrExt, //* file extension
+ LPSTR lpstrFilterSpec //* destination filter spec
+){ //* LOCAL:
+ DWORD dwSize; //* size of reg request
+ CHAR szClass[KEYNAMESIZE];//* class name
+ CHAR szName[KEYNAMESIZE]; //* name of subkey
+ CHAR szString[KEYNAMESIZE];//* name of subkey
+ INT i; //* index of subkey query
+ INT idWhich = 0; //* index of combo box item
+ INT idFilterIndex = 0; //* index to filter matching extension
+
+ for (i = 0; !RegEnumKey(HKEY_CLASSES_ROOT, i++, szName, KEYNAMESIZE); )
+ {
+ if ( *szName == '.' //* Default Extension...
+ && (dwSize = KEYNAMESIZE)
+ && !RegQueryValue(HKEY_CLASSES_ROOT, szName, szClass, &dwSize)
+ && (!lpstrClass || !lstrcmpi(lpstrClass, szClass))
+ && (dwSize = KEYNAMESIZE)
+ && !RegQueryValue(HKEY_CLASSES_ROOT, szClass, szString, &dwSize))
+ {
+ idWhich++;
+
+ if (lpstrExt && !lstrcmpi(lpstrExt, szName))
+ idFilterIndex = idWhich;
+ //* Copy over "<Class Name String>
+ //* (*<Default Extension>)"
+ //* e.g. "Server Picture (*.PIC)"
+ lstrcpy(lpstrFilterSpec, szString);
+ lstrcat(lpstrFilterSpec, " (*");
+ lstrcat(lpstrFilterSpec, szName);
+ lstrcat(lpstrFilterSpec, ")");
+ lpstrFilterSpec += lstrlen(lpstrFilterSpec) + 1;
+ //* Copy over "*<Default Extension>"
+ //* (e.g. "*.PIC") */
+ lstrcpy(lpstrFilterSpec, "*");
+ lstrcat(lpstrFilterSpec, szName);
+ lpstrFilterSpec += lstrlen(lpstrFilterSpec) + 1;
+ }
+ }
+
+ *lpstrFilterSpec = 0;
+
+ return idFilterIndex;
+
+}
+
+
+
+/***************************************************************************
+ * RegCopyClassName()
+ *
+ * Get the class name from the registration data base. We have the
+ * descriptive name and we search for the class name.
+ *
+ * returns BOOL - TRUE if class name was found and retrieved from the
+ * registration database.
+ ***************************************************************************/
+
+BOOL FAR RegCopyClassName( //* ENTRY:
+ HWND hwndList, //* HANDLE to list box
+ LPSTR lpstrClassName //* destination character string
+){ //* LOCAL:
+ DWORD dwSize; //* key name size
+ HKEY hkeyTemp; //* temp key
+ CHAR szClass[KEYNAMESIZE];//* class name string
+ CHAR szKey[KEYNAMESIZE]; //* key name string
+ INT i; //* index
+
+ szClass[0] = '\0';
+
+ if (!RegOpenKey(HKEY_CLASSES_ROOT, szClass, &hkeyTemp))
+ {
+ i = (INT)SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
+ SendMessage(hwndList, LB_GETTEXT, i, (DWORD)(LPSTR)szKey);
+
+ for (i = 0; !RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, KEYNAMESIZE); )
+ if (*szClass != '.')
+ {
+ dwSize = KEYNAMESIZE;
+ if (!RegQueryValue(HKEY_CLASSES_ROOT, szClass, lpstrClassName, &dwSize))
+ if (!lstrcmp(lpstrClassName, szKey))
+ {
+ RegCloseKey(hkeyTemp);
+ lstrcpy(lpstrClassName,szClass);
+ return TRUE;
+ }
+ }
+ RegCloseKey(hkeyTemp);
+ }
+
+ *lpstrClassName = 0;
+ return FALSE;
+
+}
+
+
+
+/***************************************************************************
+ * RegGetClassNames()
+ *
+ * Fills in the list box in the Insert New dialog with the names of
+ * OLE Servers.
+ *
+ * returns TRUE if the listbox filled successfully.
+ **************************************************************************/
+
+BOOL FAR RegGetClassNames( //* ENTRY:
+ HWND hwndList //* HANDLE to the listbox being filled
+){ //* LOCAL:
+ DWORD dwSize; //* sixe of data
+ HKEY hkeyTemp; //* temporary registration key
+ CHAR szExec[KEYNAMESIZE]; //* executables name
+ CHAR szClass[KEYNAMESIZE];//* class name
+ CHAR szName[KEYNAMESIZE]; //* key name
+ INT i;
+
+ SendMessage(hwndList, LB_RESETCONTENT, 0, 0L);
+
+ szClass[0]='\0';
+
+ if (!RegOpenKey(HKEY_CLASSES_ROOT, szClass, &hkeyTemp))
+ {
+ for (i = 0; !RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, KEYNAMESIZE); )
+ if (*szClass != '.')
+ {
+ lstrcpy(szExec, szClass);
+ lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
+ dwSize = KEYNAMESIZE;
+ if (!RegQueryValue(HKEY_CLASSES_ROOT, szExec, szName, &dwSize))
+ {
+ dwSize = KEYNAMESIZE;
+ if (!RegQueryValue(HKEY_CLASSES_ROOT, szClass, szName, &dwSize))
+ SendMessage(hwndList, LB_ADDSTRING, 0, (DWORD)(LPSTR)szName);
+ }
+ }
+ RegCloseKey(hkeyTemp);
+ return TRUE;
+ }
+ return FALSE;
+
+}
diff --git a/private/oleutest/ole1/clidemo/register.h b/private/oleutest/ole1/clidemo/register.h
new file mode 100644
index 000000000..f99da1e8a
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/register.h
@@ -0,0 +1,17 @@
+/*
+ * <register.h>
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** PROTOTYPES ***
+
+//* Far
+
+BOOL FAR RegCopyClassName(HWND hwndList, LPSTR lpstrClassName);
+VOID FAR RegGetClassId(LPSTR lpstrName, LPSTR lpstrClass);
+BOOL FAR RegGetClassNames(HWND hwndList);
+VOID FAR RegInit(HANDLE hInst);
+INT FAR RegMakeFilterSpec(LPSTR lpstrClass, LPSTR lpstrExt, LPSTR lpstrFilterSpec);
+VOID FAR RegTerm(VOID);
diff --git a/private/oleutest/ole1/clidemo/stream.c b/private/oleutest/ole1/clidemo/stream.c
new file mode 100644
index 000000000..1f0c77d56
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/stream.c
@@ -0,0 +1,348 @@
+/*
+ * stream.c - io stream function callbacks
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+/***************************************************************************
+ * This file contains all routines that directly and indirectly deal with
+ * file i/o. The OLE stream call back functions exist in this file.
+ **************************************************************************/
+
+//*** INCLUDES ***
+
+#include <windows.h>
+#include <ole.h>
+
+#include "global.h"
+#include "utility.h"
+#include "stream.h"
+#include "object.h"
+#include "demorc.h"
+
+//*** Globals ***
+
+BOOL fLoadFile = FALSE;
+
+/***************************************************************************
+ * ReadStream() - OLE Callback Function (Get)
+ *
+ * This function is pointed to from the OLESTREAM vtbl; it is Get.
+ *
+ * returns DWORD - number of bytes actually read
+ **************************************************************************/
+
+DWORD APIENTRY ReadStream( //* ENTRY:
+ LPAPPSTREAM lpStream, //* application stream pointer
+ LPSTR lpstr, //* string pointer
+ DWORD cb //* byte count
+){
+
+ return _lread(lpStream->fh, lpstr, cb);
+
+}
+
+/***************************************************************************
+ * WriteStream() - OLE Callback function (Put)
+ *
+ * This function is pointed to from the OLESTREAM vtbl; it is Put.
+ *
+ * Returns DWORD - number of bytes actually written
+ **************************************************************************/
+
+DWORD APIENTRY WriteStream( //* ENTRY:
+ LPAPPSTREAM lpStream, //* application stream pointer
+ LPSTR lpstr, //* string pointer
+ DWORD cb //* number of bytes to write
+){
+
+ return _lwrite(lpStream->fh, lpstr, cb);
+
+}
+
+/****************************************************************************
+ * ReadFromFile()
+ *
+ * This function reads OLE objects from a file. If the document
+ * contains manual links, the user will be prompted to update those links.
+ *
+ * Returns BOOL - TRUE if the read(s) were successful
+ ***************************************************************************/
+
+BOOL FAR ReadFromFile( //* ENTRY:
+ LPAPPSTREAM lpStream, //* application stream pointer
+ LHCLIENTDOC lhcDoc, //* document handle
+ LPOLECLIENT lpClient //* pointer to OLE client structure
+){ //* LOCAL:
+ BOOL bReturn = FALSE; //* return value
+ INT cFileObjects; //* number of file objects
+
+ Hourglass(TRUE);
+ fLoadFile = TRUE;
+
+ SetFilePointer((HANDLE)lpStream->fh, 0, NULL, 0);
+ //* in the file
+ if (_lread(lpStream->fh, (LPSTR)&cFileObjects, sizeof(INT)) < sizeof(INT))
+ goto Error;
+
+ for (; cFileObjects; --cFileObjects)
+ {
+ if (!ObjRead(lpStream,lhcDoc,lpClient))
+ {
+ ErrorMessage(E_FAILED_TO_READ_OBJECT);
+ goto Error;
+ }
+ }
+
+ ShowDoc(lhcDoc,1);
+ UpdateLinks(lhcDoc);
+
+ bReturn = TRUE; //* SUCCESS
+
+Error: //* ERROR Tag
+
+ Hourglass(FALSE);
+ fLoadFile = FALSE;
+ return bReturn; //* return
+
+}
+
+/****************************************************************************
+ * ObjRead()
+ *
+ * Rread an object from the specified file. The file pointer will
+ * be advanced past the object.
+ *
+ * HANDLE fh - DOS file handle of file to be read from
+ *
+ * returns HWND - window handle to item window containing the OLE object
+ ***************************************************************************/
+
+BOOL FAR ObjRead( //* ENTRY:
+ LPAPPSTREAM lpStream, //* application stream pointer
+ LHCLIENTDOC lhcDoc, //* document handle
+ LPOLECLIENT lpClient //* pointer to OLE client structure
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+ LPOLEOBJECT lpObject; //* pointer ole object
+ LONG otObject; //* type of object
+ RECT rcObject; //* object rect
+ CHAR szTmp[CBOBJNAMEMAX]; //* temporary string buffer
+ CHAR szProto[PROTOCOL_STRLEN+1];//* protocol string
+ INT i; //* index
+
+ if (_lread(lpStream->fh, szTmp, CBOBJNAMEMAX) < CBOBJNAMEMAX )
+ return FALSE;
+
+ if (_lread(lpStream->fh, szProto, PROTOCOL_STRLEN) < PROTOCOL_STRLEN )
+ return FALSE;
+
+ for (i=0; szProto[i] != ' '; i++);
+ szProto[i] = 0;
+
+ ValidateName( szTmp );
+
+ if (!(pItem = PreItemCreate(lpClient, TRUE, lhcDoc)))
+ return FALSE;
+
+ if (Error(OleLoadFromStream((LPOLESTREAM)&(lpStream->olestream),
+ szProto,(LPOLECLIENT)&(pItem->oleclient), lhcDoc, szTmp, &lpObject)))
+ goto Error;
+
+ if (_lread(lpStream->fh, (LPSTR)&rcObject, sizeof(RECT)) < sizeof(RECT))
+ goto Error;
+
+ if (_lread(lpStream->fh, (LPSTR)&otObject, sizeof(LONG)) < sizeof(LONG))
+ goto Error;
+
+ if (PostItemCreate(lpObject, otObject, &rcObject, pItem))
+ {
+ pItem->fNew = TRUE;
+ ObjSetBounds(pItem);
+ return TRUE; //* SUCCESS return
+ }
+ else
+ return FALSE;
+
+Error: //* ERROR Tag
+
+ FreeAppItem(pItem);
+ return FALSE;
+
+}
+
+/*************************************************************************
+ * WriteToFile()
+ *
+ * Write current document to a file.
+ *
+ * returns BOOL - TRUE if file successfully written
+ ************************************************************************/
+
+BOOL FAR WriteToFile( //* ENTRY:
+ LPAPPSTREAM lpStream //* application stream pointer
+){ //* LOCAL:
+ INT iObjectsWritten=0; //* counter of objects written to file
+ APPITEMPTR pItem; //* application Item pointer
+
+ UpdateFromOpenServers();
+
+ SetFilePointer((HANDLE)lpStream->fh, 0, NULL, 0);
+
+ Hourglass(TRUE);
+
+ if (_lwrite(lpStream->fh, (LPSTR)&iObjects, sizeof(INT)) < sizeof(INT))
+ goto Error;
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ {
+ if (!ObjWrite(lpStream, pItem))
+ goto Error;
+ iObjectsWritten++;
+ }
+
+ if (iObjectsWritten != iObjects)
+ goto Error;
+
+
+ Dirty(DOC_CLEAN);
+ Hourglass(FALSE);
+ return(TRUE); //* SUCCESS return
+
+Error: //* ERROR Tag
+
+ Hourglass(FALSE);
+ return(FALSE); //* ERROR return
+
+}
+
+/****************************************************************************
+ * ObjWrite()
+ *
+ * This function writes an object to the specified
+ * file. The file pointer will be advanced past the end of
+ * the written object.
+
+ * Returns BOOL - TRUE if object written successfully
+ ***************************************************************************/
+
+BOOL FAR ObjWrite( //* ENTRY:
+ LPAPPSTREAM lpStream, //* application stream pointer
+ APPITEMPTR pItem //* application item pointer
+){ //* LOCAL:
+ POINT pt; //* center of rec point
+ RECT rc; //* bounding rectangle
+ UINT cbTmp = CBOBJNAMEMAX;
+ CHAR szTmp[PROTOCOL_STRLEN];//* protocol string
+
+ OleQueryName(pItem->lpObject, szTmp, &cbTmp);
+
+ if (_lwrite(lpStream->fh, szTmp, CBOBJNAMEMAX) < CBOBJNAMEMAX )
+ return FALSE;
+
+ if (pItem->otObject == OT_STATIC)
+ wsprintf(szTmp, "%-15s", STATICP);
+ else
+ wsprintf(szTmp, "%-15s", STDFILEEDITING);
+
+ if (_lwrite(lpStream->fh, szTmp, PROTOCOL_STRLEN) < PROTOCOL_STRLEN )
+ return FALSE;
+
+ if (Error(OleSaveToStream(pItem->lpObject, (LPOLESTREAM)&(lpStream->olestream))))
+ return FALSE;
+
+ GetClientRect(pItem->hwnd, (LPRECT)&rc);
+ pt = *(LPPOINT)&rc;
+ ClientToScreen(pItem->hwnd, (LPPOINT)&pt);
+ ScreenToClient(hwndFrame, (LPPOINT)&pt);
+ OffsetRect(
+ &rc,
+ pt.x - rc.left - GetSystemMetrics(SM_CXFRAME),
+ pt.y - rc.top - GetSystemMetrics(SM_CYFRAME)
+ );
+
+ if (_lwrite(lpStream->fh, (LPSTR)&rc, sizeof(RECT)) < sizeof(RECT)
+ || _lwrite(lpStream->fh, (LPSTR)&(pItem->otObject), sizeof(LONG)) < sizeof(LONG))
+ return FALSE;
+
+ return TRUE; //* SUCCESS return
+
+}
+
+/****************************************************************************
+ * UpdateLinks()
+ *
+ * Get the most up to date rendering information and show it.
+ ***************************************************************************/
+
+static VOID UpdateLinks( //* ENTRY
+ LHCLIENTDOC lhcDoc //* client document handle
+){ //* LOCAL:
+ INT i=0; //* index
+ APPITEMPTR pItem; //* temporary item pointer
+ CHAR szUpdate[CBMESSAGEMAX];//* update message?
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ {
+ if (pItem->lhcDoc == lhcDoc && pItem->otObject == OT_LINK)
+ {
+ if (!i)
+ {
+ LoadString(hInst, IDS_UPDATELINKS, szUpdate, CBMESSAGEMAX);
+ if (MessageBox(hwndFrame, szUpdate, szAppName,
+ MB_YESNO | MB_ICONEXCLAMATION) != IDYES)
+ break;
+ i++;
+ }
+ Error(OleUpdate(pItem->lpObject));
+ }
+ }
+
+ WaitForAllObjects();
+
+}
+
+/****************************************************************************
+ * UpdateFromOpenServers()
+ *
+ * Get the most up to date rendering information before storing it.
+ ***************************************************************************/
+
+static VOID UpdateFromOpenServers(VOID)
+{ //* LOCAL:
+ APPITEMPTR pItem; //* temporary item pointer
+ APPITEMPTR pItemNext;
+
+ for (pItem = GetTopItem(); pItem; pItem = pItemNext)
+ {
+ pItemNext = GetNextItem(pItem);
+ if (pItem->otObject == OT_EMBEDDED ||
+ (pItem->uoObject == oleupdate_oncall
+ && pItem->otObject == OT_LINK ))
+
+ if (OleQueryOpen(pItem->lpObject) == OLE_OK)
+ {
+ CHAR szMessage[2*CBMESSAGEMAX];
+ CHAR szBuffer[CBMESSAGEMAX];
+ UINT cb = CBOBJNAMEMAX; //* The name will be the server window title.
+ CHAR szTmp[CBOBJNAMEMAX]; //* when the object is edited.
+
+ Error(OleQueryName(pItem->lpObject,szTmp,&cb));
+ LoadString(hInst, IDS_UPDATE_OBJ, szBuffer, CBMESSAGEMAX);
+ wsprintf(szMessage, szBuffer, (LPSTR)szTmp);
+
+ if (MessageBox(hwndFrame, szMessage, szAppName, MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
+ {
+ Error(OleUpdate(pItem->lpObject));
+ WaitForObject(pItem);
+ }
+ if (!pItem->fVisible)
+ ObjDelete(pItem, OLE_OBJ_DELETE);
+ }
+
+ }
+
+ WaitForAllObjects();
+
+}
diff --git a/private/oleutest/ole1/clidemo/stream.h b/private/oleutest/ole1/clidemo/stream.h
new file mode 100644
index 000000000..f28efcfc2
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/stream.h
@@ -0,0 +1,35 @@
+/*
+ * stream.h - OLE stream I/O headers.
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** CONSTANTS ***
+
+#define MAXREAD ((LONG) (60L * 1024L))
+
+//*** GLOBALS ***
+
+extern DWORD vcbObject;
+
+//*** PROTOTYPES ***
+
+//* OLE callbacks
+
+DWORD APIENTRY ReadStream(LPAPPSTREAM, LPSTR, DWORD);
+DWORD APIENTRY WriteStream(LPAPPSTREAM, LPSTR, DWORD);
+
+//* Far
+
+BOOL FAR WriteToFile(LPAPPSTREAM);
+BOOL FAR ObjWrite(LPAPPSTREAM, APPITEMPTR);
+BOOL FAR ReadFromFile(LPAPPSTREAM, LHCLIENTDOC, LPOLECLIENT);
+BOOL FAR ObjRead(LPAPPSTREAM, LHCLIENTDOC, LPOLECLIENT);
+
+//* Local
+
+DWORD lread(int, VOID FAR *, DWORD);
+DWORD lwrite(int, VOID FAR *, DWORD);
+static VOID UpdateLinks(LHCLIENTDOC);
+static VOID UpdateFromOpenServers(VOID);
diff --git a/private/oleutest/ole1/clidemo/utility.c b/private/oleutest/ole1/clidemo/utility.c
new file mode 100644
index 000000000..da84c0e25
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/utility.c
@@ -0,0 +1,612 @@
+/*
+ * utility.c - general purpose utility routines
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ *
+ */
+
+//*** INCLUDES ****
+
+#include <windows.h>
+#include <ole.h>
+
+#include "global.h"
+#include "demorc.h"
+#include "utility.h"
+#include "object.h"
+#include "dialog.h"
+
+static INT iTimerID = 0;
+static APPITEMPTR lpaItemHold;
+
+
+/****************************************************************************
+ * ErrorMessage()
+ *
+ * Display a message box containing the specified string from the table.
+ *
+ * id WORD - Index into string table.
+ ***************************************************************************/
+
+VOID FAR ErrorMessage( //* ENTRY:
+ DWORD id //* message ID
+){ //* LOCAL:
+ CHAR sz[CBMESSAGEMAX]; //* string
+ HWND hwnd; //* parent window handle
+
+ if (IsWindow(hwndProp))
+ hwnd = hwndProp;
+ else if (IsWindow(hwndFrame))
+ hwnd = hwndFrame;
+ else
+ return;
+
+ LoadString(hInst, id, sz, CBMESSAGEMAX);
+ MessageBox(hwnd, sz, szAppName, MB_OK | MB_ICONEXCLAMATION);
+
+}
+
+
+/****************************************************************************
+ * Hourglass()
+ *
+ * Put up or takes down the hourglass cursor as needed.
+ *
+ * int bToggle - TRUE turns the hour glass on
+ * HG_OFF turn it off
+ ***************************************************************************/
+
+VOID FAR Hourglass( //* ENTRY:
+ BOOL bOn //* hourglass on/off
+){ //* LOCAL:
+ static HCURSOR hcurWait = NULL; //* hourglass cursor
+ static HCURSOR hcurSaved; //* old cursor
+ static iCount = 0;
+
+
+ if (bOn)
+ {
+ iCount++;
+ if (!hcurWait)
+ hcurWait = LoadCursor(NULL, IDC_WAIT);
+ if (!hcurSaved)
+ hcurSaved = SetCursor(hcurWait);
+ }
+ else if (!bOn)
+ {
+ if (--iCount < 0 )
+ iCount = 0;
+ else if (!iCount)
+ {
+ SetCursor(hcurSaved);
+ hcurSaved = NULL;
+ }
+ }
+
+}
+
+/***************************************************************************
+ * WaitForObject()
+ *
+ * Dispatch messagee until the specified object is not busy.
+ * This allows asynchronous processing to occur.
+ *
+ * lpObject LPOLEOBJECT - pointer to object
+ **************************************************************************/
+
+void FAR WaitForObject( //* ENTRY:
+ APPITEMPTR paItem //* pointer to OLE object
+){ //* LOCAL
+ BOOL bTimerOn = FALSE;
+
+ while (OleQueryReleaseStatus(paItem->lpObject) == OLE_BUSY)
+ {
+ lpaItemHold = paItem;
+ if (!bTimerOn)
+ bTimerOn = ToggleBlockTimer(TRUE);//* set timer
+ ProcessMessage(hwndFrame, hAccTable);
+ }
+
+ if (bTimerOn)
+ ToggleBlockTimer(FALSE);//* toggle timer off
+}
+
+/***************************************************************************
+ * WaitForAllObjects()
+ *
+ * Wait for all asynchronous operations to complete.
+ **************************************************************************/
+
+VOID FAR WaitForAllObjects(VOID)
+{
+ BOOL bTimerOn = FALSE;
+
+ while (cOleWait)
+ {
+ if (!bTimerOn)
+ bTimerOn = ToggleBlockTimer(TRUE);//* set timer
+
+ ProcessMessage(hwndFrame, hAccTable) ;
+ }
+
+ if (bTimerOn)
+ ToggleBlockTimer(FALSE);//* toggle timer off
+
+}
+
+/****************************************************************************
+ * ProcessMessage()
+ *
+ * Obtain and dispatch a message. Used when in a message dispatch loop.
+ *
+ * Returns BOOL - TRUE if message other than WM_QUIT retrieved
+ * FALSE if WM_QUIT retrieved.
+ ***************************************************************************/
+
+BOOL FAR ProcessMessage( //* ENTRY:
+ HWND hwndFrame, //* main window handle
+ HANDLE hAccTable //* accelerator table handle
+){ //* LOCAL:
+ BOOL fReturn; //* return value
+ MSG msg; //* message
+
+ if (fReturn = GetMessage(&msg, NULL, 0, 0))
+ {
+ if (cOleWait || !TranslateAccelerator(hwndFrame, hAccTable, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ return fReturn;
+
+}
+
+
+/****************************************************************************
+ * Dirty()
+ *
+ * Keep track of weather modifications have been made
+ * to the document or not.
+ *
+ * iAction - action type:
+ * DOC_CLEAN set document clean flag true
+ * DOC_DIRTY the opposite
+ * DOC_UNDIRTY undo one dirty op
+ * DOC_QUERY return present state
+ *
+ * Returs int - present value of fDirty; 0 is clean.
+ ***************************************************************************/
+
+INT FAR Dirty( //* ENTRY:
+ INT iAction //* see above comment
+){ //* LOCAL:
+ static INT iDirty = 0; //* dirty state >0 is dirty
+
+ switch (iAction)
+ {
+ case DOC_CLEAN:
+ iDirty = 0;
+ break;
+ case DOC_DIRTY:
+ iDirty++;
+ break;
+ case DOC_UNDIRTY:
+ iDirty--;
+ break;
+ case DOC_QUERY:
+ break;
+ }
+ return(iDirty);
+
+}
+
+/***************************************************************************
+ * ObjectsBusy()
+ *
+ * This function enumerates the OLE objects in the current document
+ * and displays a message box stating whether an object is busy.
+ * This function calls the DisplayBusyMessage() function which
+ * performs most of the work. This function is only used by the macro
+ * BUSY_CHECK(), defined in object.h.
+ *
+ * fSelectionOnly BOOL -NOT USED?
+ *
+ * BOOL - TRUE if one or more objects found to be busy
+ * FALSE otherwise
+ *
+ ***************************************************************************/
+
+BOOL FAR ObjectsBusy ()
+{
+ APPITEMPTR pItem;
+
+ if (iTimerID)
+ {
+ RetryMessage(NULL,RD_CANCEL);
+ return TRUE;
+ }
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ if (DisplayBusyMessage(pItem))
+ return TRUE;
+
+ return FALSE;
+
+}
+
+/***************************************************************************
+ * DisplayBusyMessage()
+ *
+ * This function determines if an object is busy and displays
+ * a message box stating this status.
+ *
+ * Returns BOOL - TRUE if object is busy
+ **************************************************************************/
+
+BOOL FAR DisplayBusyMessage ( //* ENTRY:
+ APPITEMPTR paItem //* application item pointer
+){ //* LOCAL:
+
+ if (OleQueryReleaseStatus(paItem->lpObject) == OLE_BUSY)
+ {
+ RetryMessage(paItem,RD_CANCEL);
+ return TRUE;
+ }
+ return FALSE;
+
+}
+
+/***************************************************************************
+ * CreateNewUniqueName()
+ *
+ * Create a string name unique to this document. This is done by using the
+ * prefix string("OleDemo #") and appending a counter to the end of the
+ * prefix string. The counter is incremented whenever a new object is added.
+ * String will be 14 bytes long.
+ *
+ * Return LPSTR - pointer to unique object name.
+ ***************************************************************************/
+
+LPSTR FAR CreateNewUniqueName( //* ENTRY:
+ LPSTR lpstr //* destination pointer
+){
+
+ wsprintf( lpstr, "%s%04d", OBJPREFIX, iObjectNumber++ );
+ return( lpstr );
+
+}
+
+/***************************************************************************
+ * ValidateName()
+ *
+ * This function ensures that the given object name is valid and unique.
+ *
+ * Returns: BOOL - TRUE if object name valid
+ **************************************************************************/
+
+BOOL FAR ValidateName( //* ENTRY:
+ LPSTR lpstr //* pointer to object name
+){ //* LOCAL:
+ LPSTR lp; //* worker string
+ INT n;
+ //* check for "OleDemo #" prefix
+ lp = OBJPREFIX;
+
+ while( *lp )
+ {
+ if( *lpstr != *lp )
+ return( FALSE );
+
+ lpstr++; lp++;
+ }
+ //* convert string number to int
+ for (n = 0 ; *lpstr ; n = n*10 + (*lpstr - '0'),lpstr++);
+
+ if( n > 9999 ) //* 9999 is largest legal number
+ return FALSE;
+
+ if( iObjectNumber <= n) //* Make count > than any current
+ iObjectNumber = n + 1; //* object to ensure uniqueness
+
+ return TRUE;
+}
+
+/***************************************************************************
+ * FreeAppItem()
+ *
+ * Free application item structure and destroy the associated structure.
+ **************************************************************************/
+
+VOID FAR FreeAppItem( //* ENTRY:
+ APPITEMPTR pItem //* pointer to application item
+){ //* LOCAL:
+ HANDLE hWork; //* handle used to free
+
+ if (pItem)
+ { //* destroy the window
+ if (pItem->hwnd)
+ DestroyWindow(pItem->hwnd);
+
+ hWork = LocalHandle((LPSTR)pItem);//* get handle from pointer
+
+ if (pItem->aLinkName)
+ DeleteAtom(pItem->aLinkName);
+
+ if (pItem->aServer)
+ DeleteAtom(pItem->aServer);
+
+ LocalUnlock(hWork);
+ LocalFree(hWork);
+ }
+
+}
+
+/***************************************************************************
+ * SizeOfLinkData()
+ *
+ * Find the size of a linkdata string.
+ **************************************************************************/
+
+LONG FAR SizeOfLinkData( //* ENTRY:
+ LPSTR lpData //* pointer to link data
+){ //* LOCAL:
+ LONG lSize; //* total size
+
+ lSize = (LONG)lstrlen(lpData)+1; //* get size of classname
+ lSize += (LONG)lstrlen(lpData+lSize)+1; //* get size of doc.
+ lSize += (LONG)lstrlen(lpData+lSize)+2;//* get size of item
+ return lSize;
+
+}
+
+/****************************************************************************
+ * ShowDoc()
+ *
+ * Display all the child windows associated with a document, or make all the
+ * child windows hidden.
+ ***************************************************************************/
+
+VOID FAR ShowDoc( //* ENTRY:
+ LHCLIENTDOC lhcDoc, //* document handle
+ INT iShow //* show/hide
+){ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+ APPITEMPTR pItemTop = NULL;
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ {
+ if (pItem->lhcDoc == lhcDoc)
+ {
+ if (!pItemTop)
+ pItemTop = pItem;
+ ShowWindow(pItem->hwnd,(iShow ? SW_SHOW : SW_HIDE));
+ pItem->fVisible = (BOOL)iShow;
+ }
+ }
+
+ if (pItemTop)
+ SetTopItem(pItemTop);
+
+}
+
+/****************************************************************************
+ * GetNextActiveItem()
+ *
+ * Returns HWND - the next visible window.
+ ***************************************************************************/
+
+APPITEMPTR FAR GetNextActiveItem()
+{ //* LOCAL:
+ APPITEMPTR pItem; //* application item pointer
+
+ for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
+ if (pItem->fVisible)
+ break;
+
+ return pItem;
+
+}
+
+/****************************************************************************
+ * GetTopItem()
+ ***************************************************************************/
+
+APPITEMPTR FAR GetTopItem()
+{
+ HWND hwnd;
+
+ if (hwnd = GetTopWindow(hwndFrame))
+ return ((APPITEMPTR)GetWindowLong(hwnd,0));
+ else
+ return NULL;
+
+}
+/****************************************************************************
+ * GetNextItem()
+ ***************************************************************************/
+
+APPITEMPTR FAR GetNextItem( //* ENTRY:
+ APPITEMPTR pItem //* application item pointer
+){ //* LOCAL:
+ HWND hwnd; //* next item window handle
+
+ if (hwnd = GetNextWindow(pItem->hwnd, GW_HWNDNEXT))
+ return((APPITEMPTR)GetWindowLong(hwnd,0));
+ else
+ return NULL;
+
+}
+
+/****************************************************************************
+ * SetTopItem()
+ ***************************************************************************/
+
+VOID FAR SetTopItem(
+ APPITEMPTR pItem
+){
+ APPITEMPTR pLastItem;
+
+ pLastItem = GetTopItem();
+ if (pLastItem && pLastItem != pItem)
+ SendMessage(pLastItem->hwnd,WM_NCACTIVATE, 0, 0L);
+
+ if (!pItem)
+ return;
+
+ if (pItem->fVisible)
+ {
+ BringWindowToTop(pItem->hwnd);
+ SendMessage(pItem->hwnd,WM_NCACTIVATE, 1, 0L);
+ }
+
+}
+
+/***************************************************************************
+ * ReallocLinkData()
+ *
+ * Reallocate link data in order to avoid creating lots and lots of global
+ * memory thunks.
+ **************************************************************************/
+
+BOOL FAR ReallocLinkData( //* ENTRY:
+ APPITEMPTR pItem, //* application item pointer
+ LONG lSize //* new link data size
+){ //* LOCAL:
+ HANDLE handle; //* temporary memory handle
+
+ handle = GlobalHandle(pItem->lpLinkData);
+ GlobalUnlock(handle);
+
+ if (!(pItem->lpLinkData = GlobalLock(GlobalReAlloc(handle, lSize, 0))))
+ {
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ return FALSE;
+ }
+
+ return TRUE;
+
+}
+
+/***************************************************************************
+ * AllocLinkData()
+ *
+ * Allocate link data space.
+ **************************************************************************/
+
+BOOL FAR AllocLinkData( //* ENTRY:
+ APPITEMPTR pItem, //* application item pointer
+ LONG lSize //* link data size
+){
+
+ if (!(pItem->lpLinkData = GlobalLock(
+ GlobalAlloc(GMEM_DDESHARE | GMEM_ZEROINIT ,lSize)
+ )))
+ {
+ ErrorMessage(E_FAILED_TO_ALLOC);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/***************************************************************************
+ * FreeLinkData()
+ *
+ * Free the space associated with a linkdata pointer.
+ **************************************************************************/
+
+VOID FAR FreeLinkData( //* ENTRY:
+ LPSTR lpLinkData //* pointer to linkdata
+){ //* LOCAL:
+ HANDLE handle; //* temporary memory handle
+
+ if (lpLinkData)
+ {
+ handle = GlobalHandle(lpLinkData);
+ GlobalUnlock(handle);
+ GlobalFree(handle);
+ }
+}
+
+/****************************************************************************
+ * ShowNewWindow()
+ *
+ * Show a new application item window.
+ ***************************************************************************/
+
+VOID FAR ShowNewWindow( //* ENTRY:
+ APPITEMPTR pItem
+){
+
+ if (pItem->fVisible)
+ {
+ pItem->fNew = TRUE;
+ SetTopItem(pItem);
+ ShowWindow(pItem->hwnd,SW_SHOW);
+ }
+ else
+ ObjDelete(pItem,OLE_OBJ_DELETE);
+
+}
+
+/****************************************************************************
+ * UnqualifyPath()
+ *
+ * return pointer to unqualified path name.
+ ***************************************************************************/
+
+PSTR FAR UnqualifyPath(PSTR pPath)
+{
+ PSTR pReturn;
+
+ for (pReturn = pPath; *pPath; pPath++)
+ if (*pPath == ':' || *pPath == '\\')
+ pReturn = pPath+1;
+
+ return pReturn;
+
+}
+
+/****************************************************************************
+ * ToggleBlockTimer()
+ *
+ * Toggle a timer used to check for blocked servers.
+ ***************************************************************************/
+
+BOOL FAR ToggleBlockTimer(BOOL bSet)
+{
+ if (bSet && !iTimerID)
+ {
+ if (iTimerID = SetTimer(hwndFrame,1, 3000, (TIMERPROC) fnTimerBlockProc))
+ return TRUE;
+ }
+ else if (iTimerID)
+ {
+ KillTimer(hwndFrame,1);
+ iTimerID = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/****************************************************************************
+ * fnTimerBlockProc()
+ *
+ * Timer callback procedure
+ ***************************************************************************/
+
+VOID CALLBACK fnTimerBlockProc( //* ENTRY:
+ HWND hWnd,
+ UINT wMsg,
+ UINT iTimerID,
+ DWORD dwTime
+){
+
+ if (!hRetry)
+ RetryMessage(lpaItemHold, RD_RETRY | RD_CANCEL);
+
+}
+
diff --git a/private/oleutest/ole1/clidemo/utility.h b/private/oleutest/ole1/clidemo/utility.h
new file mode 100644
index 000000000..42a8113d9
--- /dev/null
+++ b/private/oleutest/ole1/clidemo/utility.h
@@ -0,0 +1,34 @@
+/*
+ * utility.h
+ *
+ * Created by Microsoft Corporation.
+ * (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
+ */
+
+//*** PROTO TYPES ***
+
+//* FAR
+BOOL FAR ObjectsBusy(VOID);
+VOID FAR WaitForAllObjects(VOID);
+VOID FAR WaitForObject(APPITEMPTR);
+VOID FAR ErrorMessage(DWORD);
+VOID FAR Hourglass(BOOL);
+BOOL FAR DisplayBusyMessage (APPITEMPTR);
+BOOL FAR Dirty(INT);
+LPSTR FAR CreateNewUniqueName(LPSTR);
+BOOL FAR ValidateName(LPSTR);
+BOOL FAR ProcessMessage(HWND, HANDLE);
+VOID FAR FreeAppItem(APPITEMPTR);
+LONG FAR SizeOfLinkData (LPSTR);
+VOID FAR ShowDoc(LHCLIENTDOC, INT);
+APPITEMPTR FAR GetTopItem(VOID);
+VOID FAR SetTopItem(APPITEMPTR);
+APPITEMPTR FAR GetNextActiveItem(VOID);
+APPITEMPTR FAR GetNextItem(APPITEMPTR);
+BOOL FAR ReallocLinkData(APPITEMPTR,LONG);
+BOOL FAR AllocLinkData(APPITEMPTR,LONG);
+VOID FAR FreeLinkData(LPSTR);
+VOID FAR ShowNewWindow(APPITEMPTR);
+PSTR FAR UnqualifyPath(PSTR);
+VOID CALLBACK fnTimerBlockProc(HWND, UINT, UINT, DWORD);
+BOOL FAR ToggleBlockTimer(BOOL);