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.

514 lines
12 KiB

  1. #include <objbase.h>
  2. #include <mbctype.h>
  3. #include "infgen.h"
  4. HINSTANCE g_hMyInstance;
  5. long g_cKeepAlive;
  6. LONG
  7. IncrementKeepAlive(
  8. void
  9. )
  10. {
  11. return InterlockedIncrement( &g_cKeepAlive );
  12. }
  13. LONG
  14. DecrementKeepAlive(
  15. void
  16. )
  17. {
  18. return InterlockedDecrement( &g_cKeepAlive );
  19. }
  20. class CInfGeneratorFactory : public IClassFactory
  21. {
  22. public:
  23. // IUnknown
  24. ULONG __stdcall AddRef( void );
  25. ULONG __stdcall Release( void );
  26. HRESULT __stdcall QueryInterface( REFIID riid, void **ppv );
  27. // IClassFactory
  28. HRESULT __stdcall CreateInstance( IUnknown *pUnkOuter, REFIID riid, void **ppv );
  29. HRESULT __stdcall LockServer( BOOL bLock );
  30. CInfGeneratorFactory(): m_cRef(1) {}
  31. ~CInfGeneratorFactory() {}
  32. private:
  33. long m_cRef;
  34. long m_cLocks;
  35. };
  36. ULONG
  37. CInfGeneratorFactory::AddRef(
  38. void
  39. )
  40. {
  41. IncrementKeepAlive();
  42. return InterlockedIncrement(&m_cRef);
  43. }
  44. ULONG
  45. CInfGeneratorFactory::Release(
  46. void
  47. )
  48. {
  49. if ( 0L == InterlockedDecrement(&m_cRef) )
  50. {
  51. delete this;
  52. DecrementKeepAlive();
  53. return 0L;
  54. }
  55. DecrementKeepAlive();
  56. return m_cRef;
  57. }
  58. HRESULT
  59. CInfGeneratorFactory::QueryInterface(
  60. REFIID riid,
  61. void **ppv
  62. )
  63. {
  64. *ppv = NULL;
  65. if ( IID_IUnknown == riid ||
  66. IID_IClassFactory == riid )
  67. {
  68. *ppv = (IClassFactory *)this;
  69. }
  70. else
  71. {
  72. return E_NOINTERFACE;
  73. }
  74. AddRef();
  75. return S_OK;
  76. }
  77. HRESULT
  78. CInfGeneratorFactory::CreateInstance(
  79. IUnknown *pUnkOuter,
  80. REFIID riid,
  81. void **ppv
  82. )
  83. {
  84. *ppv = NULL;
  85. if ( NULL != pUnkOuter )
  86. {
  87. return CLASS_E_NOAGGREGATION;
  88. }
  89. CUpdateInf *pUpdateInf = new CUpdateInf;
  90. if ( NULL == pUpdateInf )
  91. return E_OUTOFMEMORY;
  92. if ( !pUpdateInf->Init() )
  93. {
  94. delete pUpdateInf;
  95. return E_FAIL;
  96. }
  97. HRESULT hr = pUpdateInf->QueryInterface( riid, ppv );
  98. if ( S_OK != hr )
  99. delete pUpdateInf;
  100. else
  101. pUpdateInf->Release();
  102. return hr;
  103. }
  104. HRESULT
  105. CInfGeneratorFactory::LockServer(
  106. BOOL bLock
  107. )
  108. {
  109. if ( bLock )
  110. {
  111. IncrementKeepAlive();
  112. InterlockedIncrement( &m_cLocks );
  113. }
  114. else if ( 0 != m_cLocks )
  115. {
  116. InterlockedDecrement( &m_cLocks );
  117. DecrementKeepAlive();
  118. }
  119. else
  120. return E_FAIL;
  121. return S_OK;
  122. }
  123. inline long
  124. AssignKeyValue(
  125. HKEY hParentKey,
  126. LPTSTR szKeyName,
  127. LPTSTR szValue,
  128. LPTSTR szData,
  129. HKEY *phNewKey
  130. )
  131. {
  132. LONG lResult;
  133. DWORD dwDisposition;
  134. HKEY hKey;
  135. if ( NULL != szKeyName )
  136. {
  137. lResult = RegCreateKeyEx( hParentKey,
  138. szKeyName,
  139. (0),
  140. (0),
  141. REG_OPTION_NON_VOLATILE,
  142. KEY_ALL_ACCESS,
  143. NULL,
  144. &hKey,
  145. &dwDisposition );
  146. if ( ERROR_SUCCESS != lResult ) goto failure;
  147. }
  148. else
  149. {
  150. hKey = hParentKey;
  151. }
  152. lResult = RegSetValueEx( hKey,
  153. szValue,
  154. (0),
  155. REG_SZ,
  156. (PBYTE)szData,
  157. sizeof( TCHAR ) * _tcslen( szData ) );
  158. if ( ERROR_SUCCESS != lResult ) goto failure;
  159. if ( NULL != phNewKey )
  160. {
  161. *phNewKey = hKey;
  162. }
  163. else
  164. {
  165. RegCloseKey( hKey );
  166. hKey = NULL;
  167. }
  168. return ERROR_SUCCESS;
  169. failure:
  170. if ( NULL != hKey )
  171. RegCloseKey( hKey );
  172. return lResult;
  173. }
  174. HRESULT
  175. DllRegisterServer(
  176. void
  177. )
  178. {
  179. LONG lResult;
  180. DWORD dwDisposition;
  181. TCHAR szMe[_MAX_PATH];
  182. HKEY hKeyParent = NULL,
  183. hKey = NULL;
  184. ITypeLib *pTypeLib;
  185. HRESULT hr;
  186. // Open the CLSID key
  187. lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT,
  188. _T("CLSID"),
  189. (0),
  190. (0),
  191. REG_OPTION_NON_VOLATILE,
  192. KEY_ALL_ACCESS,
  193. NULL,
  194. &hKeyParent,
  195. &dwDisposition );
  196. if ( ERROR_SUCCESS != lResult ) goto failure;
  197. // Store our class ID
  198. lResult = AssignKeyValue( hKeyParent,
  199. _T("{9cd916b9-2004-42b1-b639-572fbf647204}"),
  200. NULL,
  201. _T("Update INF Generator"),
  202. &hKey );
  203. // Done with CLSID key
  204. RegCloseKey( hKeyParent );
  205. hKeyParent = NULL;
  206. if ( ERROR_SUCCESS != lResult ) goto failure;
  207. // Find out my full path
  208. if ( !GetModuleFileName( g_hMyInstance, szMe, _MAX_PATH ) ) goto failure;
  209. // Store our location
  210. hKeyParent = hKey;
  211. lResult = AssignKeyValue( hKeyParent,
  212. _T("InprocServer32"),
  213. NULL,
  214. szMe,
  215. &hKey );
  216. if ( ERROR_SUCCESS != lResult ) goto failure;
  217. // Store our threading model
  218. lResult = AssignKeyValue( hKey,
  219. _T("ThreadingModel"),
  220. NULL,
  221. _T("Apartment"),
  222. NULL );
  223. if ( ERROR_SUCCESS != lResult ) goto failure;
  224. RegCloseKey( hKey );
  225. hKey = NULL;
  226. // Store our type-lib info
  227. #ifndef UNICODE
  228. size_t lenMe = strlen(szMe) + 1;
  229. wchar_t *wszMe = new wchar_t[lenMe];
  230. if ( NULL == wszMe )
  231. {
  232. return false;
  233. }
  234. if ( 0 == MultiByteToWideChar( _getmbcp(),
  235. 0L,
  236. szMe,
  237. lenMe,
  238. wszMe,
  239. lenMe ) )
  240. {
  241. return false;
  242. }
  243. hr = LoadTypeLibEx( wszMe, REGKIND_REGISTER, &pTypeLib );
  244. delete [] wszMe;
  245. #else
  246. hr = LoadTypeLibEx( szMe, REGKIND_REGISTER, &pTypeLib );
  247. #endif
  248. if ( FAILED(hr) )
  249. {
  250. lResult = hr;
  251. goto failure;
  252. }
  253. pTypeLib->Release();
  254. // Now store pointer to the type-lib info
  255. lResult = AssignKeyValue( hKeyParent,
  256. _T("TypeLib"),
  257. NULL,
  258. _T("{7c1b689f-3b9f-4c65-aa65-9951a5048e47}"),
  259. NULL );
  260. if ( ERROR_SUCCESS != lResult ) goto failure;
  261. // Store our ProgID value
  262. lResult = AssignKeyValue( hKeyParent,
  263. _T("ProgID"),
  264. NULL,
  265. _T("InfGenerator"),
  266. NULL );
  267. if ( ERROR_SUCCESS != lResult ) goto failure;
  268. // Done with CLSID\{value} key
  269. RegCloseKey( hKeyParent );
  270. hKey = NULL;
  271. // *
  272. // Store our ProgID entry and associated values
  273. // *
  274. lResult = AssignKeyValue( HKEY_CLASSES_ROOT,
  275. _T("InfGenerator"),
  276. NULL,
  277. _T("Update INF Generator"),
  278. &hKey );
  279. if ( ERROR_SUCCESS != lResult ) goto failure;
  280. lResult = AssignKeyValue( hKey,
  281. _T("CLSID"),
  282. NULL,
  283. _T("{9cd916b9-2004-42b1-b639-572fbf647204}"),
  284. NULL );
  285. if ( ERROR_SUCCESS != lResult ) goto failure;
  286. lResult = AssignKeyValue( hKey,
  287. _T("CurVer"),
  288. NULL,
  289. _T("InfGenerator.1"),
  290. NULL );
  291. if ( ERROR_SUCCESS != lResult ) goto failure;
  292. // Done with <ProgID> key
  293. RegCloseKey( hKey );
  294. hKey = NULL;
  295. lResult = AssignKeyValue( HKEY_CLASSES_ROOT,
  296. _T("InfGenerator.1"),
  297. NULL,
  298. _T("Update INF Generator"),
  299. &hKey );
  300. if ( ERROR_SUCCESS != lResult ) goto failure;
  301. lResult = AssignKeyValue( hKey,
  302. _T("CLSID"),
  303. NULL,
  304. _T("{9cd916b9-2004-42b1-b639-572fbf647204}"),
  305. NULL );
  306. if ( ERROR_SUCCESS != lResult ) goto failure;
  307. // Done with version-specific <ProgID> key
  308. RegCloseKey( hKey );
  309. hKey = NULL;
  310. return S_OK;
  311. failure:
  312. if ( hKeyParent ) RegCloseKey( hKeyParent );
  313. if ( hKey ) RegCloseKey( hKey );
  314. // Undo anything we might have done
  315. DllUnregisterServer();
  316. return lResult;
  317. }
  318. long
  319. DeleteKeyTree(
  320. HKEY hKeyParent,
  321. LPTSTR szKeyName
  322. )
  323. {
  324. FILETIME ftLastWrite;
  325. DWORD i = 0,
  326. dwSizeOfKey = _MAX_PATH;
  327. TCHAR szSubkey[_MAX_PATH];
  328. LONG lResult,
  329. lFirstFailure = ERROR_SUCCESS;
  330. HKEY hKey;
  331. lResult = RegOpenKeyEx( hKeyParent,
  332. szKeyName,
  333. (0),
  334. KEY_ALL_ACCESS,
  335. &hKey );
  336. if ( ERROR_SUCCESS != lResult )
  337. {
  338. lFirstFailure = lResult;
  339. goto failure;
  340. }
  341. while ( ERROR_SUCCESS == (lResult = RegEnumKeyEx( hKey,
  342. i++,
  343. szSubkey,
  344. &dwSizeOfKey,
  345. (0),
  346. NULL,
  347. (0),
  348. &ftLastWrite )) )
  349. {
  350. lResult = DeleteKeyTree( hKey, szSubkey );
  351. if ( ERROR_SUCCESS != lResult &&
  352. ERROR_SUCCESS != lFirstFailure )
  353. {
  354. lFirstFailure = lResult;
  355. }
  356. dwSizeOfKey = _MAX_PATH;
  357. }
  358. if ( ERROR_NO_MORE_ITEMS != lResult &&
  359. ERROR_SUCCESS != lFirstFailure )
  360. {
  361. lFirstFailure = lResult;
  362. }
  363. RegCloseKey( hKey );
  364. failure: // Attempt to delete key regardless of previous failures
  365. lResult = RegDeleteKey( hKeyParent, szKeyName );
  366. if ( ERROR_SUCCESS != lResult &&
  367. ERROR_SUCCESS != lFirstFailure )
  368. {
  369. lFirstFailure = lResult;
  370. }
  371. // Check for successful completion
  372. return lFirstFailure;
  373. }
  374. HRESULT __stdcall
  375. DllCanUnloadNow(
  376. void
  377. )
  378. {
  379. if ( 0L == InterlockedCompareExchange( &g_cKeepAlive, 0L, 0L ) )
  380. return S_OK;
  381. else
  382. return S_FALSE;
  383. }
  384. HRESULT __stdcall
  385. DllGetClassObject(
  386. REFCLSID clsid,
  387. REFIID riid,
  388. void **ppv
  389. )
  390. {
  391. *ppv = NULL;
  392. if ( CLSID_InfGenerator != clsid )
  393. return CLASS_E_CLASSNOTAVAILABLE;
  394. CInfGeneratorFactory *pInfGeneratorFactory = new CInfGeneratorFactory;
  395. if ( NULL == pInfGeneratorFactory )
  396. return E_OUTOFMEMORY;
  397. HRESULT hr = pInfGeneratorFactory->QueryInterface( riid, ppv );
  398. pInfGeneratorFactory->Release();
  399. return hr;
  400. }
  401. HRESULT
  402. DllUnregisterServer(
  403. void
  404. )
  405. {
  406. long lResult;
  407. HKEY hKey;
  408. // Remove type-lib info
  409. UnRegisterTypeLib( LIBID_InfGeneratorLib, (1), (0), LANG_NEUTRAL, SYS_WIN32 );
  410. lResult = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  411. _T("CLSID"),
  412. (0),
  413. KEY_ALL_ACCESS,
  414. &hKey );
  415. if ( ERROR_SUCCESS == lResult )
  416. {
  417. // Get rid of our CLSID entry
  418. lResult = DeleteKeyTree( hKey, _T("{6324c2cf-aad4-4477-8388-4fdba25188d4}") );
  419. RegCloseKey( hKey );
  420. }
  421. // Get rid of our PROGID entry
  422. lResult = DeleteKeyTree( HKEY_CLASSES_ROOT, _T("InfGenerator") );
  423. if ( ERROR_SUCCESS != lResult )
  424. {
  425. return E_FAIL;
  426. }
  427. // And our versioned PROGID entry
  428. lResult = DeleteKeyTree( HKEY_CLASSES_ROOT, _T("InfGenerator.1") );
  429. if ( ERROR_SUCCESS != lResult )
  430. {
  431. return E_FAIL;
  432. }
  433. return S_OK;
  434. }
  435. BOOL WINAPI
  436. DllMain(
  437. HINSTANCE hInstance,
  438. DWORD dwReasonFlag,
  439. PVOID pvReserved
  440. )
  441. {
  442. // Remember instance handle
  443. g_hMyInstance = hInstance;
  444. return TRUE;
  445. }