Source code of Windows XP (NT5)
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.

692 lines
17 KiB

  1. //------------------------------------------------------------------------------
  2. // File: DllSetup.cpp
  3. //
  4. // Desc: DirectShow base classes.
  5. //
  6. // Copyright (c) 1992-2001 Microsoft Corporation. All rights reserved.
  7. //------------------------------------------------------------------------------
  8. #include <streams.h>
  9. //---------------------------------------------------------------------------
  10. // defines
  11. #define MAX_KEY_LEN 260
  12. //---------------------------------------------------------------------------
  13. // externally defined functions/variable
  14. extern int g_cTemplates;
  15. extern CFactoryTemplate g_Templates[];
  16. //---------------------------------------------------------------------------
  17. //
  18. // EliminateSubKey
  19. //
  20. // Try to enumerate all keys under this one.
  21. // if we find anything, delete it completely.
  22. // Otherwise just delete it.
  23. //
  24. // note - this was pinched/duplicated from
  25. // Filgraph\Mapper.cpp - so should it be in
  26. // a lib somewhere?
  27. //
  28. //---------------------------------------------------------------------------
  29. STDAPI
  30. EliminateSubKey( HKEY hkey, LPTSTR strSubKey )
  31. {
  32. HKEY hk;
  33. if (0 == lstrlen(strSubKey) ) {
  34. // defensive approach
  35. return E_FAIL;
  36. }
  37. LONG lreturn = RegOpenKeyEx( hkey
  38. , strSubKey
  39. , 0
  40. , MAXIMUM_ALLOWED
  41. , &hk );
  42. ASSERT( lreturn == ERROR_SUCCESS
  43. || lreturn == ERROR_FILE_NOT_FOUND
  44. || lreturn == ERROR_INVALID_HANDLE );
  45. if( ERROR_SUCCESS == lreturn )
  46. {
  47. // Keep on enumerating the first (zero-th)
  48. // key and deleting that
  49. for( ; ; )
  50. {
  51. TCHAR Buffer[MAX_KEY_LEN];
  52. DWORD dw = MAX_KEY_LEN;
  53. FILETIME ft;
  54. lreturn = RegEnumKeyEx( hk
  55. , 0
  56. , Buffer
  57. , &dw
  58. , NULL
  59. , NULL
  60. , NULL
  61. , &ft);
  62. ASSERT( lreturn == ERROR_SUCCESS
  63. || lreturn == ERROR_NO_MORE_ITEMS );
  64. if( ERROR_SUCCESS == lreturn )
  65. {
  66. EliminateSubKey(hk, Buffer);
  67. }
  68. else
  69. {
  70. break;
  71. }
  72. }
  73. RegCloseKey(hk);
  74. RegDeleteKey(hkey, strSubKey);
  75. }
  76. return NOERROR;
  77. }
  78. //---------------------------------------------------------------------------
  79. //
  80. // AMovieSetupRegisterServer()
  81. //
  82. // registers specfied file "szFileName" as server for
  83. // CLSID "clsServer". A description is also required.
  84. // The ThreadingModel and ServerType are optional, as
  85. // they default to InprocServer32 (i.e. dll) and Both.
  86. //
  87. //---------------------------------------------------------------------------
  88. STDAPI
  89. AMovieSetupRegisterServer( CLSID clsServer
  90. , LPCWSTR szDescription
  91. , LPCWSTR szFileName
  92. , LPCWSTR szThreadingModel = L"Both"
  93. , LPCWSTR szServerType = L"InprocServer32" )
  94. {
  95. // temp buffer
  96. //
  97. TCHAR achTemp[MAX_PATH];
  98. // convert CLSID uuid to string and write
  99. // out subkey as string - CLSID\{}
  100. //
  101. OLECHAR szCLSID[CHARS_IN_GUID];
  102. HRESULT hr = StringFromGUID2( clsServer
  103. , szCLSID
  104. , CHARS_IN_GUID );
  105. ASSERT( SUCCEEDED(hr) );
  106. // create key
  107. //
  108. HKEY hkey;
  109. wsprintf( achTemp, TEXT("CLSID\\%ls"), szCLSID );
  110. LONG lreturn = RegCreateKey( HKEY_CLASSES_ROOT
  111. , (LPCTSTR)achTemp
  112. , &hkey );
  113. if( ERROR_SUCCESS != lreturn )
  114. {
  115. return AmHresultFromWin32(lreturn);
  116. }
  117. // set description string
  118. //
  119. wsprintf( achTemp, TEXT("%ls"), szDescription );
  120. lreturn = RegSetValue( hkey
  121. , (LPCTSTR)NULL
  122. , REG_SZ
  123. , achTemp
  124. , sizeof(achTemp) );
  125. if( ERROR_SUCCESS != lreturn )
  126. {
  127. RegCloseKey( hkey );
  128. return AmHresultFromWin32(lreturn);
  129. }
  130. // create CLSID\\{"CLSID"}\\"ServerType" key,
  131. // using key to CLSID\\{"CLSID"} passed back by
  132. // last call to RegCreateKey().
  133. //
  134. HKEY hsubkey;
  135. wsprintf( achTemp, TEXT("%ls"), szServerType );
  136. lreturn = RegCreateKey( hkey
  137. , achTemp
  138. , &hsubkey );
  139. if( ERROR_SUCCESS != lreturn )
  140. {
  141. RegCloseKey( hkey );
  142. return AmHresultFromWin32(lreturn);
  143. }
  144. // set Server string
  145. //
  146. wsprintf( achTemp, TEXT("%ls"), szFileName );
  147. lreturn = RegSetValue( hsubkey
  148. , (LPCTSTR)NULL
  149. , REG_SZ
  150. , (LPCTSTR)achTemp
  151. , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
  152. if( ERROR_SUCCESS != lreturn )
  153. {
  154. RegCloseKey( hkey );
  155. RegCloseKey( hsubkey );
  156. return AmHresultFromWin32(lreturn);
  157. }
  158. wsprintf( achTemp, TEXT("%ls"), szThreadingModel );
  159. lreturn = RegSetValueEx( hsubkey
  160. , TEXT("ThreadingModel")
  161. , 0L
  162. , REG_SZ
  163. , (CONST BYTE *)achTemp
  164. , sizeof(TCHAR) * (lstrlen(achTemp)+1) );
  165. // close hkeys
  166. //
  167. RegCloseKey( hkey );
  168. RegCloseKey( hsubkey );
  169. // and return
  170. //
  171. return HRESULT_FROM_WIN32(lreturn);
  172. }
  173. //---------------------------------------------------------------------------
  174. //
  175. // AMovieSetupUnregisterServer()
  176. //
  177. // default ActiveMovie dll setup function
  178. // - to use must be called from an exported
  179. // function named DllRegisterServer()
  180. //
  181. //---------------------------------------------------------------------------
  182. STDAPI
  183. AMovieSetupUnregisterServer( CLSID clsServer )
  184. {
  185. // convert CLSID uuid to string and write
  186. // out subkey CLSID\{}
  187. //
  188. OLECHAR szCLSID[CHARS_IN_GUID];
  189. HRESULT hr = StringFromGUID2( clsServer
  190. , szCLSID
  191. , CHARS_IN_GUID );
  192. ASSERT( SUCCEEDED(hr) );
  193. TCHAR achBuffer[MAX_KEY_LEN];
  194. wsprintf( achBuffer, TEXT("CLSID\\%ls"), szCLSID );
  195. // delete subkey
  196. //
  197. hr = EliminateSubKey( HKEY_CLASSES_ROOT, achBuffer );
  198. ASSERT( SUCCEEDED(hr) );
  199. // return
  200. //
  201. return NOERROR;
  202. }
  203. //---------------------------------------------------------------------------
  204. //
  205. // AMovieSetupRegisterFilter through IFilterMapper2
  206. //
  207. //---------------------------------------------------------------------------
  208. STDAPI
  209. AMovieSetupRegisterFilter2( const AMOVIESETUP_FILTER * const psetupdata
  210. , IFilterMapper2 * pIFM2
  211. , BOOL bRegister )
  212. {
  213. DbgLog((LOG_TRACE, 3, TEXT("= AMovieSetupRegisterFilter")));
  214. // check we've got data
  215. //
  216. if( NULL == psetupdata ) return S_FALSE;
  217. // unregister filter
  218. // (as pins are subkeys of filter's CLSID key
  219. // they do not need to be removed separately).
  220. //
  221. DbgLog((LOG_TRACE, 3, TEXT("= = unregister filter")));
  222. HRESULT hr = pIFM2->UnregisterFilter(
  223. 0, // default category
  224. 0, // default instance name
  225. *psetupdata->clsID );
  226. if( bRegister )
  227. {
  228. REGFILTER2 rf2;
  229. rf2.dwVersion = 1;
  230. rf2.dwMerit = psetupdata->dwMerit;
  231. rf2.cPins = psetupdata->nPins;
  232. rf2.rgPins = psetupdata->lpPin;
  233. // register filter
  234. //
  235. DbgLog((LOG_TRACE, 3, TEXT("= = register filter")));
  236. hr = pIFM2->RegisterFilter(*psetupdata->clsID
  237. , psetupdata->strName
  238. , 0 // moniker
  239. , 0 // category
  240. , NULL // instance
  241. , &rf2);
  242. }
  243. // handle one acceptable "error" - that
  244. // of filter not being registered!
  245. // (couldn't find a suitable #define'd
  246. // name for the error!)
  247. //
  248. if( 0x80070002 == hr)
  249. return NOERROR;
  250. else
  251. return hr;
  252. }
  253. //---------------------------------------------------------------------------
  254. //
  255. // RegisterAllServers()
  256. //
  257. //---------------------------------------------------------------------------
  258. STDAPI
  259. RegisterAllServers( LPCWSTR szFileName, BOOL bRegister )
  260. {
  261. HRESULT hr = NOERROR;
  262. for( int i = 0; i < g_cTemplates; i++ )
  263. {
  264. // get i'th template
  265. //
  266. const CFactoryTemplate *pT = &g_Templates[i];
  267. DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"),
  268. (LPCWSTR)pT->m_Name ));
  269. // register CLSID and InprocServer32
  270. //
  271. if( bRegister )
  272. {
  273. hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
  274. , (LPCWSTR)pT->m_Name
  275. , szFileName );
  276. }
  277. else
  278. {
  279. hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
  280. }
  281. // check final error for this pass
  282. // and break loop if we failed
  283. //
  284. if( FAILED(hr) )
  285. break;
  286. }
  287. return hr;
  288. }
  289. //---------------------------------------------------------------------------
  290. //
  291. // AMovieDllRegisterServer2()
  292. //
  293. // default ActiveMovie dll setup function
  294. // - to use must be called from an exported
  295. // function named DllRegisterServer()
  296. //
  297. // this function is table driven using the
  298. // static members of the CFactoryTemplate
  299. // class defined in the dll.
  300. //
  301. // it registers the Dll as the InprocServer32
  302. // and then calls the IAMovieSetup.Register
  303. // method.
  304. //
  305. //---------------------------------------------------------------------------
  306. STDAPI
  307. AMovieDllRegisterServer2( BOOL bRegister )
  308. {
  309. HRESULT hr = NOERROR;
  310. DbgLog((LOG_TRACE, 2, TEXT("AMovieDllRegisterServer2()")));
  311. // get file name (where g_hInst is the
  312. // instance handle of the filter dll)
  313. //
  314. WCHAR achFileName[MAX_PATH];
  315. // WIN95 doesn't support GetModuleFileNameW
  316. //
  317. {
  318. char achTemp[MAX_PATH];
  319. DbgLog((LOG_TRACE, 2, TEXT("- get module file name")));
  320. // g_hInst handle is set in our dll entry point. Make sure
  321. // DllEntryPoint in dllentry.cpp is called
  322. ASSERT(g_hInst != 0);
  323. if( 0 == GetModuleFileNameA( g_hInst
  324. , achTemp
  325. , sizeof(achTemp) ) )
  326. {
  327. // we've failed!
  328. DWORD dwerr = GetLastError();
  329. return AmHresultFromWin32(dwerr);
  330. }
  331. MultiByteToWideChar( CP_ACP
  332. , 0L
  333. , achTemp
  334. , lstrlenA(achTemp) + 1
  335. , achFileName
  336. , sizeof(achFileName) );
  337. }
  338. //
  339. // first registering, register all OLE servers
  340. //
  341. if( bRegister )
  342. {
  343. DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
  344. hr = RegisterAllServers( achFileName, TRUE );
  345. }
  346. //
  347. // next, register/unregister all filters
  348. //
  349. if( SUCCEEDED(hr) )
  350. {
  351. // init is ref counted so call just in case
  352. // we're being called cold.
  353. //
  354. DbgLog((LOG_TRACE, 2, TEXT("- CoInitialize")));
  355. hr = CoInitialize( (LPVOID)NULL );
  356. ASSERT( SUCCEEDED(hr) );
  357. // get hold of IFilterMapper2
  358. //
  359. DbgLog((LOG_TRACE, 2, TEXT("- obtain IFilterMapper2")));
  360. IFilterMapper2 *pIFM2 = 0;
  361. IFilterMapper *pIFM = 0;
  362. hr = CoCreateInstance( CLSID_FilterMapper2
  363. , NULL
  364. , CLSCTX_INPROC_SERVER
  365. , IID_IFilterMapper2
  366. , (void **)&pIFM2 );
  367. if(FAILED(hr))
  368. {
  369. DbgLog((LOG_TRACE, 2, TEXT("- trying IFilterMapper instead")));
  370. hr = CoCreateInstance(
  371. CLSID_FilterMapper,
  372. NULL,
  373. CLSCTX_INPROC_SERVER,
  374. IID_IFilterMapper,
  375. (void **)&pIFM);
  376. }
  377. if( SUCCEEDED(hr) )
  378. {
  379. // scan through array of CFactoryTemplates
  380. // registering servers and filters.
  381. //
  382. DbgLog((LOG_TRACE, 2, TEXT("- register Filters")));
  383. for( int i = 0; i < g_cTemplates; i++ )
  384. {
  385. // get i'th template
  386. //
  387. const CFactoryTemplate *pT = &g_Templates[i];
  388. if( NULL != pT->m_pAMovieSetup_Filter )
  389. {
  390. DbgLog((LOG_TRACE, 2, TEXT("- - register %ls"), (LPCWSTR)pT->m_Name ));
  391. if(pIFM2)
  392. {
  393. hr = AMovieSetupRegisterFilter2( pT->m_pAMovieSetup_Filter, pIFM2, bRegister );
  394. }
  395. else
  396. {
  397. hr = AMovieSetupRegisterFilter( pT->m_pAMovieSetup_Filter, pIFM, bRegister );
  398. }
  399. }
  400. // check final error for this pass
  401. // and break loop if we failed
  402. //
  403. if( FAILED(hr) )
  404. break;
  405. }
  406. // release interface
  407. //
  408. if(pIFM2)
  409. pIFM2->Release();
  410. else
  411. pIFM->Release();
  412. }
  413. // and clear up
  414. //
  415. CoFreeUnusedLibraries();
  416. CoUninitialize();
  417. }
  418. //
  419. // if unregistering, unregister all OLE servers
  420. //
  421. if( SUCCEEDED(hr) && !bRegister )
  422. {
  423. DbgLog((LOG_TRACE, 2, TEXT("- register OLE Servers")));
  424. hr = RegisterAllServers( achFileName, FALSE );
  425. }
  426. DbgLog((LOG_TRACE, 2, TEXT("- return %0x"), hr));
  427. return hr;
  428. }
  429. //---------------------------------------------------------------------------
  430. //
  431. // AMovieDllRegisterServer()
  432. //
  433. // default ActiveMovie dll setup function
  434. // - to use must be called from an exported
  435. // function named DllRegisterServer()
  436. //
  437. // this function is table driven using the
  438. // static members of the CFactoryTemplate
  439. // class defined in the dll.
  440. //
  441. // it registers the Dll as the InprocServer32
  442. // and then calls the IAMovieSetup.Register
  443. // method.
  444. //
  445. //---------------------------------------------------------------------------
  446. STDAPI
  447. AMovieDllRegisterServer( void )
  448. {
  449. HRESULT hr = NOERROR;
  450. // get file name (where g_hInst is the
  451. // instance handle of the filter dll)
  452. //
  453. WCHAR achFileName[MAX_PATH];
  454. {
  455. // WIN95 doesn't support GetModuleFileNameW
  456. //
  457. char achTemp[MAX_PATH];
  458. if( 0 == GetModuleFileNameA( g_hInst
  459. , achTemp
  460. , sizeof(achTemp) ) )
  461. {
  462. // we've failed!
  463. DWORD dwerr = GetLastError();
  464. return AmHresultFromWin32(dwerr);
  465. }
  466. MultiByteToWideChar( CP_ACP
  467. , 0L
  468. , achTemp
  469. , lstrlenA(achTemp) + 1
  470. , achFileName
  471. , sizeof(achFileName) );
  472. }
  473. // scan through array of CFactoryTemplates
  474. // registering servers and filters.
  475. //
  476. for( int i = 0; i < g_cTemplates; i++ )
  477. {
  478. // get i'th template
  479. //
  480. const CFactoryTemplate *pT = &g_Templates[i];
  481. // register CLSID and InprocServer32
  482. //
  483. hr = AMovieSetupRegisterServer( *(pT->m_ClsID)
  484. , (LPCWSTR)pT->m_Name
  485. , achFileName );
  486. // instantiate all servers and get hold of
  487. // IAMovieSetup, if implemented, and call
  488. // IAMovieSetup.Register() method
  489. //
  490. if( SUCCEEDED(hr) && (NULL != pT->m_lpfnNew) )
  491. {
  492. // instantiate object
  493. //
  494. PAMOVIESETUP psetup;
  495. hr = CoCreateInstance( *(pT->m_ClsID)
  496. , 0
  497. , CLSCTX_INPROC_SERVER
  498. , IID_IAMovieSetup
  499. , reinterpret_cast<void**>(&psetup) );
  500. if( SUCCEEDED(hr) )
  501. {
  502. hr = psetup->Unregister();
  503. if( SUCCEEDED(hr) )
  504. hr = psetup->Register();
  505. psetup->Release();
  506. }
  507. else
  508. {
  509. if( (E_NOINTERFACE == hr )
  510. || (VFW_E_NEED_OWNER == hr ) )
  511. hr = NOERROR;
  512. }
  513. }
  514. // check final error for this pass
  515. // and break loop if we failed
  516. //
  517. if( FAILED(hr) )
  518. break;
  519. } // end-for
  520. return hr;
  521. }
  522. //---------------------------------------------------------------------------
  523. //
  524. // AMovieDllUnregisterServer()
  525. //
  526. // default ActiveMovie dll uninstall function
  527. // - to use must be called from an exported
  528. // function named DllRegisterServer()
  529. //
  530. // this function is table driven using the
  531. // static members of the CFactoryTemplate
  532. // class defined in the dll.
  533. //
  534. // it calls the IAMovieSetup.Unregister
  535. // method and then unregisters the Dll
  536. // as the InprocServer32
  537. //
  538. //---------------------------------------------------------------------------
  539. STDAPI
  540. AMovieDllUnregisterServer()
  541. {
  542. // initialize return code
  543. //
  544. HRESULT hr = NOERROR;
  545. // scan through CFactory template and unregister
  546. // all OLE servers and filters.
  547. //
  548. for( int i = g_cTemplates; i--; )
  549. {
  550. // get i'th template
  551. //
  552. const CFactoryTemplate *pT = &g_Templates[i];
  553. // check method exists
  554. //
  555. if( NULL != pT->m_lpfnNew )
  556. {
  557. // instantiate object
  558. //
  559. PAMOVIESETUP psetup;
  560. hr = CoCreateInstance( *(pT->m_ClsID)
  561. , 0
  562. , CLSCTX_INPROC_SERVER
  563. , IID_IAMovieSetup
  564. , reinterpret_cast<void**>(&psetup) );
  565. if( SUCCEEDED(hr) )
  566. {
  567. hr = psetup->Unregister();
  568. psetup->Release();
  569. }
  570. else
  571. {
  572. if( (E_NOINTERFACE == hr )
  573. || (VFW_E_NEED_OWNER == hr ) )
  574. hr = NOERROR;
  575. }
  576. }
  577. // unregister CLSID and InprocServer32
  578. //
  579. if( SUCCEEDED(hr) )
  580. {
  581. hr = AMovieSetupUnregisterServer( *(pT->m_ClsID) );
  582. }
  583. // check final error for this pass
  584. // and break loop if we failed
  585. //
  586. if( FAILED(hr) )
  587. break;
  588. }
  589. return hr;
  590. }