Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

412 lines
16 KiB

/********************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
PCH_Codec.CPP
Abstract:
WBEM provider class implementation for PCH_CODEC class
Revision History:
Ghim-Sim Chua (gschua) 04/27/99
- created
Ghim-Sim Chua (gschua) 05/02/99
- Modified code to use CopyProperty function
- Use CComBSTR instead of USES_CONVERSION
Jim Martin (a-jammar) 05/13/99
- Picked up the remaining properties (groupname and key
from the registry.
********************************************************************/
#include "pchealth.h"
#include "PCH_Codec.h"
/////////////////////////////////////////////////////////////////////////////
// tracing stuff
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
#define TRACE_ID DCID_CODEC
CPCH_Codec MyPCH_CodecSet (PROVIDER_NAME_PCH_CODEC, PCH_NAMESPACE) ;
// Property names
//===============
const static WCHAR* pCategory = L"Category" ;
const static WCHAR* pTimeStamp = L"TimeStamp" ;
const static WCHAR* pChange = L"Change" ;
const static WCHAR* pCodecDriver = L"CodecDriver" ;
const static WCHAR* pDate = L"Date" ;
const static WCHAR* pDescription = L"Description" ;
const static WCHAR* pGroupName = L"GroupName" ;
const static WCHAR* pkey = L"key" ;
const static WCHAR* pSize = L"Size" ;
const static WCHAR* pVersion = L"Version" ;
//-----------------------------------------------------------------------------
// Part of the data from the PCH_CODEC class does not come from the cimv2
// Win32_CODECFile class, but from the registry. The "GroupName" and "Key"
// properties are found at:
//
// HKLM\System\CurrentControlSet\Control\MediaResources\<group>\<key>:driver
//
// Where the "driver" value is equal to the filename of the CODEC. Due to the
// way this part of the registry is constructed, we can't find the <group>
// and <key> given the driver name. We'll need to build a map from driver
// to <group> and <key> - building the map requires traversing the registry.
//
// This class is used as a helper for that lookup. When it's created, it
// scans the registry, processing all of the CODEC entries. It can then
// be queried for the key and group associated with a driver.
//-----------------------------------------------------------------------------
#define MAX_DRIVER_LEN MAX_PATH
#define MAX_KEY_LEN MAX_PATH
#define MAX_GROUP_LEN MAX_PATH
class CCODECInfo
{
public:
CCODECInfo();
~CCODECInfo();
BOOL QueryCODECInfo(LPCTSTR szDriver, LPCSTR * pszKey, LPCSTR * pszGroup);
private:
struct SCODECNode
{
TCHAR m_szDriver[MAX_DRIVER_LEN];
TCHAR m_szKey[MAX_KEY_LEN];
TCHAR m_szGroup[MAX_GROUP_LEN];
SCODECNode * m_pNext;
};
SCODECNode * m_pCODECList;
};
//-----------------------------------------------------------------------------
// The constructor reads the CODEC info from the registry and builds a linked
// list (unsorted) of entries. The destructor deletes it.
//-----------------------------------------------------------------------------
CCODECInfo::CCODECInfo() : m_pCODECList(NULL)
{
TraceFunctEnter("CCODECInfo::CCODECInfo");
LPCTSTR szCODECKey = _T("System\\CurrentControlSet\\Control\\MediaResources");
LPTSTR szDrvValue = _T("driver");
HKEY hkeyCODEC;
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCODECKey, 0, KEY_READ, &hkeyCODEC))
ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on CODEC key.");
else
{
// Enumerate each subkey of the CODEC key. Each subkey corresponds to a group.
DWORD dwGroupIndex = 0;
DWORD dwSize = MAX_GROUP_LEN;
FILETIME ft;
TCHAR szGroup[MAX_GROUP_LEN];
TCHAR szKey[MAX_KEY_LEN];
TCHAR szDriver[MAX_DRIVER_LEN];
while (ERROR_SUCCESS == RegEnumKeyEx(hkeyCODEC, dwGroupIndex, szGroup, &dwSize, 0, NULL, NULL, &ft))
{
// Open the group subkey. Then enumerate it's subkeys. These will be the keys.
HKEY hkeyGroup;
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyCODEC, szGroup, 0, KEY_READ, &hkeyGroup))
ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on group key = %s.", szGroup);
else
{
dwSize = MAX_KEY_LEN;
DWORD dwKeyIndex = 0;
while (ERROR_SUCCESS == RegEnumKeyEx(hkeyGroup, dwKeyIndex, szKey, &dwSize, 0, NULL, NULL, &ft))
{
// For each key, attempt to get the value named "driver". This is the
// filename for the driver for this CODEC.
HKEY hkeyKey;
if (ERROR_SUCCESS != RegOpenKeyEx(hkeyGroup, szKey, 0, KEY_READ, &hkeyKey))
ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on key = %s.", szKey);
else
{
// Note - there's no trace here because sometimes there may not be
// a driver value, and this is not an error for us.
dwSize = MAX_DRIVER_LEN * sizeof(TCHAR); // this wants the size in bytes
DWORD dwType = REG_SZ;
if (ERROR_SUCCESS == RegQueryValueEx(hkeyKey, szDrvValue, NULL, &dwType, (LPBYTE) szDriver, &dwSize))
{
if (*szGroup && *szKey && *szDriver)
{
// Here's where we insert a value into the map, using
// the strings szDriver, szKey and szGroup.
SCODECNode * pNew = new SCODECNode;
if (!pNew)
{
ErrorTrace(TRACE_ID, "Out of memory.");
RegCloseKey(hkeyKey);
RegCloseKey(hkeyGroup);
RegCloseKey(hkeyCODEC);
throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
}
_tcscpy(pNew->m_szDriver, szDriver);
_tcscpy(pNew->m_szKey, szKey);
_tcscpy(pNew->m_szGroup, szGroup);
pNew->m_pNext = m_pCODECList;
m_pCODECList = pNew;
}
}
if (ERROR_SUCCESS != RegCloseKey(hkeyKey))
ErrorTrace(TRACE_ID, "RegCloseKey failed on key.");
}
dwSize = MAX_KEY_LEN;
dwKeyIndex += 1;
}
if (ERROR_SUCCESS != RegCloseKey(hkeyGroup))
ErrorTrace(TRACE_ID, "RegCloseKey failed on key.");
}
dwSize = MAX_GROUP_LEN;
dwGroupIndex += 1;
}
if (ERROR_SUCCESS != RegCloseKey(hkeyCODEC))
ErrorTrace(TRACE_ID, "RegCloseKey failed on CODEC key.");
}
TraceFunctLeave();
}
CCODECInfo::~CCODECInfo()
{
TraceFunctEnter("CCODECInfo::~CCODECInfo");
while (m_pCODECList)
{
SCODECNode * pNext = m_pCODECList->m_pNext;
delete m_pCODECList;
m_pCODECList = pNext;
}
TraceFunctLeave();
}
//-----------------------------------------------------------------------------
// Search for the requested driver in the list of CODEC information entries.
// If it's found, set pszKey and pszGroup to point to the key and group strings
// in the entry and return TRUE, otherwise return FALSE. Note: copies of the
// strings are not made, so the caller is not responsible for deallocating
// the strings. Another note: the string pointers won't be valid after the
// CCODECInfo object is destructed.
//-----------------------------------------------------------------------------
BOOL CCODECInfo::QueryCODECInfo(LPCTSTR szDriver, LPCTSTR * pszKey, LPCTSTR * pszGroup)
{
TraceFunctEnter("CCODECInfo::QueryCODECInfo");
_ASSERT(szDriver && pszKey && pszGroup);
SCODECNode * pScan = m_pCODECList;
BOOL fReturn = FALSE;
while (pScan)
{
if (0 == _tcscmp(szDriver, pScan->m_szDriver))
{
*pszKey = pScan->m_szKey;
*pszGroup = pScan->m_szGroup;
fReturn = TRUE;
break;
}
pScan = pScan->m_pNext;
}
TraceFunctLeave();
return fReturn;
}
/*****************************************************************************
*
* FUNCTION : CPCH_Codec::EnumerateInstances
*
* DESCRIPTION : Returns all the instances of this class.
*
* INPUTS : A pointer to the MethodContext for communication with WinMgmt.
* A long that contains the flags described in
* IWbemServices::CreateInstanceEnumAsync. Note that the following
* flags are handled by (and filtered out by) WinMgmt:
* WBEM_FLAG_DEEP
* WBEM_FLAG_SHALLOW
* WBEM_FLAG_RETURN_IMMEDIATELY
* WBEM_FLAG_FORWARD_ONLY
* WBEM_FLAG_BIDIRECTIONAL
*
* RETURNS : WBEM_S_NO_ERROR if successful
*
* COMMENTS : TO DO: All instances on the machine should be returned here.
* If there are no instances, return WBEM_S_NO_ERROR.
* It is not an error to have no instances.
*
*****************************************************************************/
HRESULT CPCH_Codec::EnumerateInstances(MethodContext * pMethodContext, long lFlags)
{
TraceFunctEnter("CPCH_Codec::EnumerateInstances");
USES_CONVERSION;
HRESULT hRes = WBEM_S_NO_ERROR;
REFPTRCOLLECTION_POSITION posList;
CComPtr<IEnumWbemClassObject> pEnumInst;
IWbemClassObjectPtr pObj;
ULONG ulRetVal;
// This instance of CCODECInfo will provide some of the missing information
// about each CODEC. Constructing it queries the registry for CODEC info.
CCODECInfo codecinfo;
// Get the date and time
SYSTEMTIME stUTCTime;
GetSystemTime(&stUTCTime);
// Execute the query
hRes = ExecWQLQuery(&pEnumInst, CComBSTR("SELECT * FROM Win32_CodecFile"));
if (FAILED(hRes))
goto END;
// enumerate the instances from win32_CodecFile
while (WBEM_S_NO_ERROR == pEnumInst->Next(WBEM_INFINITE, 1, &pObj, &ulRetVal))
{
// Create a new instance based on the passed-in MethodContext
CInstancePtr pInstance(CreateNewInstance(pMethodContext), false);
CComVariant varValue;
if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)))
ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
if (!pInstance->SetCHString(pChange, L"Snapshot"))
ErrorTrace(TRACE_ID, "SetCHString on Change Field failed.");
(void)CopyProperty(pObj, L"group", pInstance, pCategory);
(void)CopyProperty(pObj, L"name", pInstance, pCodecDriver);
(void)CopyProperty(pObj, L"description", pInstance, pDescription);
(void)CopyProperty(pObj, L"filesize", pInstance, pSize);
(void)CopyProperty(pObj, L"version", pInstance, pVersion);
// BUGBUG: WMI does not seem to be populating this field correctly.
// Even though Win32_CODECFile is derived from CIM_DataFile, it doesn't
// seem to be inheriting CreationDate. This is what we'd like to do:
//
// (void)CopyProperty(pObj, "CreationDate", pInstance, pDate);
// Get the data which is missing from the Win32_CODECClass. Use the
// instance of CCODECInfo we declared - we need to pass in just the
// driver name (without the complete path).
CComBSTR bstrDriver("name");
if (FAILED(pObj->Get(bstrDriver, 0, &varValue, NULL, NULL)))
ErrorTrace(TRACE_ID, "GetVariant on pCodecDriver field failed.");
else
{
CComBSTR ccombstrValue(V_BSTR(&varValue));
// Because Win32_CODECFile doesn't seem to be inheriting
// CreationDate, we need to get the actual creation date
// by calling API functions.
LPTSTR szName = W2T(ccombstrValue);
HANDLE hFile = CreateFile(szName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE == hFile)
ErrorTrace(TRACE_ID, "Couldn't open codec file to get date.");
else
{
SYSTEMTIME stFileTime;
FILETIME ftFileTime;
if (GetFileTime(hFile, NULL, NULL, &ftFileTime))
if (FileTimeToSystemTime(&ftFileTime, &stFileTime))
if (!pInstance->SetDateTime(pDate, WBEMTime(stFileTime)))
ErrorTrace(TRACE_ID, "SetDateTime on date field failed.");
CloseHandle(hFile);
}
// We need to convert the string from a BSTR to a LPCTSTR,
// and to only include the file part (without the path).
UINT uLen = SysStringLen(ccombstrValue);
// Scan backwards through the string until we've either reached
// the start (shouldn't happen) or a '\'.
UINT iChar = uLen - 1;
while (iChar && ccombstrValue[iChar] != L'\\')
iChar -= 1;
// Then scan to the end of the string, copying the filename.
if (ccombstrValue[iChar] == L'\\')
iChar += 1;
TCHAR szDriver[MAX_DRIVER_LEN + 1] = _T("");
int i = 0;
while (iChar < uLen && i < MAX_DRIVER_LEN)
szDriver[i++] = (TCHAR) ccombstrValue[iChar++];
szDriver[i] = _T('\0');
LPCSTR szKey = NULL;
LPCSTR szGroup = NULL;
if (codecinfo.QueryCODECInfo(szDriver, &szKey, &szGroup))
{
if (!pInstance->SetCHString(pkey, szKey))
ErrorTrace(TRACE_ID, "SetCHString on key field failed.");
if (!pInstance->SetCHString(pGroupName, szGroup))
ErrorTrace(TRACE_ID, "SetCHString on group field failed.");
}
else if (codecinfo.QueryCODECInfo(szName, &szKey, &szGroup))
{
// Sometimes the CODEC is stored in the registry with a complete
// path. If we can't find the CODEC based on just the filename,
// we might find it with the path.
if (!pInstance->SetCHString(pkey, szKey))
ErrorTrace(TRACE_ID, "SetCHString on key field failed.");
if (!pInstance->SetCHString(pGroupName, szGroup))
ErrorTrace(TRACE_ID, "SetCHString on group field failed.");
}
}
hRes = pInstance->Commit();
if (FAILED(hRes))
ErrorTrace(TRACE_ID, "Commit on Instance failed.");
}
END:
TraceFunctLeave();
return hRes;
}