2025-11-28 00:35:46 +09:00

303 lines
8.2 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// dllmain.cpp : Implements DLL exports and COM class factory
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Note: This source file implements the class factory for the sample
// media source, plus the following DLL functions:
// - DllMain
// - DllCanUnloadNow
// - DllRegisterServer
// - DllUnregisterServer
// - DllGetClassObject
//
//////////////////////////////////////////////////////////////////////////
#include "MPEG1Source.h"
#include "MPEG1ByteStreamHandler.h"
#include <assert.h>
#include <strsafe.h>
#include "ClassFactory.h" // Implements IClassFactory
#include "registry.h" // Helpers to register COM objects.
#include <initguid.h>
// {EFE6208A-0A2C-49fa-8A01-3768B559B6DA}
DEFINE_GUID(CLSID_MFSampleMPEG1ByteStreamHandler,
0xefe6208a, 0xa2c, 0x49fa, 0x8a, 0x1, 0x37, 0x68, 0xb5, 0x59, 0xb6, 0xda);
HMODULE g_hModule; // DLL module handle
// Defines the class factory lock variable:
DEFINE_CLASSFACTORY_SERVER_LOCK;
// g_ClassFactories: Array of class factory data.
// Defines a look-up table of CLSIDs and corresponding creation functions.
ClassFactoryData g_ClassFactories[] =
{
{ &CLSID_MFSampleMPEG1ByteStreamHandler, MPEG1ByteStreamHandler::CreateInstance }
};
DWORD g_numClassFactories = ARRAYSIZE(g_ClassFactories);
// Text strings
// Description string for the bytestream handler.
const TCHAR* sByteStreamHandlerDescription = TEXT("MPEG1 Source ByteStreamHandler");
// File extension for WAVE files.
const TCHAR* sFileExtension = TEXT(".mpg");
// Registry location for bytestream handlers.
const TCHAR* REGKEY_MF_BYTESTREAM_HANDLERS
= TEXT("Software\\Microsoft\\Windows Media Foundation\\ByteStreamHandlers");
// Forward declarations
// Functions to register and unregister the byte stream handler.
HRESULT RegisterByteStreamHandler(const GUID& guid, const TCHAR *sFileExtension, const TCHAR *sDescription);
HRESULT UnregisterByteStreamHandler(const GUID& guid, const TCHAR *sFileExtension);
// Misc Registry helpers
HRESULT SetKeyValue(HKEY hKey, const TCHAR *sName, const TCHAR *sValue);
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hModule = (HMODULE)hModule;
TRACE_INIT();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
TRACE_CLOSE();
break;
}
return TRUE;
}
STDAPI DllCanUnloadNow()
{
if (!ClassFactory::IsLocked())
{
return S_OK;
}
else
{
return S_FALSE;
}
}
STDAPI DllRegisterServer()
{
HRESULT hr = S_OK;
// Register the bytestream handler's CLSID as a COM object.
CHECK_HR(hr = RegisterObject(
g_hModule, // Module handle
CLSID_MFSampleMPEG1ByteStreamHandler, // CLSID
sByteStreamHandlerDescription, // Description
TEXT("Both") // Threading model
));
// Register the bytestream handler as the handler for the MPEG-1 file extension.
CHECK_HR(hr = RegisterByteStreamHandler(
CLSID_MFSampleMPEG1ByteStreamHandler, // CLSID
sFileExtension, // Supported file extension
sByteStreamHandlerDescription // Description
));
done:
return hr;
}
STDAPI DllUnregisterServer()
{
// Unregister the CLSIDs
UnregisterObject(CLSID_MFSampleMPEG1ByteStreamHandler);
// Unregister the bytestream handler for the file extension.
UnregisterByteStreamHandler(CLSID_MFSampleMPEG1ByteStreamHandler, sFileExtension);
return S_OK;
}
STDAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void** ppv)
{
ClassFactory *pFactory = NULL;
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE; // Default to failure
// Find an entry in our look-up table for the specified CLSID.
for (DWORD index = 0; index < g_numClassFactories; index++)
{
if (*g_ClassFactories[index].pclsid == clsid)
{
// Found an entry. Create a new class factory object.
pFactory = new ClassFactory(g_ClassFactories[index].pfnCreate);
if (pFactory)
{
hr = S_OK;
}
else
{
hr = E_OUTOFMEMORY;
}
break;
}
}
if (SUCCEEDED(hr))
{
hr = pFactory->QueryInterface(riid, ppv);
}
SAFE_RELEASE(pFactory);
return hr;
}
///////////////////////////////////////////////////////////////////////
// Name: CreateRegistryKey
// Desc: Creates a new registry key. (Thin wrapper just to encapsulate
// all of the default options.)
///////////////////////////////////////////////////////////////////////
HRESULT CreateRegistryKey(HKEY hKey, LPCTSTR subkey, HKEY *phKey)
{
assert(phKey != NULL);
LONG lreturn = RegCreateKeyEx(
hKey, // parent key
subkey, // name of subkey
0, // reserved
NULL, // class string (can be NULL)
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL, // security attributes
phKey,
NULL // receives the "disposition" (is it a new or existing key)
);
return HRESULT_FROM_WIN32(lreturn);
}
///////////////////////////////////////////////////////////////////////
// Name: RegisterByteStreamHandler
// Desc: Register a bytestream handler for the Media Foundation
// source resolver.
//
// guid: CLSID of the bytestream handler.
// sFileExtension: File extension.
// sDescription: Description.
//
// Note: sFileExtension can also be a MIME type although that is not
// illustrated in this sample.
///////////////////////////////////////////////////////////////////////
HRESULT RegisterByteStreamHandler(const GUID& guid, const TCHAR *sFileExtension, const TCHAR *sDescription)
{
HRESULT hr = S_OK;
// Open HKCU/<byte stream handlers>/<file extension>
// Create {clsid} = <description> key
HKEY hKey = NULL;
HKEY hSubKey = NULL;
OLECHAR szCLSID[CHARS_IN_GUID];
size_t cchDescription = 0;
hr = StringCchLength(sDescription, STRSAFE_MAX_CCH, &cchDescription);
if (SUCCEEDED(hr))
{
hr = StringFromGUID2(guid, szCLSID, CHARS_IN_GUID);
}
if (SUCCEEDED(hr))
{
hr = CreateRegistryKey(HKEY_LOCAL_MACHINE, REGKEY_MF_BYTESTREAM_HANDLERS, &hKey);
}
if (SUCCEEDED(hr))
{
hr = CreateRegistryKey(hKey, sFileExtension, &hSubKey);
}
if (SUCCEEDED(hr))
{
hr = RegSetValueEx(
hSubKey,
szCLSID,
0,
REG_SZ,
(BYTE*)sDescription,
static_cast<DWORD>((cchDescription + 1) * sizeof(TCHAR))
);
}
if (hSubKey != NULL)
{
RegCloseKey( hSubKey );
}
if (hKey != NULL)
{
RegCloseKey( hKey );
}
return hr;
}
HRESULT UnregisterByteStreamHandler(const GUID& guid, const TCHAR *sFileExtension)
{
TCHAR szKey[MAX_PATH];
OLECHAR szCLSID[CHARS_IN_GUID];
DWORD result = 0;
HRESULT hr = S_OK;
// Create the subkey name.
CHECK_HR(hr = StringCchPrintf(
szKey, MAX_PATH, TEXT("%s\\%s"), REGKEY_MF_BYTESTREAM_HANDLERS, sFileExtension));
// Create the CLSID name in canonical form.
CHECK_HR(hr = StringFromGUID2(guid, szCLSID, CHARS_IN_GUID));
// Delete the CLSID entry under the subkey.
// Note: There might be multiple entries for this file extension, so we should not delete
// the entire subkey, just the entry for this CLSID.
result = RegDeleteKeyValue(HKEY_LOCAL_MACHINE, szKey, szCLSID);
if (result != ERROR_SUCCESS)
{
CHECK_HR(hr = HRESULT_FROM_WIN32(result));
}
done:
return hr;
}