|
|
/* (C) Copyright Microsoft Corporation 1991-1994. All Rights Reserved */ //
// FILE: oleglue.c
//
// NOTES: OLE-related outbound references from SoundRecorder
//
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <shellapi.h>
#include <objbase.h>
#define INCLUDE_OLESTUBS
#include "soundrec.h"
#include "srecids.h"
//
// GLOBALS
//
// should unify state variables and put globals into a single location
DWORD dwOleBuildVersion = 0; // OLE library version number
BOOL gfOleInitialized = FALSE; // did OleInitialize succeed?
BOOL gfStandalone = FALSE; // status, are we a non-embedded object
BOOL gfEmbedded = FALSE; // were we invoked with an -Embedding flag?
BOOL gfLinked = FALSE; // are we a linked object?
BOOL gfTerminating = FALSE; // has TerminateServer been called?
BOOL gfHideAfterPlaying = FALSE; BOOL gfShowWhilePlaying = TRUE; BOOL gfCloseAtEndOfPlay = FALSE;
TCHAR gachLinkFilename[_MAX_PATH];
BOOL gfClosing = FALSE;
int giExtWidth; // Metafile extent width
int giExtHeight; // Metafile extent height
//
// Utility functions ported from old OLE1 code
//
/*
* DibFromBitmap() * * Will create a global memory block in DIB format that represents the DDB * passed in * */
#define WIDTHBYTES(i) ((unsigned)((i+31)&(~31))/8) /* ULONG aligned ! */
HANDLE FAR PASCAL DibFromBitmap(HBITMAP hbm, HPALETTE hpal, HANDLE hMem) { BITMAP bm; BITMAPINFOHEADER bi; BITMAPINFOHEADER FAR *lpbi; DWORD dw; HANDLE hdib = NULL; HDC hdc; HPALETTE hpalT;
if (!hbm) return NULL;
GetObject(hbm,sizeof(bm),&bm);
bi.biSize = sizeof(BITMAPINFOHEADER); bi.biWidth = bm.bmWidth; bi.biHeight = bm.bmHeight; bi.biPlanes = 1; bi.biBitCount = (bm.bmPlanes * bm.bmBitsPixel) > 8 ? 24 : 8; bi.biCompression = BI_RGB; bi.biSizeImage = (DWORD)WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = bi.biBitCount == 8 ? 256 : 0; bi.biClrImportant = 0;
dw = bi.biSize + bi.biClrUsed * sizeof(RGBQUAD) + bi.biSizeImage;
if (hMem && GlobalSize(hMem) != 0) { if (GlobalSize(hMem) < dw) return NULL;
lpbi = GlobalLock(hMem); } else lpbi = GlobalAllocPtr(GHND | GMEM_DDESHARE, dw);
if (!lpbi) return NULL; *lpbi = bi;
hdc = CreateCompatibleDC(NULL);
if (hdc) { if (hpal) { hpalT = SelectPalette(hdc,hpal,FALSE); RealizePalette(hdc); }
GetDIBits(hdc, hbm, 0, (UINT)bi.biHeight, (LPBYTE)lpbi + (int)lpbi->biSize + (int)lpbi->biClrUsed * sizeof(RGBQUAD), (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
if (hpal) SelectPalette(hdc,hpalT,FALSE);
DeleteDC(hdc); }
hdib = GlobalHandle(lpbi); GlobalUnlock(hdib); return hdib; }
HANDLE GetDIB(HANDLE hMem) { HPALETTE hpal = GetStockObject(DEFAULT_PALETTE); HBITMAP hbm = GetBitmap(); HANDLE hDib = NULL;
if (hbm && hpal) { hDib = DibFromBitmap(hbm,hpal,hMem); if (!hDib) DOUT(TEXT("DibFromBitmap failed!\r\n")); } if (hpal) DeleteObject(hpal); if (hbm) DeleteObject(hbm); return hDib; }
HBITMAP GetBitmap(void) { HDC hdcmem = NULL; HDC hdc = NULL; HBITMAP hbitmap = NULL; HBITMAP holdbitmap = NULL; RECT rc; hdc = GetDC(ghwndApp); if (hdc) { SetRect(&rc, 0, 0, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
hdcmem = CreateCompatibleDC(hdc); if (hdcmem) { hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom); holdbitmap = (HBITMAP)SelectObject(hdcmem, hbitmap);
// paint directly into the bitmap
PatBlt(hdcmem, 0, 0, rc.right, rc.bottom, WHITENESS); DrawIcon(hdcmem, 0, 0, ghiconApp);
hbitmap = (HBITMAP)SelectObject(hdcmem, holdbitmap); DeleteDC(hdcmem); } ReleaseDC(ghwndApp, hdc); } return hbitmap; }
#pragma message("this code should extract the picture from the file")
HANDLE GetPicture(void) { HANDLE hpict = NULL; HMETAFILE hMF = NULL;
LPMETAFILEPICT lppict = NULL; HBITMAP hbmT = NULL; HDC hdcmem = NULL; HDC hdc = NULL;
BITMAP bm; HBITMAP hbm; hbm = GetBitmap(); if (hbm == NULL) return NULL;
GetObject(hbm, sizeof(bm), (LPVOID)&bm); hdc = GetDC(ghwndApp); if (hdc) { hdcmem = CreateCompatibleDC(hdc); ReleaseDC(ghwndApp, hdc); } if (!hdcmem) { DeleteObject(hbm); return NULL; } hdc = CreateMetaFile(NULL); hbmT = (HBITMAP)SelectObject(hdcmem, hbm);
SetWindowOrgEx(hdc, 0, 0, NULL); SetWindowExtEx(hdc, bm.bmWidth, bm.bmHeight, NULL);
StretchBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcmem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
hMF = CloseMetaFile(hdc);
SelectObject(hdcmem, hbmT); DeleteObject(hbm); DeleteDC(hdcmem);
lppict = (LPMETAFILEPICT)GlobalAllocPtr(GHND|GMEM_DDESHARE , sizeof(METAFILEPICT)); if (!lppict) { if (hMF) DeleteMetaFile(hMF); return NULL; } hdc = GetDC(ghwndApp); lppict->mm = MM_ANISOTROPIC; lppict->hMF = hMF; lppict->xExt = MulDiv(bm.bmWidth, 2540, GetDeviceCaps(hdc, LOGPIXELSX)); lppict->yExt = MulDiv(bm.bmHeight, 2540, GetDeviceCaps(hdc, LOGPIXELSX)); giExtWidth = lppict->xExt; giExtHeight = lppict->yExt; ReleaseDC(ghwndApp, hdc);
hpict = GlobalHandle(lppict); GlobalUnlock(hpict); return hpict; }
//
// Code ported from server.c (OLE1) for serialization...
//
HANDLE GetNativeData(void) { LPBYTE lplink = NULL; MMIOINFO mmioinfo; HMMIO hmmio; BOOL fOk;
lplink = (LPBYTE)GlobalAllocPtr(GHND | GMEM_SHARE, 4096L);
if (lplink == NULL) { #if DBG
OutputDebugString(TEXT("GetNativeData: malloc failed\r\n")); #endif
return NULL; } mmioinfo.fccIOProc = FOURCC_MEM; mmioinfo.pIOProc = NULL; mmioinfo.pchBuffer = lplink; mmioinfo.cchBuffer = 4096L; // initial size
mmioinfo.adwInfo[0] = 4096L; // grow by this much
hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READWRITE);
if (hmmio == NULL) { GlobalFreePtr(lplink); return NULL; }
fOk = WriteWaveFile(hmmio , gpWaveFormat , gcbWaveFormat , gpWaveSamples , glWaveSamplesValid);
mmioGetInfo(hmmio, &mmioinfo, 0); mmioClose(hmmio,0);
if (fOk) { //
// Warning, the buffer we allocated may have been realloc'd
//
HANDLE hlink = GlobalHandle(mmioinfo.pchBuffer); GlobalUnlock(hlink); return hlink; } else { gfErrorBox++; ErrorResBox( ghwndApp , ghInst , MB_ICONEXCLAMATION | MB_OK , IDS_APPTITLE , IDS_ERROREMBED ); #if DBG
OutputDebugString(TEXT("Failed to WriteWaveFile\r\n")); #endif
gfErrorBox--; //
// Warning, the buffer we allocated may have been realloc'd
//
if (mmioinfo.pchBuffer) GlobalFreePtr(mmioinfo.pchBuffer); return NULL; } }
/*
* Called from OLE storage code */ LPBYTE PutNativeData(LPBYTE lpbData, DWORD dwSize) { MMIOINFO mmioinfo; HMMIO hmmio;
MMRESULT mmr; LPWAVEFORMATEX pwfx; DWORD cbwfx; DWORD cbdata; LPBYTE pdata;
mmioinfo.fccIOProc = FOURCC_MEM; mmioinfo.pIOProc = NULL; mmioinfo.pchBuffer = lpbData; mmioinfo.cchBuffer = dwSize; // initial size
mmioinfo.adwInfo[0] = 0L; // grow by this much
hmmio = mmioOpen(NULL, &mmioinfo, MMIO_READ); if (hmmio) { mmr = ReadWaveFile(hmmio , &pwfx , &cbwfx , &pdata , &cbdata , TEXT("NativeData") , TRUE); mmioClose(hmmio,0);
if (mmr != MMSYSERR_NOERROR) return NULL; if (pwfx == NULL) return NULL; DestroyWave(); gpWaveFormat = pwfx; gcbWaveFormat = cbwfx; gpWaveSamples = pdata; glWaveSamples = cbdata; }
//
// update state variables
//
glWaveSamplesValid = glWaveSamples; glWavePosition = 0L; gfDirty = FALSE; //
// update the display
//
UpdateDisplay(TRUE);
return (LPBYTE)gpWaveSamples; }
/*
* PERMANENT ENTRY POINTS */ BOOL ParseCommandLine(LPTSTR lpCommandLine);
/*
* modifies gfEmbedded, initializes gStartParams */
BOOL InitializeSRS(HINSTANCE hInst) { TCHAR * lptCmdLine = GetCommandLine(); BOOL fOLE = FALSE, fServer; gfUserClose = FALSE; gachLinkFilename[0] = 0;
fServer = ParseCommandLine(lptCmdLine); gfEmbedded = fServer; // We are embedded or linked
if (!fServer) { if (gStartParams.achOpenFilename[0] != 0) { lstrcpy(gachLinkFilename, gStartParams.achOpenFilename); } }
//
// Only if we are invoked as an embedded object do we initialize OLE.
// Defer initialization for the standalone object until later.
//
if (gfEmbedded) fOLE = InitializeOle(hInst); return fOLE; }
/* OLE initialization
*/ BOOL InitializeOle(HINSTANCE hInst) { BOOL fOLE;
DOUT(TEXT("SOUNDREC: Initializing OLE\r\n")); dwOleBuildVersion = OleBuildVersion();
// Fix bug #33271
// As stated in the docs:
// Typically, the COM library is initialized on an apartment only once.
// Subsequent calls will succeed, as long as they do not attempt to change
// the concurrency model of the apartment, but will return S_FALSE. To close
// the COM library gracefully, each successful call to OleInitialize,
// including those that return S_FALSE, must be balanced by a corresponding
// call to OleUninitialize.
// gfOleInitialized = (OleInitialize(NULL) == NOERROR) ? TRUE : FALSE;
gfOleInitialized = SUCCEEDED(OleInitialize(NULL));
if (gfOleInitialized) fOLE = CreateSRClassFactory(hInst, gfEmbedded); else fOLE = FALSE; // signal a serious problem!
return fOLE; }
/*
* Initialize the state of the application or * change state from Embedded to Standalone. */ void FlagEmbeddedObject(BOOL flag) { // Set global state variables. Note, gfEmbedding is untouched.
gfEmbeddedObject = flag; gfStandalone = !flag;
}
void SetOleCaption( LPTSTR lpszObj) { TCHAR aszFormatString[256]; LPTSTR lpszTitle; //
// Change title to "Sound Object in XXX"
//
LoadString(ghInst, IDS_OBJECTTITLE, aszFormatString, SIZEOF(aszFormatString));
lpszTitle = (LPTSTR)GlobalAllocPtr(GHND, (lstrlen(lpszObj) + SIZEOF(aszFormatString))*sizeof(TCHAR)); if (lpszTitle) { wsprintf(lpszTitle, aszFormatString, lpszObj); SetWindowText(ghwndApp, lpszTitle); GlobalFreePtr(lpszTitle); } }
void SetOleMenu( HMENU hMenu, LPTSTR lpszObj) { TCHAR aszFormatString[256]; LPTSTR lpszMenu; //
// Change menu to "Exit & Return to XXX"
//
LoadString(ghInst, IDS_EXITANDRETURN, aszFormatString, SIZEOF(aszFormatString));
lpszMenu = (LPTSTR)GlobalAllocPtr(GHND, (lstrlen(lpszObj) + SIZEOF(aszFormatString))*sizeof(TCHAR)); if (lpszMenu) { wsprintf(lpszMenu, aszFormatString, lpszObj); ModifyMenu(hMenu, IDM_EXIT, MF_BYCOMMAND, IDM_EXIT, lpszMenu); GlobalFreePtr(lpszMenu); } }
/* Adjust menus according to system state.
* */ void FixMenus(void) { HMENU hMenu; hMenu = GetMenu(ghwndApp); if (!gfLinked && gfEmbeddedObject) { // Remove these menu items as they are irrelevant.
DeleteMenu(hMenu, IDM_NEW, MF_BYCOMMAND); DeleteMenu(hMenu, IDM_SAVE, MF_BYCOMMAND); DeleteMenu(hMenu, IDM_SAVEAS, MF_BYCOMMAND); DeleteMenu(hMenu, IDM_REVERT, MF_BYCOMMAND); DeleteMenu(hMenu, IDM_OPEN, MF_BYCOMMAND); } else { TCHAR ach[40]; // Is this necessary?
LoadString(ghInst, IDS_NONEMBEDDEDSAVE, ach, SIZEOF(ach)); ModifyMenu(hMenu, IDM_SAVE, MF_BYCOMMAND, IDM_SAVE, ach); }
//
// Update the titlebar and exit menu too.
//
if (!gfLinked && gfEmbeddedObject) { LPTSTR lpszObj = NULL; LPTSTR lpszApp = NULL; OleObjGetHostNames(&lpszApp,&lpszObj); if (lpszObj) lpszObj = (LPTSTR)FileName((LPCTSTR)lpszObj); if (lpszObj) { SetOleCaption(lpszObj); SetOleMenu(hMenu, lpszObj); } }
DrawMenuBar(ghwndApp); /* Can't hurt... */ }
#define WM_USER_DESTROY (WM_USER+10)
//
// Called from WM_CLOSE (from user) or SCtrl::~SCtrl (from container)
//
void TerminateServer(void) { DOUT(TEXT("SoundRec: TerminateServer\r\n")); gfTerminating = TRUE;
if (gfOleInitialized) { WriteObjectIfEmpty(); ReleaseSRClassFactory(); FlushOleClipboard(); //
// If, at this time, we haven't closed, we really should.
//
if (!gfClosing) { DoOleClose(TRUE); AdviseClosed(); } } //
// only if the user is terminating OR we're embedded
//
if (gfUserClose || !gfStandalone) PostMessage(ghwndApp, WM_USER_DESTROY, 0, 0); }
/* start params!
* the app will use these params to determine behaviour once started. */ StartParams gStartParams = { FALSE,FALSE,FALSE,FALSE,TEXT("") };
BOOL ParseCommandLine(LPTSTR lpCommandLine) { #define TEST_STRING_MAX 11 // sizeof szEmbedding
#define NUMOPTIONS 6
static TCHAR szEmbedding[] = TEXT("embedding"); static TCHAR szPlay[] = TEXT("play"); static TCHAR szOpen[] = TEXT("open"); static TCHAR szNew[] = TEXT("new"); static TCHAR szClose[] = TEXT("close"); static struct tagOption { LPTSTR name; LPTSTR filename; int cchfilename; LPBOOL state; } options [] = { { NULL, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fOpen }, { szEmbedding, gStartParams.achOpenFilename, _MAX_PATH, &gfEmbedded }, { szPlay, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fPlay }, { szOpen, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fOpen }, { szNew, gStartParams.achOpenFilename, _MAX_PATH, &gStartParams.fNew }, { szClose, NULL, 0, &gStartParams.fClose } };
LPTSTR pchNext; int iOption = 0,i,cNumOptions = sizeof(options)/sizeof(struct tagOption); TCHAR szSwitch[TEST_STRING_MAX]; TCHAR ch; if (lpCommandLine == NULL) return FALSE; /* skip argv[0] */ if (*lpCommandLine == TEXT('"')) { //
// eat up everything to the next quote
//
lpCommandLine++; do { ch = *lpCommandLine++; } while (ch != TEXT('"')); } else { //
// eat up everything to the next whitespace
//
ch = *lpCommandLine; while (ch != TEXT(' ') && ch != TEXT('\t') && ch != TEXT('\0')) ch = *++lpCommandLine; } pchNext = lpCommandLine; while ( *pchNext ) { LPTSTR pchName = options[iOption].filename; int cchName = options[iOption].cchfilename; /* whitespace */ switch (*pchNext) { case TEXT(' '): case TEXT('\t'): pchNext++; continue;
case TEXT('-'): case TEXT('/'): { lstrcpyn(szSwitch,pchNext+1,TEST_STRING_MAX); szSwitch[TEST_STRING_MAX-1] = 0;
/* scan to the NULL or ' ' and terminate string */ for (i = 0; i < TEST_STRING_MAX && szSwitch[i] != 0; i++) if (szSwitch[i] == TEXT(' ')) { szSwitch[i] = 0; break; } /* now test each option switch for a hit */
for (i = 0; i < cNumOptions; i++) { if (options[i].name == NULL) continue; if (!lstrcmpi(szSwitch,options[i].name)) { *(options[i].state) = TRUE; if (options[i].filename) /* next non switch string applies to this option */ iOption = i; break; } } /* seek ahead */ while (*pchNext && *pchNext != TEXT(' ')) pchNext++; continue; } case TEXT('\"'): /* filename */ /* copy up to next quote */ pchNext++; while (*pchNext && *pchNext != TEXT('\"')) { if (cchName) { *pchName++ = *pchNext++; cchName--; } else break; } pchNext++; continue; default: /* filename */ /* copy up to the end */ while (*pchNext && cchName) { *pchName++ = *pchNext++; cchName--; } break; } } /* special case.
* we are linked if given a LinkFilename and an embedding flag. * Does this ever happen or only through IPersistFile? */ if (gfEmbedded && gStartParams.achOpenFilename[0] != 0) { gfLinked = TRUE; } return gfEmbedded; }
void BuildUniqueLinkName(void) { //
//Ensure a unique filename in gachLinkFilename so we can create valid
//FileMonikers...
//
if(gachLinkFilename[0] == 0) { TCHAR aszFile[_MAX_PATH]; GetTempFileName(TEXT("."), TEXT("Tmp"), 0, gachLinkFilename); /* GetTempFileName creates an empty file, delete it.
*/ GetFullPathName(gachLinkFilename,SIZEOF(aszFile),aszFile,NULL); DeleteFile(aszFile); } }
void AppPlay(BOOL fClose) { if (fClose) { //ugh. don't show while playing.
gfShowWhilePlaying = FALSE; } if (IsWindow(ghwndApp)) { gfCloseAtEndOfPlay = fClose; PostMessage(ghwndApp,WM_COMMAND,ID_PLAYBTN, 0L); } }
|