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

  1. /********************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. PCH_Codec.CPP
  5. Abstract:
  6. WBEM provider class implementation for PCH_CODEC class
  7. Revision History:
  8. Ghim-Sim Chua (gschua) 04/27/99
  9. - created
  10. Ghim-Sim Chua (gschua) 05/02/99
  11. - Modified code to use CopyProperty function
  12. - Use CComBSTR instead of USES_CONVERSION
  13. Jim Martin (a-jammar) 05/13/99
  14. - Picked up the remaining properties (groupname and key
  15. from the registry.
  16. ********************************************************************/
  17. #include "pchealth.h"
  18. #include "PCH_Codec.h"
  19. /////////////////////////////////////////////////////////////////////////////
  20. // tracing stuff
  21. #ifdef THIS_FILE
  22. #undef THIS_FILE
  23. #endif
  24. static char __szTraceSourceFile[] = __FILE__;
  25. #define THIS_FILE __szTraceSourceFile
  26. #define TRACE_ID DCID_CODEC
  27. CPCH_Codec MyPCH_CodecSet (PROVIDER_NAME_PCH_CODEC, PCH_NAMESPACE) ;
  28. // Property names
  29. //===============
  30. const static WCHAR* pCategory = L"Category" ;
  31. const static WCHAR* pTimeStamp = L"TimeStamp" ;
  32. const static WCHAR* pChange = L"Change" ;
  33. const static WCHAR* pCodecDriver = L"CodecDriver" ;
  34. const static WCHAR* pDate = L"Date" ;
  35. const static WCHAR* pDescription = L"Description" ;
  36. const static WCHAR* pGroupName = L"GroupName" ;
  37. const static WCHAR* pkey = L"key" ;
  38. const static WCHAR* pSize = L"Size" ;
  39. const static WCHAR* pVersion = L"Version" ;
  40. //-----------------------------------------------------------------------------
  41. // Part of the data from the PCH_CODEC class does not come from the cimv2
  42. // Win32_CODECFile class, but from the registry. The "GroupName" and "Key"
  43. // properties are found at:
  44. //
  45. // HKLM\System\CurrentControlSet\Control\MediaResources\<group>\<key>:driver
  46. //
  47. // Where the "driver" value is equal to the filename of the CODEC. Due to the
  48. // way this part of the registry is constructed, we can't find the <group>
  49. // and <key> given the driver name. We'll need to build a map from driver
  50. // to <group> and <key> - building the map requires traversing the registry.
  51. //
  52. // This class is used as a helper for that lookup. When it's created, it
  53. // scans the registry, processing all of the CODEC entries. It can then
  54. // be queried for the key and group associated with a driver.
  55. //-----------------------------------------------------------------------------
  56. #define MAX_DRIVER_LEN MAX_PATH
  57. #define MAX_KEY_LEN MAX_PATH
  58. #define MAX_GROUP_LEN MAX_PATH
  59. class CCODECInfo
  60. {
  61. public:
  62. CCODECInfo();
  63. ~CCODECInfo();
  64. BOOL QueryCODECInfo(LPCTSTR szDriver, LPCSTR * pszKey, LPCSTR * pszGroup);
  65. private:
  66. struct SCODECNode
  67. {
  68. TCHAR m_szDriver[MAX_DRIVER_LEN];
  69. TCHAR m_szKey[MAX_KEY_LEN];
  70. TCHAR m_szGroup[MAX_GROUP_LEN];
  71. SCODECNode * m_pNext;
  72. };
  73. SCODECNode * m_pCODECList;
  74. };
  75. //-----------------------------------------------------------------------------
  76. // The constructor reads the CODEC info from the registry and builds a linked
  77. // list (unsorted) of entries. The destructor deletes it.
  78. //-----------------------------------------------------------------------------
  79. CCODECInfo::CCODECInfo() : m_pCODECList(NULL)
  80. {
  81. TraceFunctEnter("CCODECInfo::CCODECInfo");
  82. LPCTSTR szCODECKey = _T("System\\CurrentControlSet\\Control\\MediaResources");
  83. LPTSTR szDrvValue = _T("driver");
  84. HKEY hkeyCODEC;
  85. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szCODECKey, 0, KEY_READ, &hkeyCODEC))
  86. ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on CODEC key.");
  87. else
  88. {
  89. // Enumerate each subkey of the CODEC key. Each subkey corresponds to a group.
  90. DWORD dwGroupIndex = 0;
  91. DWORD dwSize = MAX_GROUP_LEN;
  92. FILETIME ft;
  93. TCHAR szGroup[MAX_GROUP_LEN];
  94. TCHAR szKey[MAX_KEY_LEN];
  95. TCHAR szDriver[MAX_DRIVER_LEN];
  96. while (ERROR_SUCCESS == RegEnumKeyEx(hkeyCODEC, dwGroupIndex, szGroup, &dwSize, 0, NULL, NULL, &ft))
  97. {
  98. // Open the group subkey. Then enumerate it's subkeys. These will be the keys.
  99. HKEY hkeyGroup;
  100. if (ERROR_SUCCESS != RegOpenKeyEx(hkeyCODEC, szGroup, 0, KEY_READ, &hkeyGroup))
  101. ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on group key = %s.", szGroup);
  102. else
  103. {
  104. dwSize = MAX_KEY_LEN;
  105. DWORD dwKeyIndex = 0;
  106. while (ERROR_SUCCESS == RegEnumKeyEx(hkeyGroup, dwKeyIndex, szKey, &dwSize, 0, NULL, NULL, &ft))
  107. {
  108. // For each key, attempt to get the value named "driver". This is the
  109. // filename for the driver for this CODEC.
  110. HKEY hkeyKey;
  111. if (ERROR_SUCCESS != RegOpenKeyEx(hkeyGroup, szKey, 0, KEY_READ, &hkeyKey))
  112. ErrorTrace(TRACE_ID, "RegOpenKeyEx failed on key = %s.", szKey);
  113. else
  114. {
  115. // Note - there's no trace here because sometimes there may not be
  116. // a driver value, and this is not an error for us.
  117. dwSize = MAX_DRIVER_LEN * sizeof(TCHAR); // this wants the size in bytes
  118. DWORD dwType = REG_SZ;
  119. if (ERROR_SUCCESS == RegQueryValueEx(hkeyKey, szDrvValue, NULL, &dwType, (LPBYTE) szDriver, &dwSize))
  120. {
  121. if (*szGroup && *szKey && *szDriver)
  122. {
  123. // Here's where we insert a value into the map, using
  124. // the strings szDriver, szKey and szGroup.
  125. SCODECNode * pNew = new SCODECNode;
  126. if (!pNew)
  127. {
  128. ErrorTrace(TRACE_ID, "Out of memory.");
  129. RegCloseKey(hkeyKey);
  130. RegCloseKey(hkeyGroup);
  131. RegCloseKey(hkeyCODEC);
  132. throw CHeap_Exception(CHeap_Exception::E_ALLOCATION_ERROR);
  133. }
  134. _tcscpy(pNew->m_szDriver, szDriver);
  135. _tcscpy(pNew->m_szKey, szKey);
  136. _tcscpy(pNew->m_szGroup, szGroup);
  137. pNew->m_pNext = m_pCODECList;
  138. m_pCODECList = pNew;
  139. }
  140. }
  141. if (ERROR_SUCCESS != RegCloseKey(hkeyKey))
  142. ErrorTrace(TRACE_ID, "RegCloseKey failed on key.");
  143. }
  144. dwSize = MAX_KEY_LEN;
  145. dwKeyIndex += 1;
  146. }
  147. if (ERROR_SUCCESS != RegCloseKey(hkeyGroup))
  148. ErrorTrace(TRACE_ID, "RegCloseKey failed on key.");
  149. }
  150. dwSize = MAX_GROUP_LEN;
  151. dwGroupIndex += 1;
  152. }
  153. if (ERROR_SUCCESS != RegCloseKey(hkeyCODEC))
  154. ErrorTrace(TRACE_ID, "RegCloseKey failed on CODEC key.");
  155. }
  156. TraceFunctLeave();
  157. }
  158. CCODECInfo::~CCODECInfo()
  159. {
  160. TraceFunctEnter("CCODECInfo::~CCODECInfo");
  161. while (m_pCODECList)
  162. {
  163. SCODECNode * pNext = m_pCODECList->m_pNext;
  164. delete m_pCODECList;
  165. m_pCODECList = pNext;
  166. }
  167. TraceFunctLeave();
  168. }
  169. //-----------------------------------------------------------------------------
  170. // Search for the requested driver in the list of CODEC information entries.
  171. // If it's found, set pszKey and pszGroup to point to the key and group strings
  172. // in the entry and return TRUE, otherwise return FALSE. Note: copies of the
  173. // strings are not made, so the caller is not responsible for deallocating
  174. // the strings. Another note: the string pointers won't be valid after the
  175. // CCODECInfo object is destructed.
  176. //-----------------------------------------------------------------------------
  177. BOOL CCODECInfo::QueryCODECInfo(LPCTSTR szDriver, LPCTSTR * pszKey, LPCTSTR * pszGroup)
  178. {
  179. TraceFunctEnter("CCODECInfo::QueryCODECInfo");
  180. _ASSERT(szDriver && pszKey && pszGroup);
  181. SCODECNode * pScan = m_pCODECList;
  182. BOOL fReturn = FALSE;
  183. while (pScan)
  184. {
  185. if (0 == _tcscmp(szDriver, pScan->m_szDriver))
  186. {
  187. *pszKey = pScan->m_szKey;
  188. *pszGroup = pScan->m_szGroup;
  189. fReturn = TRUE;
  190. break;
  191. }
  192. pScan = pScan->m_pNext;
  193. }
  194. TraceFunctLeave();
  195. return fReturn;
  196. }
  197. /*****************************************************************************
  198. *
  199. * FUNCTION : CPCH_Codec::EnumerateInstances
  200. *
  201. * DESCRIPTION : Returns all the instances of this class.
  202. *
  203. * INPUTS : A pointer to the MethodContext for communication with WinMgmt.
  204. * A long that contains the flags described in
  205. * IWbemServices::CreateInstanceEnumAsync. Note that the following
  206. * flags are handled by (and filtered out by) WinMgmt:
  207. * WBEM_FLAG_DEEP
  208. * WBEM_FLAG_SHALLOW
  209. * WBEM_FLAG_RETURN_IMMEDIATELY
  210. * WBEM_FLAG_FORWARD_ONLY
  211. * WBEM_FLAG_BIDIRECTIONAL
  212. *
  213. * RETURNS : WBEM_S_NO_ERROR if successful
  214. *
  215. * COMMENTS : TO DO: All instances on the machine should be returned here.
  216. * If there are no instances, return WBEM_S_NO_ERROR.
  217. * It is not an error to have no instances.
  218. *
  219. *****************************************************************************/
  220. HRESULT CPCH_Codec::EnumerateInstances(MethodContext * pMethodContext, long lFlags)
  221. {
  222. TraceFunctEnter("CPCH_Codec::EnumerateInstances");
  223. USES_CONVERSION;
  224. HRESULT hRes = WBEM_S_NO_ERROR;
  225. REFPTRCOLLECTION_POSITION posList;
  226. CComPtr<IEnumWbemClassObject> pEnumInst;
  227. IWbemClassObjectPtr pObj;
  228. ULONG ulRetVal;
  229. // This instance of CCODECInfo will provide some of the missing information
  230. // about each CODEC. Constructing it queries the registry for CODEC info.
  231. CCODECInfo codecinfo;
  232. // Get the date and time
  233. SYSTEMTIME stUTCTime;
  234. GetSystemTime(&stUTCTime);
  235. // Execute the query
  236. hRes = ExecWQLQuery(&pEnumInst, CComBSTR("SELECT * FROM Win32_CodecFile"));
  237. if (FAILED(hRes))
  238. goto END;
  239. // enumerate the instances from win32_CodecFile
  240. while (WBEM_S_NO_ERROR == pEnumInst->Next(WBEM_INFINITE, 1, &pObj, &ulRetVal))
  241. {
  242. // Create a new instance based on the passed-in MethodContext
  243. CInstancePtr pInstance(CreateNewInstance(pMethodContext), false);
  244. CComVariant varValue;
  245. if (!pInstance->SetDateTime(pTimeStamp, WBEMTime(stUTCTime)))
  246. ErrorTrace(TRACE_ID, "SetDateTime on Timestamp Field failed.");
  247. if (!pInstance->SetCHString(pChange, L"Snapshot"))
  248. ErrorTrace(TRACE_ID, "SetCHString on Change Field failed.");
  249. (void)CopyProperty(pObj, L"group", pInstance, pCategory);
  250. (void)CopyProperty(pObj, L"name", pInstance, pCodecDriver);
  251. (void)CopyProperty(pObj, L"description", pInstance, pDescription);
  252. (void)CopyProperty(pObj, L"filesize", pInstance, pSize);
  253. (void)CopyProperty(pObj, L"version", pInstance, pVersion);
  254. // BUGBUG: WMI does not seem to be populating this field correctly.
  255. // Even though Win32_CODECFile is derived from CIM_DataFile, it doesn't
  256. // seem to be inheriting CreationDate. This is what we'd like to do:
  257. //
  258. // (void)CopyProperty(pObj, "CreationDate", pInstance, pDate);
  259. // Get the data which is missing from the Win32_CODECClass. Use the
  260. // instance of CCODECInfo we declared - we need to pass in just the
  261. // driver name (without the complete path).
  262. CComBSTR bstrDriver("name");
  263. if (FAILED(pObj->Get(bstrDriver, 0, &varValue, NULL, NULL)))
  264. ErrorTrace(TRACE_ID, "GetVariant on pCodecDriver field failed.");
  265. else
  266. {
  267. CComBSTR ccombstrValue(V_BSTR(&varValue));
  268. // Because Win32_CODECFile doesn't seem to be inheriting
  269. // CreationDate, we need to get the actual creation date
  270. // by calling API functions.
  271. LPTSTR szName = W2T(ccombstrValue);
  272. HANDLE hFile = CreateFile(szName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
  273. if (INVALID_HANDLE_VALUE == hFile)
  274. ErrorTrace(TRACE_ID, "Couldn't open codec file to get date.");
  275. else
  276. {
  277. SYSTEMTIME stFileTime;
  278. FILETIME ftFileTime;
  279. if (GetFileTime(hFile, NULL, NULL, &ftFileTime))
  280. if (FileTimeToSystemTime(&ftFileTime, &stFileTime))
  281. if (!pInstance->SetDateTime(pDate, WBEMTime(stFileTime)))
  282. ErrorTrace(TRACE_ID, "SetDateTime on date field failed.");
  283. CloseHandle(hFile);
  284. }
  285. // We need to convert the string from a BSTR to a LPCTSTR,
  286. // and to only include the file part (without the path).
  287. UINT uLen = SysStringLen(ccombstrValue);
  288. // Scan backwards through the string until we've either reached
  289. // the start (shouldn't happen) or a '\'.
  290. UINT iChar = uLen - 1;
  291. while (iChar && ccombstrValue[iChar] != L'\\')
  292. iChar -= 1;
  293. // Then scan to the end of the string, copying the filename.
  294. if (ccombstrValue[iChar] == L'\\')
  295. iChar += 1;
  296. TCHAR szDriver[MAX_DRIVER_LEN + 1] = _T("");
  297. int i = 0;
  298. while (iChar < uLen && i < MAX_DRIVER_LEN)
  299. szDriver[i++] = (TCHAR) ccombstrValue[iChar++];
  300. szDriver[i] = _T('\0');
  301. LPCSTR szKey = NULL;
  302. LPCSTR szGroup = NULL;
  303. if (codecinfo.QueryCODECInfo(szDriver, &szKey, &szGroup))
  304. {
  305. if (!pInstance->SetCHString(pkey, szKey))
  306. ErrorTrace(TRACE_ID, "SetCHString on key field failed.");
  307. if (!pInstance->SetCHString(pGroupName, szGroup))
  308. ErrorTrace(TRACE_ID, "SetCHString on group field failed.");
  309. }
  310. else if (codecinfo.QueryCODECInfo(szName, &szKey, &szGroup))
  311. {
  312. // Sometimes the CODEC is stored in the registry with a complete
  313. // path. If we can't find the CODEC based on just the filename,
  314. // we might find it with the path.
  315. if (!pInstance->SetCHString(pkey, szKey))
  316. ErrorTrace(TRACE_ID, "SetCHString on key field failed.");
  317. if (!pInstance->SetCHString(pGroupName, szGroup))
  318. ErrorTrace(TRACE_ID, "SetCHString on group field failed.");
  319. }
  320. }
  321. hRes = pInstance->Commit();
  322. if (FAILED(hRes))
  323. ErrorTrace(TRACE_ID, "Commit on Instance failed.");
  324. }
  325. END:
  326. TraceFunctLeave();
  327. return hRes;
  328. }