Annotation of mstools/samples/ole/clidemo/clidemo.c, revision 1.1

1.1     ! root        1: /* 
        !             2:  * clidemo.c - OLE client application sample code
        !             3:  *
        !             4:  * Created by Microsoft Corporation.
        !             5:  * (c) Copyright Microsoft Corp. 1990 - 1992  All Rights Reserved
        !             6:  *
        !             7:  */
        !             8: 
        !             9:  /***************************************************************************
        !            10:  * IMPORTANT - README:
        !            11:  * OLE client applications are windows programs which use the OLE client
        !            12:  * APIs.  Therefore it is imperative that you understand how these APIs
        !            13:  * operate. Most importantly it is essential that you keep in mind which
        !            14:  * procedure calls result in asynchronous states: a state where the operation
        !            15:  * is not truely complete after a return from the call.
        !            16:  * 
        !            17:  * Many functions produce asynchronous states, for example, OleActivate, 
        !            18:  * OleClose, OleCopyFromLink, OleCreate ... Reference your SDK manual for
        !            19:  * a complete list.
        !            20:  *
        !            21:  * So whenever you call any of these library functions keep in mind that
        !            22:  * the operation is not necessarily complete once a return is made.
        !            23:  * These operations require communications with a server application.  With
        !            24:  * OLE the inter-application communication is done through DDE.  In order
        !            25:  * for a DDE conversation to complete several DDE messages need to be 
        !            26:  * sent and recieved by both the server and client OLE DLLs.  So, the 
        !            27:  * asynchronous operations will not complete until the client application
        !            28:  * enters a message dipatch loop.  Therefore, it is necessary to enter
        !            29:  * a dispatch loop and wait for completion.  It is not necessary to block 
        !            30:  * all other operation; however, it is very important to coordinate the
        !            31:  * user activity to prevent disastrous re-entry cases.
        !            32:  *
        !            33:  * In this application I have written a macro to prevent re-entry
        !            34:  * problems.  Namely: ANY_OBJECT_BUSY which prevents a user from initiating
        !            35:  * an action which will result in an asynchronous call if there is an object   
        !            36:  * already in an asynchronous state.   
        !            37:  * 
        !            38:  * The following is brief summary of the three macros:
        !            39:  *
        !            40:  * ANY_OBJECT_BUSY: checks to see if any object in the document is busy.
        !            41:  *              This prevents a new document from being saved to file if there are
        !            42:  *              objects in asynchronous states.
        !            43:  *
        !            44:  * So, the problem is that we have to enter a message dispatch loop in order
        !            45:  * to let DDE messages get through so that asynchronous operations can finish.
        !            46:  * And while we are in the message dispatch loops (WaitForObject or WaitForAllObjects)
        !            47:  * we have to prevent the user from doing things that can't be done when an
        !            48:  * object(s) is busy.  Yes, it is confusing , but, the end result is a super
        !            49:  * cool application that can have linked and embbeded objects! 
        !            50:  ***************************************************************************/
        !            51: 
        !            52: //*** INCLUDES ***
        !            53: 
        !            54: #include <windows.h>                   //* WINDOWS 
        !            55: #include <ole.h>                       //* OLE structs and defines
        !            56: #include <shellapi.h>                  //* Shell, drag and drop headers 
        !            57: 
        !            58: #include "demorc.h"                    //* header for resource file
        !            59: #include "global.h"                    //* global app variables
        !            60: #include "clidemo.h"                   //* app includes:
        !            61: #include "register.h"
        !            62: #include "stream.h"
        !            63: #include "object.h"
        !            64: #include "dialog.h"
        !            65: #include "utility.h"
        !            66: 
        !            67: //*** VARIABLES ***
        !            68: 
        !            69: //** Global
        !            70: HANDLE            hInst;
        !            71: BOOL              fRetry = FALSE;
        !            72: HWND              hwndFrame;           //* main window
        !            73: HANDLE            hAccTable;           //* accelerator table
        !            74: CHAR              szFrameClass[] = "CliDemo";//* main window class name
        !            75: CHAR              szItemClass[]  = "ItemClass";//* item window class name
        !            76: CHAR              szAppName[CBMESSAGEMAX];//* Application name
        !            77: INT               iObjects = 0;        //* object count
        !            78: INT               iObjectNumber = 0;   //* object number for object name
        !            79: CHAR              szFileName[CBPATHMAX];
        !            80:                                        //* ClipBoard formats:
        !            81: OLECLIPFORMAT     vcfLink;             //* "ObjectLink" 
        !            82: OLECLIPFORMAT     vcfNative;           //* "Native"
        !            83: OLECLIPFORMAT     vcfOwnerLink;        //* "OwnerLink"
        !            84: 
        !            85: 
        !            86: /***************************************************************************
        !            87:  * WinMain() - Main Windows routine
        !            88:  ***************************************************************************/
        !            89: 
        !            90: int WinMain(
        !            91:    HANDLE hInstance,
        !            92:    HANDLE hPrevInst,
        !            93:    LPSTR  lpCmdLine,
        !            94:    INT    nCmdLine
        !            95: ){
        !            96:     hInst = hInstance;
        !            97: 
        !            98:     if (!InitApplication(hInst))   //* register window classes
        !            99:       return FALSE;
        !           100: 
        !           101:     if (!InitInstance(hInst))          //* create window instance
        !           102:         return FALSE;
        !           103: 
        !           104:     OfnInit(hInst);                    //* setup to use <commdlg.dll>
        !           105: 
        !           106:                                        //* register clipboard formats
        !           107:                                        //* used for OLE
        !           108:     vcfLink      = RegisterClipboardFormat("ObjectLink");
        !           109:     vcfNative    = RegisterClipboardFormat("Native");
        !           110:     vcfOwnerLink = RegisterClipboardFormat("OwnerLink");
        !           111:     
        !           112: 
        !           113:     ShowWindow(hwndFrame, SW_SHOWNORMAL);
        !           114:     UpdateWindow(hwndFrame);
        !           115:     ProcessCmdLine(lpCmdLine);
        !           116: 
        !           117:     while (ProcessMessage(hwndFrame, hAccTable)) ;
        !           118: 
        !           119:     return FALSE;
        !           120: }
        !           121: 
        !           122: /***************************************************************************
        !           123:  * InitApplication() 
        !           124:  *
        !           125:  * registers the window classes used by the application.
        !           126:  *
        !           127:  * Returns BOOL:      - TRUE if successful.
        !           128:  ***************************************************************************/
        !           129: 
        !           130: static BOOL InitApplication(           //* ENTRY:
        !           131:    HANDLE         hInst                //* instance handle
        !           132: ){                                     //* LOCAL:
        !           133:    WNDCLASS       wc;                  //* temp wind-class structure
        !           134: 
        !           135:    wc.style          = NULL;
        !           136:    wc.lpfnWndProc    = (WNDPROC)FrameWndProc;
        !           137:    wc.cbClsExtra     = 0;
        !           138:    wc.cbWndExtra     = 0;
        !           139:    wc.hInstance      = hInst;
        !           140:    wc.hIcon          = LoadIcon(hInst, MAKEINTRESOURCE(ID_APPLICATION));
        !           141:    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
        !           142:    wc.hbrBackground  = (HBRUSH)(COLOR_APPWORKSPACE + 1);
        !           143:    wc.lpszMenuName   = MAKEINTRESOURCE(ID_APPLICATION);
        !           144:    wc.lpszClassName  = szFrameClass;
        !           145: 
        !           146:    if (!RegisterClass(&wc))
        !           147:       return FALSE;
        !           148:                                        //* application item class
        !           149:    wc.style          = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW;
        !           150:    wc.lpfnWndProc    = (WNDPROC)ItemWndProc;
        !           151:    wc.hIcon          = NULL;
        !           152:    wc.cbWndExtra     = sizeof(APPITEMPTR);
        !           153:    wc.lpszMenuName   = NULL;
        !           154:    wc.lpszClassName  = szItemClass;
        !           155: 
        !           156:    if (!RegisterClass(&wc))
        !           157:       return FALSE;
        !           158: 
        !           159:    return TRUE;
        !           160: 
        !           161: }
        !           162: 
        !           163: /***************************************************************************
        !           164:  * InitInstance()
        !           165:  *
        !           166:  * create the main application window.
        !           167:  *
        !           168:  * Returns BOOL:      - TRUE if successful else FALSE.
        !           169:  ***************************************************************************/
        !           170: 
        !           171: static BOOL InitInstance(              //* ENTRY:
        !           172:    HANDLE         hInst                //* instance handel
        !           173: ){
        !           174:    
        !           175:    hAccTable = LoadAccelerators(hInst, MAKEINTRESOURCE(ID_APPLICATION));
        !           176: 
        !           177:    if (!(hwndFrame = 
        !           178:       CreateWindow(
        !           179:          szFrameClass, "",
        !           180:          WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
        !           181:          CW_USEDEFAULT, CW_USEDEFAULT,   
        !           182:          CW_USEDEFAULT, CW_USEDEFAULT,   
        !           183:          NULL, 
        !           184:          NULL, 
        !           185:          hInst, 
        !           186:          NULL
        !           187:       )))
        !           188:       return FALSE;                    //* ERROR return
        !           189: 
        !           190:    LoadString(hInst, IDS_APPNAME, szAppName, CBMESSAGEMAX);
        !           191:    DragAcceptFiles(hwndFrame, TRUE);   //* allow dragged and dropped files
        !           192: 
        !           193:        
        !           194:    return TRUE;                        //* SUCCESS return
        !           195: 
        !           196: }
        !           197: 
        !           198: /***************************************************************************
        !           199:  *  ProcessCmdLine()
        !           200:  *
        !           201:  *  process command line getting any command arguments.  
        !           202:  ***************************************************************************/
        !           203: 
        !           204: VOID ProcessCmdLine(LPSTR lpCmdLine)
        !           205: {                                     //* LOCAL:
        !           206:    OFSTRUCT       ofs;    
        !           207: 
        !           208: 
        !           209:    if (*lpCmdLine)                     
        !           210:    {                                   //* look for file extension
        !           211:       LPSTR lpstrExt = lpCmdLine;      //* pointer to file extension
        !           212: 
        !           213:       while (*lpstrExt && *lpstrExt != '.') 
        !           214:          lpstrExt = AnsiNext(lpstrExt);
        !           215: 
        !           216:       lstrcpy(szFileName, lpCmdLine);
        !           217:       if (!(*lpstrExt))                //* append default extension
        !           218:       {
        !           219:          lstrcat(szFileName,".");
        !           220:          lstrcat(szFileName,szDefExtension);
        !           221:       }
        !           222:                                        //* get the files fully 
        !           223:       OpenFile(szFileName, &ofs, OF_PARSE);//* qualified name
        !           224:       lstrcpy(szFileName, ofs.szPathName);
        !           225:    }
        !           226:    else 
        !           227:       *szFileName = NULL;
        !           228:                                        //* pass filename to main winproc
        !           229:    SendMessage(hwndFrame,WM_INIT,NULL,(LONG)NULL);
        !           230: 
        !           231: }
        !           232: 
        !           233: 
        !           234: /***************************************************************************
        !           235:  *  FrameWndProc()
        !           236:  *
        !           237:  *  Message handler for the application frame window.
        !           238:  *
        !           239:  *  Returns long - Variable, depends on message.
        !           240:  ***************************************************************************/
        !           241: 
        !           242: LONG  APIENTRY FrameWndProc(           //* ENTRY:
        !           243:    HWND           hwnd,                //* standard wind-proc parameters 
        !           244:    UINT           msg, 
        !           245:    DWORD          wParam, 
        !           246:    LONG           lParam
        !           247: ){                                     //* LOCAL:
        !           248:                                        //* ^ Document file name
        !           249:    static LHCLIENTDOC   lhcDoc;        //* Document Handle
        !           250:    static LPOLECLIENT   lpClient;      //* pointer to client 
        !           251:    static LPAPPSTREAM   lpStream;      //* pointer to stream vtbl
        !           252:    APPITEMPTR           pItem;         //* application item pointer
        !           253: 
        !           254:    switch (msg) 
        !           255:    {     
        !           256:       case WM_INIT:                    //* user defined message
        !           257:          if (!InitAsOleClient(hInst, hwnd, szFileName, &lhcDoc, &lpClient, &lpStream))
        !           258:             DestroyWindow(hwnd);
        !           259:          break;
        !           260:                                        //* the following three messages are
        !           261:                                        //* used to avoid problems with OLE
        !           262:                                        //* see the comment in object.h
        !           263:       case WM_DELETE:                  //* user defined message
        !           264:          pItem = (APPITEMPTR) wParam;  //* delete object
        !           265:          WaitForObject(pItem);
        !           266:          ObjDelete(pItem,OLE_OBJ_DELETE);
        !           267:          if (lParam)
        !           268:             cOleWait--;
        !           269:          break;
        !           270: 
        !           271:       case WM_ERROR:                   //* user defined message
        !           272:          ErrorMessage(wParam);         //* display error message
        !           273:          break;
        !           274: 
        !           275:       case WM_RETRY:                   //* user defined message
        !           276:          RetryMessage((APPITEMPTR)wParam, RD_RETRY | RD_CANCEL);
        !           277:          break;
        !           278: 
        !           279:       case WM_INITMENU:
        !           280:          UpdateMenu((HMENU)wParam);
        !           281:          break;
        !           282: 
        !           283:       case WM_COMMAND: 
        !           284:       {
        !           285:          WORD wID = LOWORD(wParam);
        !           286:    
        !           287:          pItem = GetTopItem();
        !           288: 
        !           289:          switch (wID) 
        !           290:          {
        !           291:             case IDM_NEW:
        !           292:                ANY_OBJECT_BUSY;
        !           293:                NewFile(szFileName,&lhcDoc,lpStream);
        !           294:                break;
        !           295: 
        !           296:             case IDM_OPEN:
        !           297:                ANY_OBJECT_BUSY;
        !           298:                MyOpenFile(szFileName,&lhcDoc,lpClient,lpStream);
        !           299:                break;
        !           300: 
        !           301:             case IDM_SAVE:
        !           302:                ANY_OBJECT_BUSY;
        !           303:                SaveFile(szFileName,lhcDoc,lpStream);
        !           304:                break;
        !           305: 
        !           306:             case IDM_SAVEAS:
        !           307:                ANY_OBJECT_BUSY;
        !           308:                SaveasFile(szFileName,lhcDoc,lpStream);
        !           309:                break;
        !           310: 
        !           311:             case IDM_ABOUT:
        !           312:                AboutBox();
        !           313:                break;
        !           314: 
        !           315:             case IDM_INSERT:
        !           316:                ANY_OBJECT_BUSY;
        !           317:                ObjInsert(lhcDoc, lpClient);
        !           318:                break;
        !           319: 
        !           320:             case IDM_INSERTFILE:
        !           321:                ANY_OBJECT_BUSY;
        !           322:                ObjCreateFromTemplate(lhcDoc,lpClient);
        !           323:                break;
        !           324: 
        !           325:             case IDM_PASTE:
        !           326:             case IDM_PASTELINK:
        !           327:                ANY_OBJECT_BUSY;
        !           328:                ObjPaste(wID == IDM_PASTE,lhcDoc,lpClient); 
        !           329:                break;
        !           330: 
        !           331:             case IDM_LINKS:
        !           332:                ANY_OBJECT_BUSY;
        !           333:                pItem = GetTopItem();
        !           334:                LinkProperties();
        !           335:                break;
        !           336:             
        !           337:             case IDM_EXIT:
        !           338:                ANY_OBJECT_BUSY;
        !           339:                SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
        !           340:                break;
        !           341: 
        !           342:             case IDM_COPY:
        !           343:             case IDM_CUT:
        !           344:                ANY_OBJECT_BUSY;
        !           345:              
        !           346:                if (!ObjCopy(pItem))
        !           347:                {
        !           348:                   ErrorMessage((wParam == IDM_CUT) ?
        !           349:                      E_CLIPBOARD_CUT_FAILED : E_CLIPBOARD_COPY_FAILED);
        !           350:                   break;
        !           351:                }   
        !           352: 
        !           353:                if (wParam == IDM_COPY)
        !           354:                   break;
        !           355: 
        !           356:             case IDM_CLEAR:            //* CUT falls through to clear
        !           357:                ANY_OBJECT_BUSY;
        !           358:                ClearItem(pItem);
        !           359:                break;
        !           360: 
        !           361:             case IDM_CLEARALL:
        !           362:                ANY_OBJECT_BUSY;
        !           363:                ClearAll(lhcDoc,OLE_OBJ_DELETE);
        !           364:                Dirty(DOC_DIRTY);
        !           365:                break;
        !           366: 
        !           367:             default:
        !           368:                if( (wParam >= IDM_VERBMIN) && (wParam <= IDM_VERBMAX) )
        !           369:                {    
        !           370:                   ANY_OBJECT_BUSY;
        !           371:                   ExecuteVerb(wParam - IDM_VERBMIN,pItem);
        !           372:                   break;
        !           373:                }
        !           374:                return DefWindowProc(hwnd, msg, wParam, lParam);
        !           375:          }
        !           376:          break;
        !           377:       }
        !           378: 
        !           379:       case WM_DROPFILES:
        !           380:          ANY_OBJECT_BUSY;
        !           381:          ObjCreateWrap((HANDLE)wParam, lhcDoc, lpClient);
        !           382:          break;
        !           383: 
        !           384:       case WM_CLOSE:
        !           385:          ANY_OBJECT_BUSY;   
        !           386:          if (!SaveAsNeeded(szFileName, lhcDoc, lpStream))
        !           387:             break;
        !           388:          DeregDoc(lhcDoc);
        !           389:          DestroyWindow(hwnd);
        !           390:          break;
        !           391: 
        !           392:       case WM_DESTROY:
        !           393:          EndStream(lpStream);
        !           394:          EndClient(lpClient);
        !           395:          PostQuitMessage(0);
        !           396:          break;
        !           397:                                        
        !           398:       case WM_QUERYENDSESSION:         //* don't let windows terminate 
        !           399:          return (QueryEndSession(szFileName,lhcDoc, lpStream));
        !           400: 
        !           401:       default:
        !           402:          return DefWindowProc(hwnd, msg, wParam, lParam);
        !           403:    } 
        !           404:    return 0L;
        !           405: 
        !           406: }
        !           407: 
        !           408: /***************************************************************************
        !           409:  * InitAsOleClient()
        !           410:  *
        !           411:  * Initiates the creation of stream and client vtbls.  These vtbls are very
        !           412:  * important for the proper operation of this application.  The stream vtbl
        !           413:  * lets the OLE librarys know where the location of the stream I/O routines
        !           414:  * reside.  The stream routines are used by OleLoadFromStream and the like.
        !           415:  * The client vtbl is used to hold the pointer to the CallBack function.
        !           416:  * IMPORTANT: both the client and the stream structures have pointers to 
        !           417:  * vtbls which have the pointers to the functions.  Therefore, it is 
        !           418:  * necessary to allocate space for the vtbl and the client structure
        !           419:  * which has the pointer to the vtbl.  
        !           420:  **************************************************************************/
        !           421: 
        !           422: static BOOL InitAsOleClient(           //* ENTRY:
        !           423:    HANDLE         hInstance,           //* applicaion instance handle
        !           424:    HWND           hwnd,                //* main window handle
        !           425:    PSTR           pFileName,           //* document file name
        !           426:    LHCLIENTDOC    *lhcDoc,             //* pointer to document Handle
        !           427:    LPOLECLIENT    *lpClient,           //* pointer to client pointer 
        !           428:    LPAPPSTREAM    *lpStream            //* pointer to APPSTREAM pointer
        !           429: ){
        !           430:                                        //* initiate client vtbl creation
        !           431:    if (!(*lpClient = InitClient(hInstance)))
        !           432:    {
        !           433:       SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
        !           434:       return FALSE;                    //* ERROR return
        !           435:    }
        !           436:                                        //* initiate stream vtbl creation
        !           437:    if (!(*lpStream = InitStream(hInstance)))
        !           438:    {
        !           439:       SendMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0L);
        !           440:       return FALSE;                    //* ERROR return
        !           441:    }
        !           442: 
        !           443:    if (*pFileName && RegDoc(pFileName,lhcDoc)
        !           444:        && LoadFile(pFileName,*lhcDoc,*lpClient,*lpStream)) 
        !           445:    {  
        !           446:       SetTitle(pFileName); 
        !           447:       return TRUE;                     //* SUCCESS return
        !           448:    }
        !           449: 
        !           450:    NewFile(pFileName, lhcDoc, *lpStream);
        !           451:    return TRUE;                        //* SUCCESS return
        !           452: 
        !           453: }                                      //* SUCCESS return
        !           454: 
        !           455: /****************************************************************************
        !           456:  *  InitClient()
        !           457:  *
        !           458:  *  Initialize the OLE client structure, create and fill the OLECLIENTVTBL 
        !           459:  *  structure.
        !           460:  *
        !           461:  *  Returns LPOLECLIENT - if successful a pointer to a client structure
        !           462:  *                        , otherwise NULL.
        !           463:  ***************************************************************************/
        !           464: 
        !           465: static LPOLECLIENT InitClient(         //* ENTRY:
        !           466:    HANDLE hInstance                    //* application instance handle
        !           467: ){                                     //* LOCAL:
        !           468:    LPOLECLIENT lpClient=NULL;          //* pointer to client struct
        !           469:                                        //* Allocate vtbls
        !           470:    if (!(lpClient = (LPOLECLIENT)GlobalLock(
        !           471:          GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLECLIENT))
        !           472:       )))
        !           473:       goto Error;                      //* ERROR jump        
        !           474: 
        !           475:    if (!(lpClient->lpvtbl = (LPOLECLIENTVTBL)GlobalLock(
        !           476:             GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLECLIENTVTBL))
        !           477:       )))
        !           478:       goto Error;                      //* ERROR jump
        !           479:                                        //* set the CALLBACK function
        !           480:                                        //* pointer
        !           481:    lpClient->lpvtbl->CallBack  = CallBack;
        !           482: 
        !           483:    return lpClient;                    //* SUCCESS return
        !           484:    
        !           485: Error:                                 //* ERROR Tag
        !           486:    
        !           487:    ErrorMessage(E_FAILED_TO_ALLOC);
        !           488:    EndClient(lpClient);                //* free any allocated space
        !           489: 
        !           490:    return NULL;                        //* ERROR return
        !           491:   
        !           492: }
        !           493:     
        !           494: /****************************************************************************
        !           495:  *  InitStream()
        !           496:  *
        !           497:  *  Create and fill the STREAMVTBL. Create a stream structure and initialize
        !           498:  *  pointer to stream vtbl.
        !           499:  *
        !           500:  *  Returns LPAPPSTREAM - if successful a pointer to a stream structure
        !           501:  *                        , otherwise NULL .     
        !           502:  ***************************************************************************/
        !           503: 
        !           504: static LPAPPSTREAM InitStream(         //* ENTRY:
        !           505:    HANDLE hInstance                    //* handle to application instance
        !           506: ){                                     //* LOCAL:
        !           507:    LPAPPSTREAM lpStream = NULL;        //* pointer to stream structure
        !           508: 
        !           509:    if (!(lpStream = (LPAPPSTREAM)GlobalLock(
        !           510:          GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(APPSTREAM))
        !           511:       )))
        !           512:       goto Error;                      //* ERROR jump
        !           513: 
        !           514:    if (!(lpStream->olestream.lpstbl = (LPOLESTREAMVTBL)GlobalLock(
        !           515:          GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizeof(OLESTREAMVTBL))
        !           516:       )))
        !           517:       goto Error;                      //* ERROR jump
        !           518: 
        !           519:                                        //* set stream func. pointers
        !           520:    lpStream->olestream.lpstbl->Get = (DWORD ( CALLBACK *)(LPOLESTREAM, VOID FAR *, DWORD)) ReadStream;
        !           521:    lpStream->olestream.lpstbl->Put = (DWORD ( CALLBACK *)(LPOLESTREAM, OLE_CONST VOID FAR *, DWORD)) WriteStream;
        !           522: 
        !           523:    return lpStream;                    //* SUCCESS return
        !           524: 
        !           525: Error:                                 //* ERROR Tag
        !           526: 
        !           527:    ErrorMessage(E_FAILED_TO_ALLOC);
        !           528:    EndStream(lpStream);
        !           529: 
        !           530:    return NULL;                        //* ERROR return
        !           531: 
        !           532: }
        !           533: 
        !           534: /***************************************************************************
        !           535:  *  UpdateMenu()
        !           536:  *
        !           537:  *  Enabling or disable menuitems based upon program state.
        !           538:  ***************************************************************************/
        !           539: 
        !           540: static VOID UpdateMenu(                //* ENTRY:
        !           541:    HMENU       hMenu                   //* menu handle to updated
        !           542: ){                                     //* LOCAL:
        !           543:    INT         mf;                     //* generic menu flag 
        !           544:    APPITEMPTR  paItem;                 //* app item pointer
        !           545:    HMENU       hSub;
        !           546:                                        //* there must be at least on object
        !           547:                                        //* for the following to be enabled
        !           548: 
        !           549:    paItem = GetTopItem() ; 
        !           550: 
        !           551:    mf = (paItem ? MF_ENABLED : MF_GRAYED);
        !           552:    EnableMenuItem(hMenu, IDM_CUT, mf); //* i.e. Cut,Copy,Clear,Clearall...
        !           553:    EnableMenuItem(hMenu, IDM_COPY, mf);
        !           554:    EnableMenuItem(hMenu, IDM_CLEAR, mf);
        !           555:    EnableMenuItem(hMenu, IDM_CLEARALL, mf);
        !           556:                                        //* enable links option only if there
        !           557:                                        //* is at least one linked object
        !           558:    EnableMenuItem(hMenu, IDM_LINKS, MF_GRAYED);
        !           559:    for (; paItem; paItem = GetNextItem(paItem))
        !           560:    {
        !           561:       if (paItem->otObject == OT_LINK)
        !           562:       {   
        !           563:          EnableMenuItem(hMenu, IDM_LINKS, MF_ENABLED);
        !           564:          break;
        !           565:       }
        !           566:    }
        !           567: 
        !           568:    if (hSub = GetSubMenu(hMenu,POS_EDITMENU))
        !           569:       UpdateObjectMenuItem(hSub);
        !           570: 
        !           571:    if (OleQueryCreateFromClip(STDFILEEDITING, olerender_draw, 0) == OLE_OK)
        !           572:       EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
        !           573:    else if (OleQueryCreateFromClip(STATICP, olerender_draw, 0) == OLE_OK)
        !           574:       EnableMenuItem(hMenu, IDM_PASTE, MF_ENABLED);
        !           575:    else  
        !           576:       EnableMenuItem(hMenu, IDM_PASTE, MF_GRAYED);
        !           577: 
        !           578:    if (OleQueryLinkFromClip(STDFILEEDITING, olerender_draw, 0) == OLE_OK)
        !           579:       EnableMenuItem(hMenu, IDM_PASTELINK, MF_ENABLED);
        !           580:    else  
        !           581:       EnableMenuItem(hMenu, IDM_PASTELINK, MF_GRAYED);
        !           582: 
        !           583: }
        !           584: 
        !           585: /***************************************************************************
        !           586:  *  NewFile()
        !           587:  *
        !           588:  *  Save the present document and open a new blank one. 
        !           589:  ***************************************************************************/
        !           590: 
        !           591: static VOID NewFile(                   //* ENTRY:
        !           592:    PSTR           pFileName,           //* open file name
        !           593:    LHCLIENTDOC    *lhcptrDoc,          //* pointer to client doc. handle
        !           594:    LPAPPSTREAM    lpStream             //* pointer to stream structure
        !           595: ){                                     //* LOCAL:
        !           596:    static CHAR  szUntitled[CBMESSAGEMAX] = "";//* "(Untitled)" string 
        !           597:    LHCLIENTDOC lhcDocNew;              //* handle for new doc.
        !           598: 
        !           599:    if (!(*szUntitled))
        !           600:       LoadString(hInst, IDS_UNTITLED, (LPSTR)szUntitled, CBMESSAGEMAX);
        !           601: 
        !           602:    if (SaveAsNeeded(pFileName, *lhcptrDoc, lpStream))
        !           603:    {                                   //* try to register new document
        !           604:       if (!RegDoc(szUntitled, &lhcDocNew)) 
        !           605:          return;                       //* before deregistring the old one
        !           606:       DeregDoc(*lhcptrDoc);            
        !           607:       *lhcptrDoc = lhcDocNew;
        !           608:       Dirty(DOC_CLEAN);                //* new document is clean
        !           609:       lstrcpy(pFileName,szUntitled);
        !           610:       SetTitle(pFileName);
        !           611:       iObjectNumber = 0;
        !           612:    }
        !           613: 
        !           614: }
        !           615: 
        !           616: /***************************************************************************
        !           617:  *  MyOpenFile()
        !           618:  *
        !           619:  *  Open a file and load it.  Notice that the new file is loaded before
        !           620:  *  the old is removed.  This is done to assure a succesful file load
        !           621:  *  before removing an existing document. 
        !           622:  ***************************************************************************/
        !           623: 
        !           624: static VOID MyOpenFile(                //* ENTRY:
        !           625:    PSTR           pFileName,           //* open file name
        !           626:    LHCLIENTDOC    *lhcptrDoc,          //* pointer to document handle
        !           627:    LPOLECLIENT    lpClient,            //* pointer to client structure
        !           628:    LPAPPSTREAM    lpStream             //* pointer to stream structure
        !           629: ){                                     //* LOCAL:
        !           630:    CHAR           szNewFile[CBPATHMAX];//* new file name buffer
        !           631:    LHCLIENTDOC    lhcDocNew;           //* handle of new document
        !           632:    APPITEMPTR     pItem;               //* hold top item
        !           633: 
        !           634:    if (SaveAsNeeded(pFileName, *lhcptrDoc, lpStream))
        !           635:    {
        !           636:       *szNewFile = NULL;
        !           637: 
        !           638:       if (!OfnGetName(hwndFrame, szNewFile, IDM_OPEN)) 
        !           639:          return;                       //* ERROR return
        !           640:       
        !           641:       if (!RegDoc(szNewFile,&lhcDocNew)) 
        !           642:          return;                       //* ERROR return
        !           643:       
        !           644:       pItem = GetTopItem();
        !           645:       ShowDoc(*lhcptrDoc,0);           //* make old doc objects hidden.
        !           646:                                        //* try to load the new file before
        !           647:       if (!LoadFile(szNewFile, lhcDocNew, lpClient, lpStream))
        !           648:       {                                //* before removing the old.
        !           649:          DeregDoc(lhcDocNew);          //* restore old document if new
        !           650:          SetTopItem(pItem);            //* file did not load
        !           651:          ShowDoc(*lhcptrDoc,1);
        !           652:          return;                       //* ERROR return
        !           653:       }
        !           654:       
        !           655:       DeregDoc(*lhcptrDoc);            //* deregister old document
        !           656:       *lhcptrDoc = lhcDocNew;
        !           657:       lstrcpy(pFileName,szNewFile);
        !           658:       SetTitle(pFileName);             //* set new title
        !           659:       Dirty(DOC_CLEAN);   
        !           660:    }
        !           661: 
        !           662: }                                      //* SUCCESS return
        !           663: 
        !           664: /***************************************************************************
        !           665:  *  SaveasFile()
        !           666:  *
        !           667:  * Prompt the user for a new file name.  Write the document to the new
        !           668:  * filename.
        !           669:  ***************************************************************************/
        !           670: 
        !           671: static VOID SaveasFile(                //* ENTRY:
        !           672:    PSTR           pFileName,           //* old filename
        !           673:    LHCLIENTDOC    lhcDoc,              //* document handle
        !           674:    LPAPPSTREAM    lpStream             //* pointer to stream structure
        !           675: ){
        !           676:    CHAR           szNewFile[CBPATHMAX];//* new file name
        !           677: 
        !           678:    *szNewFile = NULL;                  //* prompt user for new file name
        !           679:    if (!OfnGetName(hwndFrame, szNewFile, IDM_SAVEAS)) 
        !           680:       return;                          //* ERROR return
        !           681:                                        //* rename document
        !           682:    if (!SaveFile(szNewFile, lhcDoc, lpStream))
        !           683:       return;
        !           684: 
        !           685:    if (Error(OleRenameClientDoc(lhcDoc, szNewFile)))
        !           686:    {
        !           687:       ErrorMessage(W_FAILED_TO_NOTIFY);
        !           688:       return;                          //* ERROR return
        !           689:    }   
        !           690: 
        !           691:    lstrcpy(pFileName,szNewFile);
        !           692:    SetTitle(pFileName);
        !           693: 
        !           694: }                                      //* SUCCESS return
        !           695: 
        !           696: /***************************************************************************
        !           697:  *  SaveFile()
        !           698:  *
        !           699:  * Save a compound document file.  If the file is untitled, ask the user
        !           700:  * for a name and save the document to that file. 
        !           701:  ***************************************************************************/
        !           702: 
        !           703: static BOOL SaveFile(                  //* ENTRY:
        !           704:    PSTR           pFileName,           //* file to save document to
        !           705:    LHCLIENTDOC    lhcDoc,              //* OLE document handle
        !           706:    LPAPPSTREAM    lpStream             //* pointer to app. stream struct
        !           707: ){                                     //* LOCAL:
        !           708:    CHAR           szNewFile[CBPATHMAX];//* New file name strings
        !           709:    CHAR           szOemFileName[2*CBPATHMAX]; 
        !           710:    static CHAR    szUntitled[CBMESSAGEMAX] = "";
        !           711:    int            fh;                  //* file handle
        !           712:    
        !           713:    *szNewFile = NULL;
        !           714:    if (!(*szUntitled))
        !           715:       LoadString(hInst, IDS_UNTITLED, (LPSTR)szUntitled, CBMESSAGEMAX);
        !           716:                     
        !           717:    if (!lstrcmp(szUntitled, pFileName))//* get filename for the untitled case
        !           718:    {
        !           719:       if (!OfnGetName(hwndFrame, szNewFile, IDM_SAVEAS))
        !           720:          return FALSE;                 //* CANCEL return    
        !           721:       lstrcpy(pFileName,szNewFile);
        !           722:       SetTitle(pFileName);
        !           723:    }
        !           724: 
        !           725:    AnsiToOem(pFileName, szOemFileName);
        !           726:    if ((fh = _lcreat((LPSTR)szOemFileName, 0)) <= 0) 
        !           727:    {
        !           728:       ErrorMessage(E_INVALID_FILENAME);
        !           729:       return FALSE;                    //* ERROR return
        !           730:    }
        !           731: 
        !           732:    lpStream->fh = fh;
        !           733:                                        //* save file on disk
        !           734:    if (!WriteToFile(lpStream)) 
        !           735:    {
        !           736:       _lclose(fh);
        !           737:       ErrorMessage(E_FAILED_TO_SAVE_FILE);
        !           738:       return FALSE;                    //* ERROR return
        !           739:    }
        !           740:    _lclose(fh);
        !           741: 
        !           742:    if (Error(OleSavedClientDoc(lhcDoc)))
        !           743:    {
        !           744:       ErrorMessage(W_FAILED_TO_NOTIFY);
        !           745:       return FALSE;                    //* ERROR return
        !           746:    }
        !           747: 
        !           748:    Dirty(DOC_CLEAN);
        !           749:    return TRUE;                        //* SUCCESS return
        !           750: 
        !           751: } 
        !           752: 
        !           753: /***************************************************************************
        !           754:  *  LoadFile()
        !           755:  *
        !           756:  *  Load a document file from disk. 
        !           757:  ***************************************************************************/
        !           758: 
        !           759: static BOOL LoadFile(                  //* ENTRY:
        !           760:    PSTR           pFileName,           //* file name
        !           761:    LHCLIENTDOC    lhcDoc,              //* document handle
        !           762:    LPOLECLIENT    lpClient,            //* pointer to client structure
        !           763:    LPAPPSTREAM    lpStream             //* pointer to stream structure
        !           764: ){                                     //* LOCAL:
        !           765:                                        //* OEM file name
        !           766:    CHAR           szOemFileName[2*CBPATHMAX];      
        !           767:    int            fh;                  //* file handle
        !           768:    INT            iObjectNumberHold;   //* hold object number
        !           769: 
        !           770:    AnsiToOem(pFileName, szOemFileName);
        !           771:    if ((fh = _lopen(szOemFileName, OF_READ | OF_SHARE_DENY_WRITE)) == -1) 
        !           772:    {
        !           773:       ErrorMessage(E_FAILED_TO_READ_FILE);
        !           774:       return FALSE;                    //* ERROR return
        !           775:    }
        !           776: 
        !           777:    lpStream->fh = fh;
        !           778: 
        !           779:    iObjectNumberHold = iObjectNumber;  //* save object number so it can 
        !           780:    iObjectNumber     = 0;              //* be restored if read from file
        !           781:                                        //* fails
        !           782:    if (!ReadFromFile(lpStream, lhcDoc, lpClient)) 
        !           783:    {
        !           784:       _lclose(fh);
        !           785:       ErrorMessage(E_FAILED_TO_READ_FILE);
        !           786:       iObjectNumber = iObjectNumberHold;
        !           787:       return FALSE;                    //* ERROR return
        !           788:    }
        !           789:    return TRUE;                        //* SUCCESS return
        !           790: 
        !           791: } 
        !           792: 
        !           793: /***************************************************************************
        !           794:  *  RegDoc()
        !           795:  *
        !           796:  * Register the client document with the OLE library.
        !           797:  **************************************************************************/
        !           798: 
        !           799: static BOOL RegDoc(                    //* ENTRY:
        !           800:    PSTR           pFileName,           //* file name
        !           801:    LHCLIENTDOC    *lhcptrDoc           //* pointer to client document handle
        !           802: ){
        !           803: 
        !           804:    if (Error(OleRegisterClientDoc(szAppName, (LPSTR)pFileName, 0L, lhcptrDoc))) 
        !           805:    {
        !           806:       ErrorMessage(W_FAILED_TO_NOTIFY);
        !           807:       return FALSE;                    //* ERROR return
        !           808:    }
        !           809:    return TRUE;                        //* SUCCESS return
        !           810: 
        !           811: }    
        !           812: 
        !           813: /****************************************************************************
        !           814:  *  DeregDoc()
        !           815:  *
        !           816:  *  This function initiates the removal of all OLE objects from the
        !           817:  *  current document and deregisters the document with the OLE library.
        !           818:  ***************************************************************************/
        !           819: 
        !           820: static VOID DeregDoc(                  //* ENTRY:
        !           821:    LHCLIENTDOC    lhcDoc               //* client document handle
        !           822: ){
        !           823: 
        !           824:     if (lhcDoc) 
        !           825:     {                                  //* release all OLE objects
        !           826:         ClearAll(lhcDoc,OLE_OBJ_RELEASE);      //* and remove them from the screen
        !           827:         WaitForAllObjects();
        !           828:         if (Error(OleRevokeClientDoc(lhcDoc)))
        !           829:             ErrorMessage(W_FAILED_TO_NOTIFY);
        !           830:     }
        !           831: 
        !           832: }                                      //* SUCCESS return
        !           833: 
        !           834: /***************************************************************************
        !           835:  *  ClearAll()
        !           836:  *
        !           837:  * This function will destroy all of the item windows in the current 
        !           838:  * document and delete all OLE objects.  The loop is basically an enum 
        !           839:  * of all child windows.
        !           840:  **************************************************************************/
        !           841: 
        !           842: static VOID ClearAll(                  //* ENTRY:
        !           843:    LHCLIENTDOC    lhcDoc,              //* application document handle
        !           844:    BOOL           fDelete              //* Delete / Release
        !           845: ){                                     //* LOCAL:
        !           846:    APPITEMPTR     pItemNext;           //* working handles
        !           847:    APPITEMPTR     pItem;               //* pointer to application item
        !           848:    
        !           849:    pItem = GetTopItem();
        !           850: 
        !           851:    while (pItem)     
        !           852:    {  
        !           853:       pItemNext = GetNextItem(pItem);
        !           854:       if (pItem->lhcDoc == lhcDoc)
        !           855:          ObjDelete(pItem, fDelete); 
        !           856:       pItem = pItemNext;
        !           857:    }
        !           858: 
        !           859: }  
        !           860:                                     //* SUCCESS return
        !           861: /***************************************************************************
        !           862:  * ClearItem()
        !           863:  *
        !           864:  * This function will destroy an item window, and make the 
        !           865:  * next window active.
        !           866:  **************************************************************************/
        !           867: 
        !           868: VOID  FAR ClearItem(                 //* ENTRY:
        !           869:    APPITEMPTR     pItem                //* application item pointer
        !           870: ){                                   
        !           871: 
        !           872:    pItem->fVisible = FALSE;
        !           873:    SetTopItem(GetNextActiveItem());
        !           874:    ObjDelete(pItem, OLE_OBJ_DELETE);
        !           875:    Dirty(DOC_DIRTY);
        !           876: 
        !           877: }
        !           878: 
        !           879: /****************************************************************************
        !           880:  *  SaveAsNeeded()
        !           881:  *
        !           882:  *  This function will have the file saved if and only
        !           883:  *  if the document has been modified. If the fDirty flag has
        !           884:  *  been set to TRUE, then the document needs to be saved.
        !           885:  *
        !           886:  *  Returns: BOOL -  TRUE if document doesn't need saving or if the
        !           887:  *                   document has been saved successfully.
        !           888:  ***************************************************************************/
        !           889: 
        !           890: static BOOL SaveAsNeeded(              //* ENTRY:
        !           891:    PSTR           pFileName,           //* file to save
        !           892:    LHCLIENTDOC    lhcDoc,              //* OLE doc handle
        !           893:    LPAPPSTREAM    lpStream             //* pointer to OLE stream vtbl ... 
        !           894: ){                                     //* LOCAL:
        !           895:    CHAR           sz[CBMESSAGEMAX];    //* work strings 
        !           896:    CHAR           sz2[CBMESSAGEMAX + CBPATHMAX]; 
        !           897: 
        !           898:    if (Dirty(DOC_QUERY))               //* if doc is clean don't bother
        !           899:    {
        !           900: 
        !           901:       LoadString(hInst, IDS_MAYBESAVE, sz, CBMESSAGEMAX);
        !           902:       wsprintf(sz2, sz, (LPSTR)pFileName );
        !           903: 
        !           904:       switch (MessageBox(hwndFrame, sz2, szAppName, MB_YESNOCANCEL | MB_ICONQUESTION)) 
        !           905:       {
        !           906: 
        !           907:          case IDCANCEL:
        !           908:             return FALSE;              //* CANCEL return
        !           909: 
        !           910:          case IDYES:
        !           911:             return (SaveFile(pFileName,lhcDoc,lpStream));
        !           912: 
        !           913:          default:
        !           914:             break;
        !           915:       }
        !           916:    }
        !           917:    return TRUE;                        //* SUCCESS return
        !           918: 
        !           919: }
        !           920: 
        !           921: /****************************************************************************
        !           922:  *  SetTitle()
        !           923:  *
        !           924:  *  Set the window caption to the current file name. If szFileName is 
        !           925:  *  NULL, the caption will be set to "(Untitled)".
        !           926:  ***************************************************************************/
        !           927: 
        !           928: static VOID SetTitle(                  //* ENTRY:
        !           929:    PSTR           pFileName            //* file name
        !           930: ){                                     //* LOCAL
        !           931:                                        //* window title string
        !           932:    CHAR           szTitle[CBMESSAGEMAX + CBPATHMAX];
        !           933: 
        !           934:    wsprintf(szTitle, "%s - %s", (LPSTR)szAppName, (LPSTR)pFileName);
        !           935:    SetWindowText(hwndFrame, szTitle);        
        !           936: 
        !           937: }
        !           938: 
        !           939: /***************************************************************************
        !           940:  *  EndClient()
        !           941:  *
        !           942:  *  Perform cleanup prior to app termination. The OLECLIENT
        !           943:  *  memory blocks and procedure instance thunks freed.
        !           944:  **************************************************************************/
        !           945: 
        !           946: static VOID EndStream(                 //* ENTRY:
        !           947:    LPAPPSTREAM    lpStream             //* pointer to stream structure
        !           948: ){                                     //* LOCAL:
        !           949:    HANDLE         hGeneric;            //* temp handle
        !           950: 
        !           951:     if (lpStream)                      //* is there a STREAM struct?  
        !           952:     {
        !           953:       if (lpStream->olestream.lpstbl)
        !           954:       {
        !           955:          FreeProcInstance((FARPROC)lpStream->olestream.lpstbl->Get);
        !           956:          FreeProcInstance((FARPROC)lpStream->olestream.lpstbl->Put);
        !           957:          hGeneric = GlobalHandle((LPSTR)lpStream->olestream.lpstbl);
        !           958:          GlobalUnlock(hGeneric);
        !           959:          GlobalFree(hGeneric);
        !           960:       }
        !           961:       hGeneric = GlobalHandle((LPSTR)lpStream);
        !           962:       GlobalUnlock(hGeneric);
        !           963:       GlobalFree(hGeneric);
        !           964:     }
        !           965: 
        !           966: }                                      //* SUCCESS return
        !           967: 
        !           968: /***************************************************************************
        !           969:  *  EndClient()
        !           970:  *
        !           971:  *  Perform cleanup prior to app termination. The OLECLIENT
        !           972:  *  memory blocks and procedure instance thunks are freed.
        !           973:  **************************************************************************/
        !           974: 
        !           975: static VOID EndClient(                 //* ENTRY:
        !           976:    LPOLECLIENT    lpClient             //* pointer to client structure
        !           977: ){                                     //* LOCAL:
        !           978:    HANDLE         hGeneric;            //* temp handle
        !           979: 
        !           980:    if (lpClient)                       //* is there a client structure
        !           981:    {
        !           982:       if (lpClient->lpvtbl)
        !           983:       {
        !           984:          FreeProcInstance(lpClient->lpvtbl->CallBack);
        !           985:          hGeneric = GlobalHandle((LPSTR)lpClient->lpvtbl);
        !           986:          GlobalUnlock(hGeneric);
        !           987:          GlobalFree(hGeneric);
        !           988:       }
        !           989:       hGeneric = GlobalHandle((LPSTR)lpClient);
        !           990:       GlobalUnlock(hGeneric);
        !           991:       GlobalFree(hGeneric);
        !           992:    }
        !           993: 
        !           994: }                                      //* SUCCESS return
        !           995: 
        !           996: /****************************************************************************
        !           997:  * QueryEndSession()
        !           998:  ***************************************************************************/
        !           999: 
        !          1000: static LONG QueryEndSession(           //* ENTRY:
        !          1001:    PSTR           pFileName,           //* document name
        !          1002:    LHCLIENTDOC    lhcDoc,              //* client document handle
        !          1003:    LPAPPSTREAM    lpStream             //* application stream pointer
        !          1004: ){                                     //* LOCAL:
        !          1005:    APPITEMPTR     pItem;               //* application item pointer
        !          1006:       
        !          1007: 
        !          1008:    for (pItem = GetTopItem(); pItem; pItem = GetNextItem(pItem))
        !          1009:       if (OleQueryOpen(pItem->lpObject) == OLE_OK)
        !          1010:       {
        !          1011:          MessageBox(hwndFrame,"Exit CliDemo before closing Windows",
        !          1012:                szAppName, MB_OK | MB_ICONSTOP);
        !          1013:          return 0L;
        !          1014:       }
        !          1015: 
        !          1016:    if (!SaveAsNeeded(pFileName, lhcDoc, lpStream))
        !          1017:       return 0L;
        !          1018:    DeregDoc(lhcDoc);
        !          1019:    return 1L;
        !          1020: 
        !          1021: }
        !          1022: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.