From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/oleutest/ole1/clidemo/clidemo | 37 + private/oleutest/ole1/clidemo/clidemo.c | 1032 +++++++++++++++++++++ private/oleutest/ole1/clidemo/clidemo.def | 35 + private/oleutest/ole1/clidemo/clidemo.h | 62 ++ private/oleutest/ole1/clidemo/clidemo.ico | Bin 0 -> 766 bytes private/oleutest/ole1/clidemo/clidemo.rc | 231 +++++ private/oleutest/ole1/clidemo/clidemo.rcv | 33 + private/oleutest/ole1/clidemo/cliver.h | 9 + private/oleutest/ole1/clidemo/daytona/makefile | 6 + private/oleutest/ole1/clidemo/daytona/sources | 26 + private/oleutest/ole1/clidemo/demorc.h | 180 ++++ private/oleutest/ole1/clidemo/dialog.c | 1150 +++++++++++++++++++++++ private/oleutest/ole1/clidemo/dialog.h | 85 ++ private/oleutest/ole1/clidemo/dirs | 4 + private/oleutest/ole1/clidemo/global.h | 108 +++ private/oleutest/ole1/clidemo/object.c | 1177 ++++++++++++++++++++++++ private/oleutest/ole1/clidemo/object.h | 40 + private/oleutest/ole1/clidemo/register.c | 196 ++++ private/oleutest/ole1/clidemo/register.h | 17 + private/oleutest/ole1/clidemo/stream.c | 348 +++++++ private/oleutest/ole1/clidemo/stream.h | 35 + private/oleutest/ole1/clidemo/utility.c | 612 ++++++++++++ private/oleutest/ole1/clidemo/utility.h | 34 + 23 files changed, 5457 insertions(+) create mode 100644 private/oleutest/ole1/clidemo/clidemo create mode 100644 private/oleutest/ole1/clidemo/clidemo.c create mode 100644 private/oleutest/ole1/clidemo/clidemo.def create mode 100644 private/oleutest/ole1/clidemo/clidemo.h create mode 100644 private/oleutest/ole1/clidemo/clidemo.ico create mode 100644 private/oleutest/ole1/clidemo/clidemo.rc create mode 100644 private/oleutest/ole1/clidemo/clidemo.rcv create mode 100644 private/oleutest/ole1/clidemo/cliver.h create mode 100644 private/oleutest/ole1/clidemo/daytona/makefile create mode 100644 private/oleutest/ole1/clidemo/daytona/sources create mode 100644 private/oleutest/ole1/clidemo/demorc.h create mode 100644 private/oleutest/ole1/clidemo/dialog.c create mode 100644 private/oleutest/ole1/clidemo/dialog.h create mode 100644 private/oleutest/ole1/clidemo/dirs create mode 100644 private/oleutest/ole1/clidemo/global.h create mode 100644 private/oleutest/ole1/clidemo/object.c create mode 100644 private/oleutest/ole1/clidemo/object.h create mode 100644 private/oleutest/ole1/clidemo/register.c create mode 100644 private/oleutest/ole1/clidemo/register.h create mode 100644 private/oleutest/ole1/clidemo/stream.c create mode 100644 private/oleutest/ole1/clidemo/stream.h create mode 100644 private/oleutest/ole1/clidemo/utility.c create mode 100644 private/oleutest/ole1/clidemo/utility.h (limited to 'private/oleutest/ole1/clidemo') 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 + +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 +#include //* OLE structs and defines +#include //* 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 + + //* 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 Binary files /dev/null and b/private/oleutest/ole1/clidemo/clidemo.ico 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 +#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 +#include //* 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 ":" 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 + +//*** 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 +#include //* SHELL +#include //* 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 +#include + +#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 " + //* (*)" + //* e.g. "Server Picture (*.PIC)" + lstrcpy(lpstrFilterSpec, szString); + lstrcat(lpstrFilterSpec, " (*"); + lstrcat(lpstrFilterSpec, szName); + lstrcat(lpstrFilterSpec, ")"); + lpstrFilterSpec += lstrlen(lpstrFilterSpec) + 1; + //* Copy over "*" + //* (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 @@ +/* + * + * + * 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 +#include + +#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 +#include + +#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); -- cgit v1.2.3