2374 lines
75 KiB
C
2374 lines
75 KiB
C
/*-----------------------------------------------------------------------------+
|
||
| OLE1.C |
|
||
| |
|
||
| (C) Copyright Microsoft Corporation 1991. All rights reserved. |
|
||
| |
|
||
| Revision History |
|
||
| 02-Jun-94 AndrewBe created, based upon the OLE1 SERVER.C |
|
||
| |
|
||
+-----------------------------------------------------------------------------*/
|
||
|
||
#ifdef OLE1_HACK
|
||
|
||
/* This was originally server.c in the OLE1 Media Player.
|
||
* It is here somewhat munged to bolt onto the side of the OLE2 Media Player,
|
||
* to get around the fact that OLE1/OLE2 interoperability is broken in Daytona.
|
||
*
|
||
* The OLE2 interface is Unicode, whereas the OLE1 interface is ANSI.
|
||
* This accounts for some, though probably not all, of the horrors that are
|
||
* about to unfold before your eyes.
|
||
*/
|
||
|
||
#ifndef UNICODE
|
||
#error This file assumes that UNICODE is defined.
|
||
#endif
|
||
|
||
#undef UNICODE
|
||
|
||
#define SERVERONLY
|
||
#include <windows.h>
|
||
#include <commdlg.h>
|
||
#include <mmsystem.h>
|
||
#include <port1632.h>
|
||
#include <shellapi.h>
|
||
#include <string.h>
|
||
#include <ole.h>
|
||
#include "mplayer.h"
|
||
#include "ole1.h"
|
||
|
||
//////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// (c) Copyright Microsoft Corp. 1991 - All Rights Reserved
|
||
//
|
||
/////////////////////////////////////////////////////////////////////////
|
||
#include <stdlib.h>
|
||
#undef _MAX_PATH // ??? someone hacking?
|
||
#undef _MAX_DIR // ??? someone hacking?
|
||
#undef _MAX_FNAME // ??? someone hacking?
|
||
#undef _MAX_EXT // ??? someone hacking?
|
||
#include "toolbar.h"
|
||
|
||
DWORD gDocVersion = DOC_VERSION_NONE;
|
||
|
||
extern PSTR gpchFilter;
|
||
|
||
#define WAITDIFFERENTLY // dont ask....
|
||
|
||
extern UINT gwPlaybarHeight; // tell playbar how tall to make itself
|
||
// so it covers the title
|
||
STATICDT BOOL gfMouseUpSeen = FALSE; // OK to close play in place?
|
||
STATICDT BOOL gfKeyStateUpSeen = FALSE; // OK to close play in place?
|
||
|
||
/* Height of picture given to client to be pasted */
|
||
STATICDT UINT gwPastedHeight;
|
||
|
||
/* DELAYED BROKEN LINK */
|
||
extern WCHAR gachFile[MAX_PATH];
|
||
STATICDT CHAR gachDeviceA[80];
|
||
STATICDT WCHAR gachDeviceW[80];
|
||
extern BOOL gfBrokenLink;
|
||
STATICDT int gerr;
|
||
STATICDT HWND ghwndClient = NULL;
|
||
STATICDT RECT grcClient;
|
||
/* ........................ */
|
||
|
||
extern HANDLE ghInst;
|
||
extern POINT gptBtnSize;
|
||
|
||
#define abs(x) ((x) < 0 ? -(x) : (x))
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
#ifndef GetWS
|
||
#define GetWS(hwnd) GetWindowLongPtr(hwnd, GWL_STYLE)
|
||
#define PutWS(hwnd, f) SetWindowLongPtr(hwnd, GWL_STYLE, f)
|
||
#define TestWS(hwnd,f) (GetWS(hwnd) & f)
|
||
#define SetWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) | f)
|
||
#define ClrWS(hwnd, f) PutWS(hwnd, GetWS(hwnd) & ~(f))
|
||
#endif
|
||
|
||
/************************************************************************
|
||
Important Note:
|
||
|
||
No method should ever dispatch a DDE message or allow a DDE message to
|
||
be dispatched.
|
||
Therefore, no method should ever enter a message dispatch loop.
|
||
Also, a method should not show a dialog or message box, because the
|
||
processing of the dialog box messages will allow DDE messages to be
|
||
dispatched.
|
||
|
||
the hacky way we enforce this is with the global <gfErrorBox>. see
|
||
errorbox.c and all the "gfErrorBox++"'s in this file.
|
||
|
||
Note that we are an exe, not a DLL, so this does not rely on
|
||
non-preemptive scheduling. Should be OK on NT too.
|
||
|
||
***************************************************************************/
|
||
|
||
|
||
/**************************************************************************
|
||
|
||
GLOBALS
|
||
|
||
***************************************************************************/
|
||
|
||
STATICDT BOOL gfUnblockServer; //
|
||
STATICDT int nBlockCount;
|
||
|
||
#ifndef _WIN32
|
||
HHOOK hHookMouse; // Mouse hook handle.
|
||
HOOKPROC fpMouseHook; // Mouse hook proc address.
|
||
#else
|
||
|
||
/*
|
||
** These functions are exported from mciole32.dll.
|
||
**
|
||
*/
|
||
typedef BOOL (*LPINSTALLHOOK)( HWND, DWORD );
|
||
typedef BOOL (*LPREMOVEHOOK)( VOID );
|
||
|
||
LPINSTALLHOOK fpInstallHook;
|
||
LPREMOVEHOOK fpRemoveHook;
|
||
BOOL fHookInstalled = FALSE;
|
||
|
||
#endif
|
||
|
||
HWND ghwndFocusSave; // saved focus window
|
||
|
||
HMODULE hMciOle;
|
||
|
||
OLECLIPFORMAT cfLink;
|
||
OLECLIPFORMAT cfOwnerLink;
|
||
OLECLIPFORMAT cfNative;
|
||
|
||
OLESERVERDOCVTBL docVTbl;
|
||
OLEOBJECTVTBL itemVTbl;
|
||
OLESERVERVTBL srvrVTbl;
|
||
|
||
SRVR gSrvr;
|
||
OLE1DOC gDoc;
|
||
ITEM gItem;
|
||
|
||
/**************************************************************************
|
||
|
||
STRINGS
|
||
|
||
***************************************************************************/
|
||
|
||
#ifdef _WIN32
|
||
STATICDT ANSI_SZCODE aszInstallHook[] = "InstallHook";
|
||
STATICDT ANSI_SZCODE aszRemoveHook[] = "RemoveHook";
|
||
#endif
|
||
|
||
extern ANSI_SZCODE aszAppName[] = "MPlayer";
|
||
|
||
|
||
/* Formatting characters for string macros:
|
||
*/
|
||
|
||
STATICDT WCHAR szFormatAnsiToUnicode[] = L"%hs";
|
||
STATICDT CHAR szFormatUnicodeToAnsi[] = "%ws";
|
||
STATICDT WCHAR szFormatUnicodeToUnicode[] = L"%ws";
|
||
|
||
/* Unicode - ANSI string-copying macros:
|
||
*/
|
||
|
||
#define COPYSTRINGA2W(pTarget, pSource) wsprintfW(pTarget, szFormatAnsiToUnicode, pSource)
|
||
#define COPYSTRINGW2A(pTarget, pSource) wsprintfA(pTarget, szFormatUnicodeToAnsi, pSource)
|
||
#define COPYSTRINGW2W(pTarget, pSource) wsprintfW(pTarget, szFormatUnicodeToUnicode, pSource)
|
||
|
||
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL Ole1PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc);
|
||
void FAR PASCAL Ole1EndPlayInPlace(HWND hwndApp);
|
||
OLESTATUS FAR PASCAL ItemSetData1(LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata);
|
||
BOOL NEAR PASCAL ScanCmdLine(LPSTR szCmdLine);
|
||
STATICFN int NEAR PASCAL Ole1ReallyDoVerb(LPOLEOBJECT lpobj, UINT verb, BOOL fShow, BOOL fActivate);
|
||
STATICFN OLESTATUS NEAR PASCAL SetDataPartII(LPWSTR szFile, LPWSTR szDevice);
|
||
STATICFN BOOL NetParseFile(LPSTR szFile, LPSTR szPath);
|
||
|
||
int FAR PASCAL ParseOptions(LPTSTR pOpt);
|
||
extern BOOL FindRealFileName(LPTSTR szFile, int iLen);
|
||
HWND TopWindow(HWND hwnd);
|
||
void PASCAL DinkWithWindowStyles(HWND hwnd, BOOL fRestore);
|
||
HANDLE GetLink( VOID );
|
||
|
||
/*
|
||
*
|
||
*/
|
||
VOID SetDocVersion( DWORD DocVersion )
|
||
{
|
||
#if DBG
|
||
if( ( DocVersion != DOC_VERSION_NONE ) && ( gDocVersion != DOC_VERSION_NONE ) )
|
||
{
|
||
DPF0( "Expected gDocVersion == 0!! It's %u\n", gDocVersion );
|
||
}
|
||
#endif /* DBG */
|
||
|
||
gDocVersion = DocVersion;
|
||
|
||
DPF0( "gDocVersion set to %u\n", DocVersion );
|
||
}
|
||
|
||
|
||
/**************************************************************************
|
||
* Ole1UpdateObject() - handle the update of the object
|
||
*
|
||
***************************************************************************/
|
||
|
||
void Ole1UpdateObject(void)
|
||
{
|
||
if (gfEmbeddedObject) {
|
||
//
|
||
// some client's (ie Excel 3.00 and PowerPoint 1.0) dont
|
||
// handle saved notifications, they expect to get a
|
||
// OLE_CLOSED message.
|
||
//
|
||
// we will send a OLE_CLOSED message right before we
|
||
// revoke the DOC iff gfDirty == -1, see FileNew()
|
||
//
|
||
if (SendChangeMsg(OLE_SAVED) == OLE_OK)
|
||
CleanObject();
|
||
else {
|
||
DPF("Unable to update object, setting gfDirty = -1\n");
|
||
gfDirty = -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*
|
||
*
|
||
*/
|
||
BOOL FAR PASCAL Ole1FixLinkDialog(LPSTR szFile, LPSTR szDevice, int iLen)
|
||
{
|
||
UINT wDevice;
|
||
char achFile[MAX_PATH + 1]; /* file or device name buffer */
|
||
char achTitle[80]; /* string holding the title bar name */
|
||
HWND hwndFocus;
|
||
OPENFILENAME ofn;
|
||
BOOL f;
|
||
|
||
static SZCODE aszDialog[] = "MciOpenDialog"; // in open.c too.
|
||
|
||
//
|
||
// I GIVE UP!!! Put up an open dlg box and let them find it themselves!
|
||
//
|
||
|
||
// If we haven't initialized the device menu yet, do it now.
|
||
if (gwNumDevices == 0)
|
||
InitDeviceMenu();
|
||
|
||
// find out the device number for the specifed device
|
||
wDevice = gwCurDevice;
|
||
|
||
LoadString(ghInst, IDS_FINDFILE, achFile, CHAR_COUNT(achFile));
|
||
wsprintf(achTitle, achFile, FileName(szFile)); // title bar for locate dlg
|
||
|
||
/* Start with the bogus file name */
|
||
lstrcpy(achFile, FileName(szFile));
|
||
|
||
/* Set up the ofn struct */
|
||
ofn.lStructSize = sizeof(OPENFILENAME);
|
||
|
||
/* MUST use ActiveWindow to make user deal with us NOW in case of multiple*/
|
||
/* broken links */
|
||
ofn.hwndOwner = GetActiveWindow();
|
||
|
||
ofn.hInstance = ghInst;
|
||
ofn.lpstrFilter = gpchFilter;
|
||
ofn.lpstrCustomFilter = NULL;
|
||
ofn.nMaxCustFilter = 0;
|
||
|
||
if (wDevice == 0)
|
||
ofn.nFilterIndex = gwNumDevices+1; // select "All Files"
|
||
else
|
||
ofn.nFilterIndex = wDevice;
|
||
|
||
ofn.lpstrFile = achFile;
|
||
ofn.nMaxFile = sizeof(achFile);
|
||
ofn.lpstrFileTitle = NULL;
|
||
ofn.nMaxFileTitle = 0;
|
||
ofn.lpstrInitialDir = NULL;
|
||
ofn.lpstrTitle = achTitle;
|
||
|
||
// ofn.Flags = OFN_ENABLETEMPLATE | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
|
||
ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
|
||
OFN_SHAREAWARE | OFN_PATHMUSTEXIST;
|
||
|
||
ofn.nFileOffset = 0;
|
||
ofn.nFileExtension = 0;
|
||
ofn.lpstrDefExt = NULL;
|
||
ofn.lCustData = 0;
|
||
ofn.lpfnHook = NULL;
|
||
// ofn.lpTemplateName = aszDialog;
|
||
ofn.lpTemplateName = NULL;
|
||
|
||
// Show the cursor in case PowerPig is hiding it
|
||
ShowCursor(TRUE);
|
||
|
||
hwndFocus = GetFocus();
|
||
|
||
/* Let the user pick a filename */
|
||
BlockServer();
|
||
gfErrorBox++;
|
||
f = GetOpenFileName(&ofn);
|
||
if (f) {
|
||
lstrcpyn(szFile, achFile, iLen);
|
||
gfDirty = TRUE; // make sure the object is dirty now
|
||
}
|
||
gfErrorBox--;
|
||
UnblockServer();
|
||
|
||
SetFocus(hwndFocus);
|
||
|
||
// Put cursor back how it used to be
|
||
ShowCursor(FALSE);
|
||
|
||
return f;
|
||
}
|
||
|
||
|
||
/**************************************************************************/
|
||
/* We've just gotten our delayed message that we need to bring up an open */
|
||
/* dialog to let the user fix the broken link, and then we can finish the */
|
||
/* SetData and the DoVerb. */
|
||
/**************************************************************************/
|
||
void FAR PASCAL DelayedFixLink(UINT verb, BOOL fShow, BOOL fActivate)
|
||
{
|
||
CHAR achFileA[MAX_PATH];
|
||
|
||
gfBrokenLink = FALSE;
|
||
|
||
COPYSTRINGW2A(gachDeviceA, garMciDevices[gwCurDevice].szDevice);
|
||
COPYSTRINGW2W(gachDeviceW, garMciDevices[gwCurDevice].szDevice);
|
||
COPYSTRINGW2A(achFileA, gachFile);
|
||
|
||
/* Something goes wrong? Get out of here and give up. */
|
||
if (!Ole1FixLinkDialog(achFileA, gachDeviceA, CHAR_COUNT(achFileA)) ||
|
||
SetDataPartII(gachFile, gachDeviceW) != OLE_OK)
|
||
PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
|
||
else
|
||
Ole1ReallyDoVerb(NULL, verb, fShow, fActivate);
|
||
}
|
||
|
||
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
BOOL FAR PASCAL InitOle1Server(HWND hwnd, HANDLE hInst)
|
||
{
|
||
long cb;
|
||
int err;
|
||
char aszPlay[40];
|
||
char aszEdit[40];
|
||
|
||
#ifdef _WIN32
|
||
/*
|
||
** On NT we have to install a global mouse HookProc which has to
|
||
** in a DLL. Also we have to tell the DLL which process/thread we are
|
||
** interested in, therefore let the DLL install the HookProc. When the
|
||
** HookProc detects an "interesting" mouse message it stops the
|
||
** device from playing. However, the device "stopping" function is
|
||
** inside mplayer, so we have to export it so that the HookProc can
|
||
** call it.
|
||
*/
|
||
if ( hMciOle ) {
|
||
|
||
fpInstallHook = (LPINSTALLHOOK)GetProcAddress(hMciOle, aszInstallHook);
|
||
fpRemoveHook = (LPREMOVEHOOK)GetProcAddress(hMciOle, aszRemoveHook);
|
||
}
|
||
else {
|
||
fpInstallHook = NULL;
|
||
fpRemoveHook = NULL;
|
||
}
|
||
#endif
|
||
|
||
cfLink = RegisterClipboardFormat("Link");
|
||
cfOwnerLink = RegisterClipboardFormat("OwnerLink");
|
||
|
||
// The scheme of casting everything to FARPROC relies on then being able
|
||
// to do a cast on lvalue later to make it all work. Last time I checked
|
||
// that wouldn't wash on MIPS. So we have be a little cleaner.
|
||
#define MPI(fn) MakeProcInstance((FARPROC)fn, hInst);
|
||
|
||
//
|
||
// srvr vtable.
|
||
//
|
||
*(FARPROC*)&srvrVTbl.Open = MPI(SrvrOpen);
|
||
*(FARPROC*)&srvrVTbl.Create = MPI(SrvrCreate);
|
||
*(FARPROC*)&srvrVTbl.CreateFromTemplate = MPI(SrvrCreateFromTemplate);
|
||
*(FARPROC*)&srvrVTbl.Edit = MPI(SrvrEdit);
|
||
*(FARPROC*)&srvrVTbl.Exit = MPI(SrvrExit);
|
||
*(FARPROC*)&srvrVTbl.Release = MPI(SrvrRelease1);
|
||
*(FARPROC*)&srvrVTbl.Execute = MPI(SrvrExecute);
|
||
|
||
//
|
||
// doc table
|
||
//
|
||
*(FARPROC*)&docVTbl.Save = MPI(DocSave);
|
||
*(FARPROC*)&docVTbl.Close = MPI(DocClose);
|
||
*(FARPROC*)&docVTbl.GetObject = MPI(DocGetObject);
|
||
*(FARPROC*)&docVTbl.Release = MPI(DocRelease);
|
||
*(FARPROC*)&docVTbl.SetHostNames = MPI(DocSetHostNames);
|
||
*(FARPROC*)&docVTbl.SetDocDimensions = MPI(DocSetDocDimensions);
|
||
*(FARPROC*)&docVTbl.SetColorScheme = MPI(DocSetColorScheme);
|
||
*(FARPROC*)&docVTbl.Execute = MPI(DocExecute);
|
||
|
||
//
|
||
// item table.
|
||
//
|
||
*(FARPROC*)&itemVTbl.Show = MPI(ItemOpen);
|
||
*(FARPROC*)&itemVTbl.DoVerb = MPI(ItemDoVerb);
|
||
*(FARPROC*)&itemVTbl.GetData = MPI(ItemGetData);
|
||
*(FARPROC*)&itemVTbl.SetData = MPI(ItemSetData1);
|
||
*(FARPROC*)&itemVTbl.Release = MPI(ItemRelease);
|
||
*(FARPROC*)&itemVTbl.SetTargetDevice = MPI(ItemSetTargetDevice);
|
||
*(FARPROC*)&itemVTbl.EnumFormats = MPI(ItemEnumFormats);
|
||
*(FARPROC*)&itemVTbl.SetBounds = MPI(ItemSetBounds);
|
||
*(FARPROC*)&itemVTbl.SetColorScheme = MPI(ItemSetColorScheme);
|
||
|
||
gSrvr.lhsrvr = 0L;
|
||
gDoc.lhdoc = 0L;
|
||
gItem.lpoleclient = NULL;
|
||
|
||
gSrvr.olesrvr.lpvtbl = &srvrVTbl;
|
||
|
||
err = OleRegisterServer(aszAppName, (LPOLESERVER)&gSrvr,
|
||
&gSrvr.lhsrvr, hInst, OLE_SERVER_MULTI);
|
||
|
||
if (err != OLE_OK) {
|
||
gSrvr.lhsrvr = 0L;
|
||
Error(ghwndApp, IDS_CANTSTARTOLE);
|
||
return TRUE;
|
||
}
|
||
gSrvr.hwnd = hwnd; // corresponding main window
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL TermServer(void)
|
||
{
|
||
if (hMciOle)
|
||
FreeLibrary(hMciOle);
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL NewDoc(BOOL fUntitled)
|
||
{
|
||
//
|
||
// some client's (ie Excel 3.00 and PowerPoint 1.0) dont
|
||
// handle saved notifications, they expect to get a
|
||
// OLE_CLOSED message.
|
||
//
|
||
// if the user has chosen to update the object, but the client did
|
||
// not then send a OLE_CLOSED message.
|
||
//
|
||
if (gfEmbeddedObject && IsObjectDirty()) {
|
||
|
||
UpdateObject();
|
||
|
||
if (gfDirty == -1)
|
||
SendChangeMsg(OLE_CLOSED);
|
||
|
||
CleanObject();
|
||
}
|
||
|
||
BlockServer();
|
||
/* !!! If PlayMCI errors, and we close the client, we get called, but */
|
||
/* we can't CloseMCI now or we'll explode. */
|
||
if (!gfErrorBox && IsWindowEnabled(ghwndApp))
|
||
CloseMCI(TRUE);
|
||
|
||
// app.c has a better way of not dispatching evil timer messages
|
||
#if 0
|
||
// A leftover WM_TIMER is UAE'ing Packager going down
|
||
if (PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE | PM_NOYIELD)) {
|
||
DPF("Ack! *** We removed a WM_TIMER msg from someone's queue!\n");
|
||
}
|
||
#endif
|
||
|
||
UnblockServer();
|
||
|
||
RevokeDocument();
|
||
|
||
//
|
||
// register a "untitled" doc?????
|
||
//
|
||
if (fUntitled) {
|
||
LoadStringW(ghInst, IDS_UNTITLED, (LPWSTR)gachFileDevice, 40);
|
||
RegisterDocument(0,0);
|
||
}
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL ServerUnblock()
|
||
{
|
||
if (gfUnblockServer)
|
||
{
|
||
BOOL fMoreMsgs = TRUE;
|
||
|
||
while (fMoreMsgs && gSrvr.lhsrvr)
|
||
OleUnblockServer (gSrvr.lhsrvr, &fMoreMsgs);
|
||
|
||
// We have taken care of all the messages in the OLE queue
|
||
gfUnblockServer = FALSE;
|
||
}
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL BlockServer()
|
||
{
|
||
// gfErrorBox++;
|
||
|
||
if (nBlockCount++ == 0)
|
||
OleBlockServer(gSrvr.lhsrvr);
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL UnblockServer()
|
||
{
|
||
/* Don't wrap around! */
|
||
if (!nBlockCount)
|
||
return;
|
||
|
||
if (--nBlockCount == 0)
|
||
gfUnblockServer = TRUE;
|
||
|
||
// gfErrorBox--;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL TerminateServer(void)
|
||
{
|
||
LHSERVER lhsrvr;
|
||
|
||
if (gfPlayingInPlace)
|
||
Ole1EndPlayInPlace(ghwndApp);
|
||
|
||
// Is this right?
|
||
DPF("IDM_EXIT: Revoking server...\n");
|
||
|
||
lhsrvr = gSrvr.lhsrvr;
|
||
if (lhsrvr) {
|
||
ServerUnblock();
|
||
gSrvr.lhsrvr = (LHSERVER)0;
|
||
////////ShowWindow(ghwndApp,SW_HIDE); // Insert 2nd obj over 1st in Write bug
|
||
// RevokeServer won't Destroy us
|
||
OleRevokeServer(lhsrvr);
|
||
} else {
|
||
/* Probably, there never was a server... */
|
||
DPF("Closing application window\n");
|
||
// This delete server should release the server immediately
|
||
// EndDialog(ghwndApp, TRUE);
|
||
// DestroyWindow(ghwndApp);
|
||
PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0);
|
||
}
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrRelease1 (LPOLESERVER lpolesrvr)
|
||
{
|
||
LHSERVER lhsrvr;
|
||
|
||
/* If we're visible, but we don't want to be released, then ignore. */
|
||
if (gSrvr.lhsrvr && (IsWindowVisible(ghwndApp) || !gfRunWithEmbeddingFlag)) {
|
||
DPF("SrvrRelease: Ignoring releases...\n");
|
||
return OLE_OK;
|
||
}
|
||
|
||
lhsrvr = gSrvr.lhsrvr;
|
||
if (lhsrvr) {
|
||
DPF("SrvrRelease: Calling RevokeServer\n");
|
||
ServerUnblock();
|
||
gSrvr.lhsrvr = 0;
|
||
OleRevokeServer(lhsrvr);
|
||
} else {
|
||
DPF("SrvrRelease: Closing application window\n");
|
||
// This delete server should release the server immediately
|
||
// EndDialog(ghwndApp, TRUE);
|
||
// DestroyWindow(ghwndApp);
|
||
|
||
PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0);
|
||
}
|
||
return OLE_OK; // return something
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrExecute (LPOLESERVER lpoledoc, HGLOBAL hCommands)
|
||
{
|
||
return OLE_ERROR_GENERIC;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
BOOL FAR PASCAL RegisterDocument(LHSERVERDOC lhdoc, LPOLESERVERDOC FAR *lplpoledoc)
|
||
{
|
||
/* If we don't have a server, don't even bother. */
|
||
if (!gSrvr.lhsrvr)
|
||
return TRUE;
|
||
|
||
gDoc.hwnd = ghwndApp; // corresponding main window
|
||
|
||
/* should only be one document at a time... */
|
||
|
||
while (gDoc.lhdoc != (LHSERVERDOC)0 && gDoc.lhdoc != -1)
|
||
RevokeDocument();
|
||
|
||
#ifdef WAITDIFFERENTLY
|
||
while (gDoc.lhdoc == -1) {
|
||
MSG rMsg; /* variable used for holding a message */
|
||
DPF("RegisterDoc: Waiting for document to be released....\n");
|
||
|
||
/* call the server code and let it unblock the server */
|
||
ServerUnblock();
|
||
|
||
if (!GetMessage(&rMsg, NULL, 0, 0)) {
|
||
DPF("VERY BAD: got WM_QUIT while waiting...\n");
|
||
}
|
||
TranslateMessage(&rMsg);
|
||
DispatchMessage(&rMsg);
|
||
}
|
||
#endif
|
||
|
||
if (lhdoc == (LHSERVERDOC)0) {
|
||
CHAR szAnsi[MAX_PATH];
|
||
|
||
DPF("Registering document: %ws\n", (LPWSTR)gachFileDevice);
|
||
|
||
COPYSTRINGW2A(szAnsi, gachFileDevice);
|
||
if (OleRegisterServerDoc(gSrvr.lhsrvr, szAnsi, (LPOLESERVERDOC)&gDoc,
|
||
(LHSERVERDOC FAR *)&gDoc.lhdoc) != OLE_OK)
|
||
return FALSE;
|
||
} else {
|
||
gDoc.lhdoc = lhdoc;
|
||
}
|
||
|
||
DPF0( "RegisterDocument: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
|
||
|
||
////UpdateCaption(); //!!!
|
||
|
||
////DPF("Adding document handle: %lx\n",lhdoc);
|
||
|
||
////gDoc.aName = GlobalAddAtom(MakeAnsi((LPWSTR)gachFileDevice));
|
||
gDoc.oledoc.lpvtbl = &docVTbl;
|
||
|
||
if (lplpoledoc)
|
||
*lplpoledoc = (LPOLESERVERDOC)&gDoc;
|
||
|
||
SetDocVersion( DOC_VERSION_OLE1 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL RevokeDocument(void)
|
||
{
|
||
LHSERVERDOC lhdoc;
|
||
|
||
if (gDoc.lhdoc == -1) {
|
||
DPF("RevokeDocument: Document has been revoked, waiting for release!\n");
|
||
return;
|
||
}
|
||
|
||
if (gDoc.lhdoc) {
|
||
|
||
DPF0( "RevokeDocument: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
|
||
DPF("Revoking document: lhdoc=%lx\n",gDoc.lhdoc);
|
||
lhdoc = gDoc.lhdoc;
|
||
if (lhdoc) {
|
||
gDoc.lhdoc = -1;
|
||
if (OleRevokeServerDoc(lhdoc) == OLE_WAIT_FOR_RELEASE) {
|
||
#ifndef WAITDIFFERENTLY
|
||
while (gDoc.lhdoc != 0) {
|
||
MSG msg;
|
||
|
||
DPF("RevokeDocument: waiting for release...\n");
|
||
|
||
/* call the server code and let it unblock the server */
|
||
ServerUnblock();
|
||
|
||
if (!GetMessage(&msg, NULL, 0, 0)) {
|
||
DPF("VERY BAD: got WM_QUIT while waiting...\n");
|
||
}
|
||
TranslateMessage(&msg);
|
||
DispatchMessage(&msg);
|
||
}
|
||
DPF("RevokeDocument: done waiting for release\n");
|
||
#endif
|
||
} else {
|
||
//!! WinAssert(gDoc.lhdoc == 0);
|
||
}
|
||
|
||
SetDocVersion( DOC_VERSION_NONE );
|
||
|
||
} else {
|
||
DPF0("Document already revoked!");
|
||
}
|
||
SetEmbeddedObjectFlag(FALSE);
|
||
}
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrOpen (
|
||
LPOLESERVER lpolesrvr,
|
||
LHSERVERDOC lhdoc,
|
||
OLE_LPCSTR lpdocname,
|
||
LPOLESERVERDOC FAR *lplpoledoc)
|
||
{
|
||
BOOL f;
|
||
|
||
DPF("SrvrOpen: %s\n",lpdocname);
|
||
|
||
SetEmbeddedObjectFlag(TRUE);
|
||
|
||
BlockServer();
|
||
f = OpenMciDevice((LPSTR)lpdocname, (LPSTR)NULL);
|
||
UnblockServer();
|
||
|
||
if (!f)
|
||
return OLE_ERROR_GENERIC;
|
||
|
||
SetEmbeddedObjectFlag(FALSE);
|
||
|
||
RegisterDocument(lhdoc, lplpoledoc);
|
||
return OLE_OK;
|
||
}
|
||
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrCreate (
|
||
LPOLESERVER lpolesrvr,
|
||
LHSERVERDOC lhdoc,
|
||
OLE_LPCSTR lpclassname,
|
||
OLE_LPCSTR lpdocname,
|
||
LPOLESERVERDOC FAR *lplpoledoc)
|
||
{
|
||
DPF("SrvrCreate: %s!%s\n",lpdocname,lpclassname);
|
||
|
||
BlockServer();
|
||
CloseMCI(TRUE);
|
||
UnblockServer();
|
||
|
||
/* Set the title of the client document we're imbedded in */
|
||
COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocname);
|
||
|
||
RegisterDocument(lhdoc,lplpoledoc);
|
||
|
||
/* You are dirty by default according to OLE */
|
||
gfDirty = TRUE;
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrCreateFromTemplate (
|
||
LPOLESERVER lpolesrvr,
|
||
LHSERVERDOC lhdoc,
|
||
OLE_LPCSTR lpclassname,
|
||
OLE_LPCSTR lpdocname,
|
||
OLE_LPCSTR lptemplatename,
|
||
LPOLESERVERDOC FAR *lplpoledoc)
|
||
{
|
||
BOOL f;
|
||
|
||
DPF("SrvrCreateFromTemplate: %s as %s class=%s\n",lptemplatename,lpdocname,lpclassname);
|
||
|
||
SetEmbeddedObjectFlag(TRUE);
|
||
|
||
BlockServer();
|
||
f = OpenMciDevice((LPSTR)lptemplatename, (LPSTR)NULL);
|
||
UnblockServer();
|
||
|
||
if (!f)
|
||
return OLE_ERROR_GENERIC;
|
||
|
||
RegisterDocument(lhdoc,lplpoledoc);
|
||
|
||
gfDirty = TRUE;
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrEdit (
|
||
LPOLESERVER lpolesrvr,
|
||
LHSERVERDOC lhdoc,
|
||
OLE_LPCSTR lpclassname,
|
||
OLE_LPCSTR lpdocname,
|
||
LPOLESERVERDOC FAR *lplpoledoc)
|
||
{
|
||
DPF("SrvrEdit: %s class=%s\n",lpdocname,lpclassname);
|
||
|
||
BlockServer();
|
||
CloseMCI(TRUE);
|
||
UnblockServer();
|
||
|
||
/* Set the title of the client document we're imbedded in */
|
||
COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocname);
|
||
RegisterDocument(lhdoc,lplpoledoc);
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL SrvrExit (
|
||
LPOLESERVER lpolesrvr)
|
||
{
|
||
LHSERVER lhsrvr;
|
||
// Server lib is calling us to exit.
|
||
// Let us hide the main window.
|
||
// But let us not delete the window.
|
||
|
||
DPF("SrvrExit\n");
|
||
|
||
ShowWindow (ghwndApp, SW_HIDE);
|
||
|
||
lhsrvr = gSrvr.lhsrvr;
|
||
if (lhsrvr) {
|
||
gSrvr.lhsrvr = 0;
|
||
OleRevokeServer(lhsrvr);
|
||
}
|
||
return OLE_OK;
|
||
|
||
// How does the application ever end?
|
||
// Application will end when Release is received
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocSave (
|
||
LPOLESERVERDOC lpoledoc)
|
||
{
|
||
DPF("DocSave\n");
|
||
|
||
////BlockServer();
|
||
////FileSave(FALSE); // Save should send change message
|
||
////UnblockServer();
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocClose (
|
||
LPOLESERVERDOC lpoledoc)
|
||
{
|
||
DPF("DocClose\n");
|
||
|
||
BlockServer();
|
||
NewDoc(FALSE);
|
||
UnblockServer();
|
||
|
||
DPF("Leaving DocClose\n");
|
||
|
||
#ifdef WAITDIFFERENTLY
|
||
TerminateServer();
|
||
#else
|
||
PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
|
||
#endif
|
||
|
||
return OLE_OK;
|
||
|
||
// Should we exit the app here?
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
OLESTATUS FAR PASCAL DocSetHostNames(
|
||
LPOLESERVERDOC lpoledoc,
|
||
OLE_LPCSTR lpclientName,
|
||
OLE_LPCSTR lpdocName)
|
||
{
|
||
DPF("DocSetHostNames: %s -- %s\n",lpclientName,lpdocName);
|
||
|
||
COPYSTRINGA2W((LPWSTR)gachDocTitle, lpdocName);
|
||
SetEmbeddedObjectFlag(TRUE); // update menu items
|
||
gfValidCaption = FALSE;
|
||
UpdateDisplay();
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocSetDocDimensions(
|
||
LPOLESERVERDOC lpoledoc,
|
||
OLE_CONST RECT FAR * lprc)
|
||
{
|
||
DPF("DocSetDocDimensions [%d,%d,%d,%d]\n", *lprc);
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocRelease (
|
||
LPOLESERVERDOC lpoledoc)
|
||
{
|
||
DPF("DocRelease\n");
|
||
|
||
// !!! what is this supposed to do?
|
||
// Revoke document calls DocRelease.
|
||
////if (gDoc.aName)
|
||
////////GlobalDeleteAtom (gDoc.aName);
|
||
|
||
/* This marks the document as having been released */
|
||
gDoc.lhdoc = 0L;
|
||
|
||
// Should we kill the application here?
|
||
// No, I don't think so.
|
||
|
||
return OLE_OK; // return something
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocExecute (LPOLESERVERDOC lpoledoc, HANDLE hCommands)
|
||
{
|
||
return OLE_ERROR_GENERIC;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocSetColorScheme (LPOLESERVERDOC lpdoc,
|
||
OLE_CONST LOGPALETTE FAR* lppalette)
|
||
{
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL DocGetObject (
|
||
LPOLESERVERDOC lpoledoc,
|
||
OLE_LPCSTR lpitemname,
|
||
LPOLEOBJECT FAR * lplpoleobject,
|
||
LPOLECLIENT lpoleclient)
|
||
{
|
||
DPF("DocGetObject: '%s'\n",lpitemname);
|
||
|
||
gItem.hwnd = ghwndApp;
|
||
gItem.oleobject.lpvtbl = &itemVTbl;
|
||
|
||
// If the item is not null, then do not show the window.
|
||
// So do we show the window here, or not?
|
||
|
||
*lplpoleobject = (LPOLEOBJECT)&gItem;
|
||
gItem.lpoleclient = lpoleclient;
|
||
|
||
/* !!! We have been given OLD options before any updates. We don't need */
|
||
/* to parse options here... we'll do it when given our native data in */
|
||
/* ItemSetData. */
|
||
#if 0
|
||
/* Get the options from the item string */
|
||
BlockServer();
|
||
err = ParseOptions(lpitemname);
|
||
UnblockServer();
|
||
#endif
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
|
||
get the native data that represents the currenly open MCI
|
||
file/device. currently this is exactly the same as cfLink data!
|
||
|
||
***************************************************************************/
|
||
|
||
STATICFN HANDLE NEAR PASCAL Ole1GetLink ()
|
||
{
|
||
HANDLE hUnicode;
|
||
DWORD cbUnicode;
|
||
LPWSTR pUnicode;
|
||
DWORD cbAnsi;
|
||
LPSTR pAnsi;
|
||
HANDLE hAnsi;
|
||
|
||
DPF("Ole1GetLink\n");
|
||
|
||
hUnicode = GetLink();
|
||
|
||
if( !hUnicode )
|
||
return NULL;
|
||
|
||
cbUnicode = GlobalSize( hUnicode );
|
||
|
||
if( cbUnicode == 0 )
|
||
return NULL;
|
||
|
||
pUnicode = GlobalLock( hUnicode );
|
||
|
||
if( !pUnicode )
|
||
{
|
||
GlobalUnlock( hUnicode );
|
||
GlobalFree( hUnicode );
|
||
return NULL;
|
||
}
|
||
|
||
cbAnsi = ( cbUnicode * sizeof(CHAR) ) / sizeof(WCHAR);
|
||
|
||
hAnsi = GlobalAlloc( GMEM_DDESHARE | GMEM_ZEROINIT, cbAnsi );
|
||
|
||
if( !hAnsi )
|
||
return NULL;
|
||
|
||
pAnsi = GlobalLock( hAnsi );
|
||
|
||
if( !pAnsi )
|
||
{
|
||
GlobalFree( hAnsi );
|
||
return NULL;
|
||
}
|
||
|
||
while( *pUnicode )
|
||
{
|
||
DWORD Len;
|
||
|
||
COPYSTRINGW2A( pAnsi, pUnicode );
|
||
Len = wcslen( pUnicode );
|
||
pAnsi += ( Len + 1 );
|
||
pUnicode += ( Len + 1 );
|
||
}
|
||
|
||
GlobalUnlock( hUnicode );
|
||
GlobalUnlock( hAnsi );
|
||
|
||
GlobalFree( hUnicode );
|
||
|
||
return hAnsi;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
STATICFN HBITMAP NEAR PASCAL GetBitmap (PITEM pitem)
|
||
{
|
||
DPF(" GetBitmap\n");
|
||
|
||
return BitmapMCI();
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
STATICFN HANDLE PASCAL NEAR GetPalette(PITEM pitem)
|
||
{
|
||
extern HPALETTE CopyPalette(HPALETTE); // in MCI.C
|
||
|
||
DPF(" GetPalette\n");
|
||
|
||
return CopyPalette(PaletteMCI());
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
STATICFN HANDLE PASCAL NEAR GetDib(PITEM pitem)
|
||
{
|
||
HBITMAP hbm;
|
||
HPALETTE hpal;
|
||
HANDLE hdib;
|
||
HDC hdc;
|
||
|
||
extern HANDLE FAR PASCAL DibFromBitmap(HBITMAP hbm, HPALETTE hpal);
|
||
extern void FAR PASCAL DitherMCI(HANDLE hdib, HPALETTE hpal);
|
||
|
||
DPF(" GetDib\n");
|
||
|
||
hbm = GetBitmap(pitem);
|
||
hpal = PaletteMCI();
|
||
|
||
hdib = DibFromBitmap(hbm, hpal);
|
||
|
||
//
|
||
// if we are on a palette device. possibly dither to the VGA colors
|
||
// for apps that dont deal with palettes!
|
||
//
|
||
hdc = GetDC(NULL);
|
||
if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) &&
|
||
(gwOptions & OPT_DITHER)) {
|
||
DitherMCI(hdib, hpal);
|
||
hpal = NULL; // no longer working with a palette
|
||
}
|
||
ReleaseDC(NULL, hdc);
|
||
|
||
DeleteObject(hbm);
|
||
return hdib;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
STATICFN HANDLE PASCAL NEAR GetPicture (PITEM pitem)
|
||
{
|
||
HPALETTE hpal;
|
||
HANDLE hdib;
|
||
HANDLE hmfp;
|
||
HDC hdc;
|
||
extern HPALETTE CopyPalette(HPALETTE); // in MCI.C
|
||
|
||
HANDLE FAR PASCAL PictureFromDib(HANDLE hdib, HPALETTE hpal);
|
||
|
||
DPF(" GetPicture\n");
|
||
|
||
hdib = GetDib(pitem);
|
||
|
||
/* If we're dithered, don't use a palette */
|
||
hdc = GetDC(NULL);
|
||
if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && (gwOptions & OPT_DITHER))
|
||
hpal = NULL;
|
||
else
|
||
hpal = PaletteMCI();
|
||
|
||
if (hpal)
|
||
hpal = CopyPalette(hpal);
|
||
|
||
ReleaseDC(NULL, hdc);
|
||
|
||
hmfp = PictureFromDib(hdib, hpal);
|
||
|
||
if (hpal)
|
||
DeleteObject(hpal);
|
||
|
||
GlobalFree(hdib);
|
||
|
||
return hmfp;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemOpen (
|
||
LPOLEOBJECT lpoleobject,
|
||
BOOL fActivate)
|
||
{
|
||
/* Start an edit session, and if there is something to play, play it */
|
||
/* This is called by Excel to play an object, because it doesn't know */
|
||
/* about the PLAY verb. It's also called to Insert a New object into */
|
||
/* any client. */
|
||
/* All this work is done in our special -1 verb in ReallyDoVerb. */
|
||
|
||
DPF("ItemOpen\n");
|
||
Ole1ReallyDoVerb(lpoleobject, (UINT)(-1), TRUE, fActivate);
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
/**************************************************************************
|
||
* I know this looks odd, but ItemDoVerb is exported so we can't call it*
|
||
* internally and sometimes we need to. *
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemDoVerb (
|
||
LPOLEOBJECT lpobj,
|
||
UINT verb,
|
||
BOOL fShow,
|
||
BOOL fActivate)
|
||
{
|
||
return Ole1ReallyDoVerb(lpobj, verb, fShow, fActivate);
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
typedef enum
|
||
{
|
||
OLE1_OLEOK, /* 0 Function operated correctly */
|
||
|
||
OLE1_OLEWAIT_FOR_RELEASE, /* 1 Command has been initiated, client */
|
||
/* must wait for release. keep dispatching */
|
||
/* messages till OLE1_OLERELESE in callback */
|
||
|
||
OLE1_OLEBUSY, /* 2 Tried to execute a method while another */
|
||
/* method is in progress. */
|
||
|
||
OLE1_OLEERROR_PROTECT_ONLY, /* 3 Ole APIs are called in real mode */
|
||
OLE1_OLEERROR_MEMORY, /* 4 Could not alloc or lock memory */
|
||
OLE1_OLEERROR_STREAM, /* 5 (OLESTREAM) stream error */
|
||
OLE1_OLEERROR_STATIC, /* 6 Non static object expected */
|
||
OLE1_OLEERROR_BLANK, /* 7 Critical data missing */
|
||
OLE1_OLEERROR_DRAW, /* 8 Error while drawing */
|
||
OLE1_OLEERROR_METAFILE, /* 9 Invalid metafile */
|
||
OLE1_OLEERROR_ABORT, /* 10 Client chose to abort metafile drawing */
|
||
OLE1_OLEERROR_CLIPBOARD, /* 11 Failed to get/set clipboard data */
|
||
OLE1_OLEERROR_FORMAT, /* 12 Requested format is not available */
|
||
OLE1_OLEERROR_OBJECT, /* 13 Not a valid object */
|
||
OLE1_OLEERROR_OPTION, /* 14 Invalid option(link update / render) */
|
||
OLE1_OLEERROR_PROTOCOL, /* 15 Invalid protocol */
|
||
OLE1_OLEERROR_ADDRESS, /* 16 One of the pointers is invalid */
|
||
OLE1_OLEERROR_NOT_EQUAL, /* 17 Objects are not equal */
|
||
OLE1_OLEERROR_HANDLE, /* 18 Invalid handle encountered */
|
||
OLE1_OLEERROR_GENERIC, /* 19 Some general error */
|
||
OLE1_OLEERROR_CLASS, /* 20 Invalid class */
|
||
OLE1_OLEERROR_SYNTAX, /* 21 Command syntax is invalid */
|
||
OLE1_OLEERROR_DATATYPE, /* 22 Data format is not supported */
|
||
OLE1_OLEERROR_PALETTE, /* 23 Invalid color palette */
|
||
OLE1_OLEERROR_NOT_LINK, /* 24 Not a linked object */
|
||
OLE1_OLEERROR_NOT_EMPTY, /* 25 Client doc contains objects. */
|
||
OLE1_OLEERROR_SIZE, /* 26 Incorrect buffer size passed to the api */
|
||
/* that places some string in caller's */
|
||
/* buffer */
|
||
|
||
OLE1_OLEERROR_DRIVE, /* 27 Drive letter in doc name is invalid */
|
||
OLE1_OLEERROR_NETWORK, /* 28 Failed to establish connection to a */
|
||
/* network share on which the document */
|
||
/* is located */
|
||
|
||
OLE1_OLEERROR_NAME, /* 29 Invalid name(doc name, object name), */
|
||
/* etc.. passed to the APIs */
|
||
|
||
OLE1_OLEERROR_TEMPLATE, /* 30 Server failed to load template */
|
||
OLE1_OLEERROR_NEW, /* 31 Server failed to create new doc */
|
||
OLE1_OLEERROR_EDIT, /* 32 Server failed to create embedded */
|
||
/* instance */
|
||
OLE1_OLEERROR_OPEN, /* 33 Server failed to open document, */
|
||
/* possible invalid link */
|
||
|
||
OLE1_OLEERROR_NOT_OPEN, /* 34 Object is not open for editing */
|
||
OLE1_OLEERROR_LAUNCH, /* 35 Failed to launch server */
|
||
OLE1_OLEERROR_COMM, /* 36 Failed to communicate with server */
|
||
OLE1_OLEERROR_TERMINATE, /* 37 Error in termination */
|
||
OLE1_OLEERROR_COMMAND, /* 38 Error in execute */
|
||
OLE1_OLEERROR_SHOW, /* 39 Error in show */
|
||
OLE1_OLEERROR_DOVERB, /* 40 Error in sending do verb, or invalid */
|
||
/* verb */
|
||
OLE1_OLEERROR_ADVISE_NATIVE, /* 41 Item could be missing */
|
||
OLE1_OLEERROR_ADVISE_PICT, /* 42 Item could be missing or server doesn't */
|
||
/* this format. */
|
||
|
||
OLE1_OLEERROR_ADVISE_RENAME, /* 43 Server doesn't support rename */
|
||
OLE1_OLEERROR_POKE_NATIVE, /* 44 Failure of poking native data to server */
|
||
OLE1_OLEERROR_REQUEST_NATIVE, /* 45 Server failed to render native data */
|
||
OLE1_OLEERROR_REQUEST_PICT, /* 46 Server failed to render presentation */
|
||
/* data */
|
||
OLE1_OLEERROR_SERVER_BLOCKED, /* 47 Trying to block a blocked server or */
|
||
/* trying to revoke a blocked server */
|
||
/* or document */
|
||
|
||
OLE1_OLEERROR_REGISTRATION, /* 48 Server is not registered in regestation */
|
||
/* data base */
|
||
OLE1_OLEERROR_ALREADY_REGISTERED,/*49 Trying to register same doc multiple */
|
||
/* times */
|
||
OLE1_OLEERROR_TASK, /* 50 Server or client task is invalid */
|
||
OLE1_OLEERROR_OUTOFDATE, /* 51 Object is out of date */
|
||
OLE1_OLEERROR_CANT_UPDATE_CLIENT,/* 52 Embed doc's client doesn't accept */
|
||
/* updates */
|
||
OLE1_OLEERROR_UPDATE, /* 53 erorr while trying to update */
|
||
OLE1_OLEERROR_SETDATA_FORMAT, /* 54 Server app doesn't understand the */
|
||
/* format given to its SetData method */
|
||
OLE1_OLEERROR_STATIC_FROM_OTHER_OS,/* 55 trying to load a static object created */
|
||
/* on another Operating System */
|
||
|
||
/* Following are warnings */
|
||
OLE1_OLEWARN_DELETE_DATA = 1000 /* Caller must delete the data when he is */
|
||
/* done with it. */
|
||
} OLE1_OLESTATUS;
|
||
|
||
OLE1_OLESTATUS (FAR PASCAL *OleQueryObjPos)(LPVOID lpobj, HWND FAR* lphwnd, LPRECT lprc, LPRECT lprcWBounds);
|
||
|
||
STATICFN int NEAR PASCAL Ole1ReallyDoVerb (
|
||
LPOLEOBJECT lpobj,
|
||
UINT verb,
|
||
BOOL fShow,
|
||
BOOL fActivate)
|
||
{
|
||
BOOL fWindowWasVisible = IsWindowVisible(ghwndApp);
|
||
|
||
int dx,dy;
|
||
HWND hwndClient;
|
||
HWND hwndT;
|
||
RECT rcSave;
|
||
RECT rcClient;
|
||
RECT rc;
|
||
UINT err;
|
||
HPALETTE hpal;
|
||
HDC hdc;
|
||
INT xTextExt, yTextExt;
|
||
int yOrig, yNow, xOrig, ytitleNow, xtitleOrig, xNow;
|
||
int xIndent;
|
||
int wWinNow;
|
||
|
||
|
||
// ACK! We haven't finished doing ItemSetData yet because we have to
|
||
// bring up an open dialog. So we can't do the ItemDoVerb yet. We will
|
||
// Post a message to ourselves that will do both the SetData and DoVerb
|
||
// and we will succeed the DoVerb right now so the client will be happy
|
||
// and start dispatching messages again.
|
||
if (gfBrokenLink) {
|
||
// We need to get client info NOW because our OLE handler can only
|
||
// answer this question now... if we click on two broken links at the
|
||
// same time, it will get confused about which object we want.
|
||
gerr = OleQueryObjPos(lpobj, &ghwndClient, &grcClient, NULL);
|
||
|
||
PostMessage(ghwndApp, WM_DO_VERB, verb, MAKELONG(fShow, fActivate));
|
||
return OLE_OK;
|
||
}
|
||
|
||
//
|
||
// dont even try to nest things.
|
||
//
|
||
if (gfPlayingInPlace)
|
||
return OLE_OK;
|
||
|
||
if (verb == OLEVERB_PRIMARY) {
|
||
DPF("ItemDoVerb: Play\n");
|
||
|
||
//
|
||
// if the device can't window and the user does not want a playbar
|
||
// dont play in place - just start the media and run invisible.
|
||
//
|
||
if (!(gwDeviceType & DTMCI_CANWINDOW) && !(gwOptions & OPT_BAR)) {
|
||
gwOptions &= ~OPT_PLAY;
|
||
}
|
||
|
||
//
|
||
// Select the palette in right now on behalf of the active
|
||
// window, so USER will think it is palette aware.
|
||
//
|
||
// any palette will do we dont even have to realize it!!
|
||
//
|
||
if ((hpal = PaletteMCI()) && (hwndT = GetActiveWindow())) {
|
||
hdc = GetDC(hwndT);
|
||
hpal = SelectPalette(hdc, hpal, FALSE);
|
||
SelectPalette(hdc, hpal, FALSE);
|
||
ReleaseDC(hwndT, hdc);
|
||
}
|
||
|
||
if (ghwndClient) {
|
||
hwndClient = ghwndClient;
|
||
err = gerr;
|
||
rcClient = grcClient;
|
||
ghwndClient = NULL;
|
||
} else
|
||
err = OleQueryObjPos(lpobj, &hwndClient, &rcClient, NULL);
|
||
|
||
#ifdef DEBUG
|
||
if (gwOptions & OPT_PLAY)
|
||
{
|
||
DPF("ObjQueryObjPos: hwnd=%04X [%d %d %d %d]\n",hwndClient, rcClient);
|
||
|
||
if (err != OLE_OK) {
|
||
DPF("ItemDoVerb: CANT GET OBJECT POSITION!!!\n");
|
||
}
|
||
else {
|
||
if (!(gwDeviceType & DTMCI_CANWINDOW))
|
||
DPF("ItemDoVerb: DEVICE CANT WINDOW\n");
|
||
|
||
if (!IsWindow(hwndClient))
|
||
DPF("ItemDoVerb: Invalid Client Window?\n");
|
||
|
||
if (!IsWindowVisible(hwndClient))
|
||
DPF("ItemDoVerb: Client window is not visible, playing in a popup\n");
|
||
}
|
||
}
|
||
#endif
|
||
|
||
/* We want to play in place and we can. */
|
||
/* If we're a link, not an embedded object, and there was an instance */
|
||
/* of MPlayer up when we said "Play" that was already editing this */
|
||
/* file, we don't want to play in place... we'll just play in that */
|
||
/* instance. We can tell this by the fact that our main MPlayer */
|
||
/* window is already visible. */
|
||
if (err == OLE_OK && (gwOptions & OPT_PLAY) &&
|
||
IsWindow(hwndClient) && IsWindowVisible(hwndClient) &&
|
||
!fWindowWasVisible)
|
||
{
|
||
extern HPALETTE FAR PASCAL CreateSystemPalette(void);
|
||
|
||
rc = grcSize; // default playback window size for this movie
|
||
|
||
/* If we can't window, or something's wrong, use ICON size */
|
||
if (IsRectEmpty(&rc))
|
||
SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON),
|
||
GetSystemMetrics(SM_CYICON));
|
||
|
||
/* rcSave is the area for the MCI window above the control bar */
|
||
/* (if we have one). */
|
||
/* rcClient is the area of the MCI window (0 based) to play in.*/
|
||
/* Control bar may be longer than picutre, so rcClient may be */
|
||
/* smaller than rcSave. */
|
||
rcSave = rcClient; // remember stretched size
|
||
|
||
/* Make rcClient 0 based from rcSave */
|
||
rcClient.left = 0;
|
||
rcClient.right = rcSave.right - rcSave.left;
|
||
rcClient.top = 0;
|
||
rcClient.bottom = rcSave.bottom - rcSave.top;
|
||
|
||
/* Assume playbar will be regular height for now */
|
||
if (gwOptions & OPT_BAR)
|
||
gwPlaybarHeight = TOOLBAR_HEIGHT;
|
||
else
|
||
gwPlaybarHeight = 0;
|
||
|
||
//
|
||
// munge rectangle to account for a title in the picture
|
||
// and the fact that picture is centred above title.
|
||
// Remember, it's been stretched around.
|
||
//
|
||
if (gwOptions & OPT_TITLE) {
|
||
|
||
CHAR szAnsi[MAX_PATH];
|
||
|
||
hdc = GetDC(NULL);
|
||
|
||
if (ghfontMap)
|
||
SelectObject(hdc, ghfontMap);
|
||
|
||
#ifdef _WIN32
|
||
COPYSTRINGW2A(szAnsi, gachCaption);
|
||
MGetTextExtent( hdc, szAnsi, lstrlen(szAnsi),
|
||
&xTextExt, &yTextExt);
|
||
#else
|
||
xTextExt = GetTextExtent(hdc, gachCaption,
|
||
lstrlen(gachCaption));
|
||
#endif
|
||
|
||
ReleaseDC(NULL, hdc);
|
||
if (gwPastedHeight)
|
||
yOrig = gwPastedHeight;
|
||
else
|
||
yOrig = rc.bottom - rc.top;
|
||
xOrig = rc.right - rc.left;
|
||
xtitleOrig = max(xTextExt + 4, xOrig);
|
||
yNow = rcClient.bottom - rcClient.top;
|
||
xNow = rcClient.right - rcClient.left;
|
||
ytitleNow = (int)((long)yNow - ((long)yOrig * yNow)
|
||
/ (yOrig + TITLE_HEIGHT));
|
||
/* for windowed devices, center the playback area above the */
|
||
/* control bar if the control bar is longer. */
|
||
if (gwDeviceType & DTMCI_CANWINDOW) {
|
||
wWinNow =(int)((long)xOrig * (long)xNow / (long)xtitleOrig);
|
||
xIndent = (xNow - wWinNow) / 2;
|
||
rcClient.left += xIndent;
|
||
rcClient.right = rcClient.left + wWinNow;
|
||
}
|
||
|
||
// Align top of control bar with the top of the title bar.
|
||
// The control bar (if there) will appear under rcSave.
|
||
rcClient.bottom = rcClient.top + yNow - ytitleNow;
|
||
rcSave.bottom = rcSave.top + yNow - ytitleNow;
|
||
|
||
/* When we make the playbar, make it cover the title */
|
||
/* if the caption was stretched taller than ordinary.*/
|
||
if (gwOptions & OPT_BAR)
|
||
gwPlaybarHeight = max(ytitleNow, TOOLBAR_HEIGHT);
|
||
}
|
||
|
||
/* Enforce a minimum width for the control bar */
|
||
if ((gwOptions & OPT_BAR) &&
|
||
(rcSave.right - rcSave.left < 3 * GetSystemMetrics(SM_CXICON))){
|
||
rcSave.right = rcSave.left + 3 * GetSystemMetrics(SM_CXICON);
|
||
if (gwDeviceType & DTMCI_CANWINDOW)
|
||
xIndent = TRUE; // force SetWindowMCI to be called to
|
||
// avoid stretching to this new size.
|
||
}
|
||
|
||
if (gwDeviceType & DTMCI_CANWINDOW) {
|
||
//
|
||
// If we've only stretched a bit, don't stretch at all.
|
||
// We might be off a bit due to rounding problems.
|
||
//
|
||
dx = (rcClient.right - rcClient.left) - (rc.right - rc.left);
|
||
dy = (rcClient.bottom - rcClient.top) - (rc.bottom - rc.top);
|
||
|
||
if (dx && abs(dx) <= 2)
|
||
{
|
||
DPF("Adjusting for x round off\n");
|
||
rcClient.right = rcClient.left + (rc.right - rc.left);
|
||
// Fix Save rect too
|
||
rcSave.right = rcSave.left + (rc.right - rc.left);
|
||
}
|
||
|
||
if (dy && abs(dy) <= 2)
|
||
{
|
||
DPF("Adjusting for y round off\n");
|
||
rcClient.bottom = rcClient.top + (rc.bottom - rc.top);
|
||
// Fix Save rect, too.
|
||
rcSave.bottom = rcSave.top + (rc.bottom - rc.top);
|
||
}
|
||
|
||
//
|
||
// try to get the right palette from the client, if our
|
||
// pesentation data was dithered or, the user asked us to
|
||
// always use the object palette, then ignore any client
|
||
// palette.
|
||
//
|
||
#ifdef DEBUG
|
||
if (GetProfileInt("options", "UseClientPalette", !(gwOptions & OPT_USEPALETTE)))
|
||
gwOptions &= ~OPT_USEPALETTE;
|
||
else
|
||
gwOptions |= OPT_USEPALETTE;
|
||
#endif
|
||
if (!(gwOptions & OPT_USEPALETTE) &&
|
||
!(gwOptions & OPT_DITHER)) {
|
||
|
||
//
|
||
// try to get a OWNDC Palette of the client, PowerPoint
|
||
// uses a PC_RESERVED palette in "SlideShow" mode. so
|
||
// we must use it's exact palette.
|
||
//
|
||
hdc = GetDC(hwndClient);
|
||
hpal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
|
||
SelectPalette(hdc, hpal, FALSE);
|
||
ReleaseDC(hwndClient, hdc);
|
||
|
||
if (hpal == NULL || hpal == GetStockObject(DEFAULT_PALETTE)) {
|
||
|
||
/* Assume client realized the proper palette for us */
|
||
|
||
DPF("Using system palette\n");
|
||
|
||
if (ghpalApp)
|
||
DeleteObject(ghpalApp);
|
||
|
||
hpal = ghpalApp = CreateSystemPalette();
|
||
}
|
||
else {
|
||
DPF("Using clients OWNDC palette\n");
|
||
}
|
||
|
||
if (hpal)
|
||
SetPaletteMCI(hpal);
|
||
}
|
||
else {
|
||
DPF("Using MCI Object's normal palette\n");
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// for non window devices, just have the playbar show up!
|
||
// so use a zero height MCI Window area.
|
||
//
|
||
rcSave.top = rcSave.bottom;
|
||
}
|
||
|
||
//
|
||
// if we are not in small mode, get there now
|
||
//
|
||
if (!gfPlayOnly) {
|
||
ShowWindow(ghwndApp, SW_HIDE);
|
||
gfPlayOnly = TRUE;
|
||
SizeMPlayer();
|
||
}
|
||
|
||
ClrWS(ghwndApp, WS_THICKFRAME|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_BORDER);
|
||
|
||
if (gwOptions & OPT_BORDER)
|
||
SetWS(ghwndApp, WS_BORDER);
|
||
|
||
/* Set the size of Mplayer to have enough space for the MCI */
|
||
/* playback area and a playbar and the non-client area. */
|
||
|
||
rcSave.bottom += gwPlaybarHeight;
|
||
|
||
AdjustWindowRect(&rcSave, GetWS(ghwndApp), FALSE);
|
||
|
||
Ole1PlayInPlace(ghwndApp, hwndClient, &rcSave);
|
||
|
||
fShow = FALSE;
|
||
fActivate = FALSE;
|
||
|
||
/* become visible */
|
||
ShowWindow(ghwndApp,SW_SHOWNA);
|
||
|
||
/* Remember to play the video in the rcClient area of rcSave */
|
||
if ((gwDeviceType & DTMCI_CANWINDOW) &&
|
||
(gwOptions & OPT_TITLE) && xIndent != 0)
|
||
SetDestRectMCI(&rcClient);
|
||
|
||
/* Let keyboard interface work on control bar, and let the */
|
||
/* accelerators go through. */
|
||
toolbarSetFocus(ghwndToolbar, BTN_PLAY);
|
||
SetFocus(ghwndToolbar);
|
||
|
||
gfCloseAfterPlaying = TRUE;
|
||
|
||
/* We won't play in place - use a popup window or nothing. */
|
||
} else {
|
||
|
||
/* If we want a playbar, then use MPlayer reduced mode to play. */
|
||
/* If we don't want one, then don't show mplayer's window - */
|
||
/* we'll just use the default MCI window (for a windowed device)*/
|
||
/* or nothing for a non-windowed device. If we stole an already*/
|
||
/* running instance of mplayer, we must use it and not run */
|
||
/* silently. */
|
||
if ((gwOptions & OPT_BAR) || fWindowWasVisible) {
|
||
DPF("Using Toplevel window for playback\n");
|
||
|
||
/* go to our little miniature version */
|
||
if (!gfPlayOnly && !fWindowWasVisible) {
|
||
gwPlaybarHeight = TOOLBAR_HEIGHT;
|
||
gfPlayOnly = TRUE;
|
||
SizeMPlayer();
|
||
}
|
||
|
||
fShow = fActivate = TRUE;
|
||
gfCloseAfterPlaying = !fWindowWasVisible;
|
||
|
||
} else {
|
||
DPF("Running silently\n");
|
||
|
||
if (!fWindowWasVisible)
|
||
SetWindowMCI(NULL); // make sure we're using default MCI win
|
||
|
||
fShow = fActivate = FALSE;
|
||
gfCloseAfterPlaying = TRUE; // we're invisible, so close auto.
|
||
}
|
||
}
|
||
|
||
Yield(); // If play goes to full screen mode, PowerPig will
|
||
Yield(); // time out and put up errors thinking we didn't play.
|
||
PostMessage(ghwndApp, WM_COMMAND, ID_PLAYSEL, 0); // play selection
|
||
|
||
} else if (verb == 1) {
|
||
DPF("ItemDoVerb: Edit\n");
|
||
|
||
if (gfPlayOnly) {
|
||
gfPlayOnly = FALSE;
|
||
SizeMPlayer();
|
||
}
|
||
|
||
/* If we come up empty, it's OK to be in OPEN or NOT_READY mode and */
|
||
/* don't try to seek anywhere. */
|
||
if (gwDeviceID) {
|
||
switch (gwStatus) {
|
||
|
||
case MCI_MODE_OPEN:
|
||
case MCI_MODE_NOT_READY:
|
||
Error(ghwndApp, IDS_CANTEDIT);
|
||
break;
|
||
|
||
default:
|
||
// Seek to the position we were when we copied. Stop first.
|
||
if (StopMCI()) {
|
||
// fix state so Seek recognizes we're stopped
|
||
gwStatus = MCI_MODE_STOP;
|
||
SeekMCI(gdwPosition);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
/* Let UpdateDisplay set focus properly by saying we're invalid */
|
||
gwStatus = (UINT)(-1);
|
||
|
||
/* Our special ItemOpen verb */
|
||
} else if (verb == -1) {
|
||
Ole1ReallyDoVerb(lpobj, 1, fShow, fActivate);
|
||
if (gwDeviceID)
|
||
Ole1ReallyDoVerb(lpobj, OLEVERB_PRIMARY, fShow, fActivate);
|
||
return OLE_OK;
|
||
|
||
} else {
|
||
DPF("ItemDoVerb: Unknown verb: %d\n", verb);
|
||
}
|
||
|
||
if (fShow) {
|
||
ShowWindow(ghwndApp, SW_SHOW);
|
||
|
||
if (IsIconic(ghwndApp))
|
||
SendMessage(ghwndApp, WM_SYSCOMMAND, SC_RESTORE, 0L);
|
||
}
|
||
|
||
if (fActivate) {
|
||
BringWindowToTop (ghwndApp); // let WM_ACTIVATE put client
|
||
SetActiveWindow (ghwndApp); // underneath us
|
||
}
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemRelease (
|
||
LPOLEOBJECT lpoleobject)
|
||
{
|
||
DPF("ItemRelease\n");
|
||
|
||
gItem.lpoleclient = NULL;
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemGetData ( LPOLEOBJECT lpoleobject,
|
||
OLECLIPFORMAT cfFormat,
|
||
LPHANDLE lphandle)
|
||
{
|
||
PITEM pitem;
|
||
|
||
DPF("ItemGetData\n");
|
||
|
||
#ifndef _WIN32
|
||
pitem = (PITEM)(WORD)(DWORD)lpoleobject;
|
||
#else
|
||
// LKG: What was that doing? Are they unpacking something subtle?
|
||
pitem = (PITEM)lpoleobject;
|
||
#endif //_WIN32
|
||
|
||
if (cfFormat == cfNative) {
|
||
|
||
*lphandle = Ole1GetLink ();
|
||
if (!(*lphandle))
|
||
return OLE_ERROR_MEMORY;
|
||
|
||
if (gfEmbeddedObject)
|
||
CleanObject();
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
*lphandle = NULL;
|
||
|
||
if (cfFormat == CF_METAFILEPICT) {
|
||
*lphandle = GetPicture (pitem);
|
||
|
||
}
|
||
else if (cfFormat == CF_PALETTE) {
|
||
*lphandle = GetPalette(pitem);
|
||
|
||
}
|
||
else if (cfFormat == CF_DIB) {
|
||
*lphandle = GetDib(pitem);
|
||
|
||
}
|
||
else if (cfFormat == cfLink || cfFormat == cfOwnerLink){
|
||
*lphandle = Ole1GetLink ();
|
||
}
|
||
else return OLE_ERROR_MEMORY; // this is actually unknown format.
|
||
|
||
if (!(*lphandle))
|
||
return OLE_ERROR_MEMORY; // honestly this time
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemSetTargetDevice (
|
||
LPOLEOBJECT lpoleobject,
|
||
HGLOBAL hdata)
|
||
{
|
||
DPF("ItemSetTargetDevice\n");
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
|
||
STATICFN OLESTATUS NEAR PASCAL SetDataPartII(LPWSTR szFile, LPWSTR szDevice)
|
||
{
|
||
int status = OLE_OK;
|
||
LHSERVERDOC lhdocTemp;
|
||
|
||
// TERRIBLE HACK! set gfEmbeddedObject so OpenMCI does
|
||
// not re-register this document!!!
|
||
//
|
||
|
||
BlockServer();
|
||
|
||
lhdocTemp = gDoc.lhdoc;
|
||
gDoc.lhdoc = (LHSERVERDOC)0; /* So it won't be killed by CloseMCI!! */
|
||
gfEmbeddedObject++;
|
||
|
||
/* Coming up: Horrible cast to get rid of warning.
|
||
*
|
||
* This file is compiled non-Unicode, in contrast to the rest of MPlayer.
|
||
* This means that LPTSTR in the function prototypes mean different things
|
||
* depending on who included them. OpenMciDevice and other Unicode
|
||
* routines called from this module expect Unicode strings, but the
|
||
* compiler thinks they're ANSI. We can keep the compiler happy by
|
||
* casting them to LPTSTR. Does that make sense?
|
||
*
|
||
* Places where this unspeakable act is perpetrated are indicated thus:
|
||
*/
|
||
if (!OpenMciDevice((LPTSTR)szFile, (LPTSTR)szDevice))
|
||
// ^^^^^^^^ ^^^^^^^^
|
||
status = OLE_ERROR_FORMAT;
|
||
|
||
gfEmbeddedObject--;
|
||
gDoc.lhdoc = lhdocTemp;
|
||
|
||
/* Set the selection to what we parsed in ParseOptions. */
|
||
if (status == OLE_OK) {
|
||
SendMessage(ghwndTrackbar, TBM_SETSELSTART, 0, glSelStart);
|
||
SendMessage(ghwndTrackbar, TBM_SETSELEND, 0, glSelEnd);
|
||
}
|
||
|
||
UnblockServer();
|
||
|
||
return status;
|
||
}
|
||
|
||
/**************************************************************************/
|
||
/**************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemSetData1(LPOLEOBJECT lpoleobject, OLECLIPFORMAT cfFormat, HANDLE hdata)
|
||
{
|
||
LPBYTE p, pSave, pT;
|
||
// Why BYTE?? And is this heading
|
||
// for UNICODE trouble?
|
||
LPWSTR pUnicode;
|
||
LPSTR szFile, szDevice;
|
||
char achFile[MAX_PATH];
|
||
char ach[40];
|
||
OLESTATUS status;
|
||
|
||
WCHAR FileNameW[MAX_PATH];
|
||
|
||
DPF("ItemSetData1\n");
|
||
|
||
if (hdata == NULL)
|
||
return OLE_ERROR_MEMORY;
|
||
|
||
if (cfFormat != cfNative)
|
||
return OLE_ERROR_FORMAT;
|
||
|
||
p = GlobalLock(hdata);
|
||
if (p == NULL)
|
||
return OLE_ERROR_MEMORY;
|
||
|
||
szFile = p + lstrlen((LPSTR)p) + 1; // pick off the Filename
|
||
|
||
p = szFile + lstrlen(szFile) + 1;
|
||
pSave = p;
|
||
szDevice = ach; // copy over Device name and
|
||
for (pT = ach; *p && *p != ',';) // NULL terminate it (it ends
|
||
*pT++ = *p++; // with a ',' right now).
|
||
*pT = '\0';
|
||
|
||
#ifdef DEBUG
|
||
DPF(" %s|%s!%s\n", (LPSTR)p, (LPSTR)szFile, (LPSTR)szDevice);
|
||
#endif
|
||
|
||
BlockServer(); // cause CloseMCI can yield
|
||
CloseMCI(TRUE); // nuke old gachCaption
|
||
UnblockServer();
|
||
pUnicode = AllocateUnicodeString(pSave);
|
||
|
||
if( !pUnicode )
|
||
return OLE_ERROR_MEMORY;
|
||
|
||
ParseOptions((LPTSTR)pUnicode); // this will set new gachCaption
|
||
// YUK ^^^^^^^^ \\
|
||
|
||
FreeUnicodeString(pUnicode);
|
||
|
||
// If this file doesn't exist, we won't continue setting data, we will
|
||
// succeed and get out, and do it later, because we can't bring up a dialog
|
||
// right now because clients like WinWord won't dispatch any msgs.
|
||
|
||
lstrcpyn(achFile, szFile, sizeof(achFile));
|
||
// if the filename we were given is bad, try and find it somewhere
|
||
|
||
COPYSTRINGA2W(FileNameW, szFile);
|
||
|
||
if (FindRealFileName((LPTSTR)FileNameW, sizeof(achFile))) {
|
||
// YUK ^^^^^^^^ \\
|
||
// We found it on the disk somewhere, so continue with SetData
|
||
WCHAR szDeviceW[80];
|
||
|
||
COPYSTRINGA2W(szDeviceW, szDevice);
|
||
status = SetDataPartII(FileNameW, szDeviceW);
|
||
} else {
|
||
|
||
// Nowhere to be found. We need to ask the user to find it... LATER!!
|
||
|
||
if (gfBrokenLink) {
|
||
DPF("ACK!! Got Second ItemSetData with BrokenLink!!");
|
||
return OLE_ERROR_GENERIC;
|
||
}
|
||
|
||
// Succeed to ItemSetData so client will be happy
|
||
lstrcpyn(gachDeviceA, szDevice, sizeof(gachDeviceA));
|
||
COPYSTRINGA2W(gachFile, szFile);
|
||
gfBrokenLink = TRUE;
|
||
status = OLE_OK;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemSetColorScheme (LPOLEOBJECT lpobj,
|
||
OLE_CONST LOGPALETTE FAR * lppalette)
|
||
{
|
||
DPF("ItemSetColorScheme\n");
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLESTATUS FAR PASCAL ItemSetBounds (LPOLEOBJECT lpobj, OLE_CONST RECT FAR* lprc)
|
||
{
|
||
DPF("ItemSetBounds: [%d,%d,%d,%d]\n", *lprc);
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
OLECLIPFORMAT FAR PASCAL ItemEnumFormats(
|
||
LPOLEOBJECT lpoleobject,
|
||
OLECLIPFORMAT cfFormat)
|
||
{
|
||
////DPF("ItemEnumFormats: %u\n",cfFormat);
|
||
|
||
if (cfFormat == 0)
|
||
return cfLink;
|
||
|
||
if (cfFormat == cfLink)
|
||
return cfOwnerLink;
|
||
|
||
if (cfFormat == cfOwnerLink)
|
||
return CF_METAFILEPICT;
|
||
|
||
if (cfFormat == CF_METAFILEPICT)
|
||
return CF_DIB;
|
||
|
||
if (cfFormat == CF_DIB)
|
||
return CF_PALETTE;
|
||
|
||
if (cfFormat == CF_PALETTE)
|
||
return cfNative;
|
||
|
||
//if (cfFormat == cfNative)
|
||
// return NULL;
|
||
|
||
return (OLECLIPFORMAT)0;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
int FAR PASCAL SendChangeMsg (UINT options)
|
||
{
|
||
CHAR szAnsi[MAX_PATH];
|
||
|
||
if (gDoc.lhdoc && gDoc.lhdoc != -1) {
|
||
if (options == OLE_SAVED) {
|
||
DPF("SendChangeMsg(OLE_SAVED): Calling OleSavedServerDoc\n");
|
||
DPF0( "SendChangeMsg: Locks on server doc: %x\n", GlobalFlags(gDoc.lhdoc) & (GMEM_LOCKCOUNT | GMEM_INVALID_HANDLE) );
|
||
return OleSavedServerDoc(gDoc.lhdoc);
|
||
} else if (options == OLE_RENAMED) {
|
||
DPF("SendChangeMsg(OLE_RENAMED): new name is '%ws'.\n", (LPWSTR)gachFileDevice);
|
||
COPYSTRINGW2A(szAnsi, gachFileDevice);
|
||
return OleRenameServerDoc(gDoc.lhdoc, szAnsi);
|
||
} else if (gItem.lpoleclient) {
|
||
DPF("SendChangeMsg(%d) client=%lx\n",options,gItem.lpoleclient);
|
||
return (*gItem.lpoleclient->lpvtbl->CallBack) (gItem.lpoleclient,
|
||
options, (LPOLEOBJECT)&gItem);
|
||
}
|
||
}
|
||
|
||
return OLE_OK;
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL CopyObject(HWND hwnd)
|
||
{
|
||
PITEM pitem = &gItem;
|
||
|
||
//
|
||
// we put two types of OLE objects in the clipboard, the type of
|
||
// OLE object is determined by the *order* of the clipboard data
|
||
//
|
||
// Embedded Object:
|
||
// cfNative
|
||
// OwnerLink
|
||
// Picture
|
||
// ObjectLink
|
||
//
|
||
// Linked Object:
|
||
// OwnerLink
|
||
// Picture
|
||
// ObjectLink
|
||
//
|
||
|
||
if (OpenClipboard (hwnd)) {
|
||
|
||
// Copying an object can take a long time - especially large AVI frames
|
||
// Tell the user its coffee time.
|
||
HCURSOR hcurPrev = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
||
BlockServer();
|
||
|
||
EmptyClipboard();
|
||
|
||
SetClipboardData(cfNative, Ole1GetLink());
|
||
|
||
/* Don't ask me why we do this even if it is untitled... */
|
||
SetClipboardData (cfOwnerLink, Ole1GetLink());
|
||
|
||
CopyMCI(NULL);
|
||
|
||
#if 0 // DON'T OFFER LINKS ANYMORE!
|
||
/* Only offer link data if not untitled and not a embedded object */
|
||
if (gwDeviceType & DTMCI_FILEDEV)
|
||
SetClipboardData(cfLink, Ole1GetLink());
|
||
#endif
|
||
|
||
UnblockServer();
|
||
CloseClipboard();
|
||
SetCursor(hcurPrev); // We're back!!!
|
||
}
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
/**************************************************************************
|
||
|
||
STUFF FOR PLAY IN PLACE
|
||
|
||
***************************************************************************/
|
||
|
||
|
||
#ifndef _WIN32
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
LRESULT CALLBACK _EXPORT MouseHook(int hc, WPARAM wParam, LPARAM lParam)
|
||
{
|
||
LPMOUSEHOOKSTRUCT lpmh = (LPVOID)lParam;
|
||
BOOL fDownNow, fDownBefore;
|
||
|
||
//
|
||
// NOTE SS != DS
|
||
//
|
||
|
||
if (hc == HC_ACTION)
|
||
{
|
||
#ifdef XDEBUG
|
||
char ach[80];
|
||
wsprintf( ach
|
||
, "MouseHook: %c%c pt=[%d,%d] hwnd=%04X ht=%04X\r\n"
|
||
, (GetAsyncKeyState(VK_LBUTTON) < 0 ? 'L' : ' ')
|
||
, (GetAsyncKeyState(VK_RBUTTON) < 0 ? 'R' : ' ')
|
||
, lpmh->pt
|
||
, lpmh->hwnd
|
||
, lpmh->wHitTestCode
|
||
);
|
||
OutputDebugString(ach);
|
||
#endif
|
||
/* If the mouse was DOWN when we started, we wait until it comes up */
|
||
/* before we let mouse downs kill us. If KeyState said it was DOWN */
|
||
/* we wait until it says it is UP before we let DOWN KeyStates kill */
|
||
/* us. */
|
||
/* We're checking Async because we have to... it's the NOW state. */
|
||
/* We're ALSO checking GetKeyState because Faris' machine misses */
|
||
/* some mouse downs unless we call every function possible !!**!!** */
|
||
|
||
fDownNow = GetAsyncKeyState(VK_LBUTTON) || GetAsyncKeyState(VK_RBUTTON);
|
||
fDownBefore = GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON);
|
||
|
||
if ((fDownNow && gfMouseUpSeen) || (fDownBefore && gfKeyStateUpSeen)) {
|
||
//
|
||
// the user is clicking on the client DOC, allow him/her to
|
||
// only click on the caption (for moving sizing) or we will
|
||
// exit.
|
||
//
|
||
if (lpmh->hwnd != GetDesktopWindow() &&
|
||
lpmh->wHitTestCode != HTCAPTION) {
|
||
|
||
// Do this NOW before anybody gets a chance to yield and draw
|
||
// with the wrong styles...
|
||
|
||
if (gfPlayingInPlace)
|
||
Ole1EndPlayInPlace(ghwndApp);
|
||
|
||
PostMessage(ghwndApp, WM_CLOSE, 0, 0L); // GET OUT !!!
|
||
}
|
||
}
|
||
if (!fDownNow)
|
||
gfMouseUpSeen = TRUE;
|
||
if (!fDownBefore)
|
||
gfKeyStateUpSeen = TRUE;
|
||
}
|
||
|
||
return CallNextHookEx(hHookMouse, hc, wParam, lParam);
|
||
}
|
||
#endif
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL Ole1PlayInPlace(HWND hwndApp, HWND hwndClient, LPRECT prc)
|
||
{
|
||
HWND hwndP;
|
||
|
||
DPF("Ole1PlayInPlace(%04X, %04X, [%d %d %d %d])\n", hwndApp, hwndClient, *prc);
|
||
|
||
if (gfPlayingInPlace) // this is bad
|
||
return;
|
||
|
||
#ifdef DEBUG
|
||
if (GetPrivateProfileInt("options", "PopupWindow", FALSE, "mplayer.ini"))
|
||
#else
|
||
if (FALSE)
|
||
#endif
|
||
{
|
||
DPF("Using Popup window for playback\n");
|
||
|
||
//
|
||
// this is code for a popup window.
|
||
//
|
||
ClientToScreen(hwndClient, (LPPOINT)prc);
|
||
ClientToScreen(hwndClient, (LPPOINT)prc+1);
|
||
|
||
SetWS(hwndApp, WS_POPUP);
|
||
|
||
hwndP = TopWindow(hwndClient);
|
||
|
||
#ifndef _WIN32
|
||
// I haven't the faintest idea what this is trying to do, but I see it's
|
||
// within the scope of a retail if(FALSE) anyway.
|
||
// If you understand it then either delete the function or replace this comment.
|
||
// Laurie
|
||
SetWindowWord(hwndApp, GWW_HWNDPARENT, (WORD)hwndP); // set owner
|
||
#endif
|
||
|
||
gfParentWasEnabled = IsWindowEnabled(hwndP);
|
||
EnableWindow(hwndP, FALSE);
|
||
|
||
} else {
|
||
DPF("Using Child window for playback\n");
|
||
|
||
SetWS(hwndApp, WS_CHILD);
|
||
SetParent(hwndApp, hwndClient);
|
||
|
||
DinkWithWindowStyles(hwndApp, FALSE);
|
||
}
|
||
|
||
gfPlayingInPlace = TRUE;
|
||
|
||
SetWindowPos(hwndApp, HWND_TOP,
|
||
prc->left,prc->top,
|
||
prc->right - prc->left,
|
||
prc->bottom - prc->top,
|
||
SWP_NOACTIVATE);
|
||
|
||
#ifndef _WIN32
|
||
if (fpMouseHook == NULL)
|
||
fpMouseHook = (HOOKPROC)MakeProcInstance((FARPROC)MouseHook, ghInst);
|
||
#endif
|
||
|
||
|
||
//
|
||
// Is the key down at this INSTANT ??? Then wait until it comes up before
|
||
// we allow GetAsyncKeyState to make us go away
|
||
//
|
||
|
||
gfMouseUpSeen = !((GetAsyncKeyState(VK_LBUTTON) & 0x8000) ||
|
||
(GetAsyncKeyState(VK_RBUTTON) & 0x8000));
|
||
|
||
//
|
||
// Is GetKeyState saying it's down? If so, wait until GetKeyState returns
|
||
// up before we let GetKeyState kill us.
|
||
//
|
||
|
||
gfKeyStateUpSeen= !(GetKeyState(VK_LBUTTON) || GetKeyState(VK_RBUTTON));
|
||
|
||
|
||
#ifdef _WIN32
|
||
|
||
/*
|
||
** Tell mciole32.dll to install its mouse HookProc.
|
||
*/
|
||
|
||
#ifdef DEBUG
|
||
if ( fHookInstalled ) {
|
||
|
||
DPF( "Hook already installed\n" );
|
||
DebugBreak();
|
||
}
|
||
#endif
|
||
|
||
if ( fpInstallHook ) {
|
||
|
||
DWORD wow_thread_id = 0L;
|
||
|
||
/*
|
||
** This is a HACK. If the client applications is a WOW app the
|
||
** HIWORD of the window handle will be 0xFFFF.
|
||
*/
|
||
if ( HIWORD(hwndClient) == 0xFFFF ) {
|
||
wow_thread_id = GetWindowThreadProcessId( hwndClient, NULL );
|
||
}
|
||
|
||
fHookInstalled = (*fpInstallHook)( ghwndApp, wow_thread_id );
|
||
}
|
||
|
||
#else /* !_WIN32 */
|
||
|
||
hHookMouse = SetWindowsHookEx( WH_MOUSE, fpMouseHook, ghInst,
|
||
GetWindowTask(hwndClient) );
|
||
#endif
|
||
|
||
ghwndFocusSave = GetFocus();
|
||
}
|
||
|
||
/**************************************************************************
|
||
***************************************************************************/
|
||
|
||
void FAR PASCAL Ole1EndPlayInPlace(HWND hwndApp)
|
||
{
|
||
HWND hwndP;
|
||
HWND hwndT;
|
||
|
||
#if 0 // can't do this because SS != DS
|
||
DPF("Ole1EndPlayInPlace()\n");
|
||
#endif
|
||
|
||
if (!gfPlayingInPlace || !IsWindow(hwndApp))
|
||
return;
|
||
|
||
/* Do this BEFORE hiding our window and BEFORE we do anything that */
|
||
/* might yield so client can't redraw with the wrong styles set. */
|
||
DinkWithWindowStyles(hwndApp, TRUE);
|
||
|
||
gfPlayingInPlace = FALSE;
|
||
|
||
#ifdef _WIN32
|
||
|
||
/*
|
||
** Tell mciole32.dll to remove its mouse HookProc.
|
||
*/
|
||
|
||
if ( fpRemoveHook ) {
|
||
|
||
fHookInstalled = !(*fpRemoveHook)();
|
||
}
|
||
|
||
#else /* !_WIN32 */
|
||
|
||
UnhookWindowsHookEx(hHookMouse);
|
||
hHookMouse = NULL;
|
||
|
||
#endif
|
||
|
||
hwndP = GetParent(hwndApp);
|
||
|
||
//
|
||
// If we have the focus, then restore it to who used to have it.
|
||
// ACK!! If the person who used to have it is GONE, we must give it away
|
||
// to somebody (who choose our parent) because our child can't
|
||
// keep the focus without making windows crash hard during the WM_DESTROY
|
||
// (or maybe later whenever it feels like crashing at some random time).
|
||
// See bug #8634.
|
||
//
|
||
if ((hwndT = GetFocus()) && GetWindowTask(hwndT) == MGetCurrentTask) {
|
||
if (IsWindow(ghwndFocusSave))
|
||
SetFocus(ghwndFocusSave);
|
||
else
|
||
SetFocus(hwndP);
|
||
}
|
||
|
||
if (!hwndP ||
|
||
(gwOptions & OPT_BAR) ||
|
||
(gwOptions & OPT_BORDER) ||
|
||
(gwOptions & OPT_AUTORWD)) {
|
||
//
|
||
// hide the aplication window
|
||
//
|
||
SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
|
||
SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|SWP_HIDEWINDOW|
|
||
SWP_NOACTIVATE);
|
||
}
|
||
else {
|
||
//
|
||
// hide our window, but don't redraw it will look
|
||
// like we are still on the last frame.
|
||
//
|
||
// this is when we are playing in place, and there is
|
||
// no playbar, and no rewind
|
||
//
|
||
// this is for Playing a AVI in a PowerPoint slide
|
||
// without redraw problems.
|
||
//
|
||
SetWindowPos(hwndApp, NULL, 0, 0, 0, 0,
|
||
SWP_NOREDRAW|SWP_NOZORDER|SWP_NOSIZE|SWP_NOMOVE|
|
||
SWP_HIDEWINDOW|SWP_NOACTIVATE);
|
||
}
|
||
|
||
SetParent(hwndApp, NULL);
|
||
ClrWS(hwndApp, WS_CHILD);
|
||
|
||
if (hwndP && gfParentWasEnabled)
|
||
EnableWindow(hwndP, TRUE);
|
||
|
||
//
|
||
// set either the owner or the WS_CHILD bit so it will
|
||
// not act up because we have the palette bit set and cause the
|
||
// desktop to steal the palette.
|
||
//
|
||
#if 0
|
||
// The folowing was ifdef-ed away before I saw it, but note that it
|
||
// wouldn't work on WIN32 anyway.
|
||
SetWindowWord(hwndApp, GWW_HWNDPARENT, (WORD)GetDesktopWindow());
|
||
#else
|
||
SetWS(hwndApp, WS_CHILD);
|
||
#endif
|
||
}
|
||
|
||
#endif /* OLE1_HACK */
|
||
|