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.

668 lines
15 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. fusion.c
  5. Abstract:
  6. Wrappers and functions for fusionizing SetupAPI
  7. without effecting 3rd party DLL's
  8. and without dll-load overhead
  9. Author:
  10. Jamie Hunter (JamieHun) 12/4/2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. #ifdef FUSIONAWARE
  16. #undef CreateWindow
  17. #undef CreateWindowEx
  18. #undef CreateDialogParam
  19. #undef CreateDialogIndirectParam
  20. #undef DialogBoxParam
  21. #undef DialogBoxIndirectParam
  22. #undef MessageBox
  23. #undef CreatePropertySheetPage
  24. #undef DestroyPropertySheetPage
  25. #undef PropertySheet
  26. #undef ImageList_Create
  27. #undef ImageList_Destroy
  28. #undef ImageList_GetImageCount
  29. #undef ImageList_SetImageCount
  30. #undef ImageList_Add
  31. #undef ImageList_ReplaceIcon
  32. #undef ImageList_SetBkColor
  33. #undef ImageList_GetBkColor
  34. #undef ImageList_SetOverlayImage
  35. #include <shfusion.h>
  36. static CRITICAL_SECTION spFusionInitCritSec;
  37. static BOOL spInitFusionCritSec = FALSE;
  38. static BOOL spFusionDoneInit = FALSE;
  39. BOOL spFusionInitialize()
  40. /*++
  41. Routine Description:
  42. Called on DllLoad
  43. do minimum possible
  44. Arguments:
  45. none
  46. Return Value:
  47. TRUE successful initialization
  48. --*/
  49. {
  50. try {
  51. InitializeCriticalSection(&spFusionInitCritSec);
  52. spInitFusionCritSec = TRUE;
  53. } except (EXCEPTION_EXECUTE_HANDLER) {
  54. //
  55. // spInitFusionCritSec remains FALSE
  56. //
  57. }
  58. return spInitFusionCritSec;
  59. }
  60. VOID
  61. spFusionInitLong()
  62. /*++
  63. Routine Description:
  64. Called by internal stub to do real initialization
  65. Arguments:
  66. none
  67. Return Value:
  68. none
  69. --*/
  70. {
  71. BOOL locked = FALSE;
  72. BOOL success = FALSE;
  73. INITCOMMONCONTROLSEX CommCtrl;
  74. if(!spInitFusionCritSec) {
  75. //
  76. // critical section not initialized
  77. // probably out of memory
  78. // bail
  79. //
  80. MYASSERT(spInitFusionCritSec);
  81. spFusionDoneInit = TRUE;
  82. return;
  83. }
  84. try {
  85. EnterCriticalSection(&spFusionInitCritSec);
  86. locked = TRUE;
  87. } except(EXCEPTION_EXECUTE_HANDLER) {
  88. }
  89. if(!locked) {
  90. //
  91. // wasn't able to grab lock - probably out of memory
  92. // bail
  93. //
  94. spFusionDoneInit = TRUE;
  95. return;
  96. }
  97. if(spFusionDoneInit) {
  98. //
  99. // by the time we grabbed critical section
  100. // initialization was done
  101. // bail
  102. //
  103. LeaveCriticalSection(&spFusionInitCritSec);
  104. return;
  105. }
  106. //
  107. // call shell's fusion enabler
  108. //
  109. success = SHFusionInitializeFromModuleID(MyDllModuleHandle,IDR_MANIFEST);
  110. MYASSERT(success);
  111. ZeroMemory(&CommCtrl,sizeof(CommCtrl));
  112. CommCtrl.dwSize = sizeof(CommCtrl);
  113. CommCtrl.dwICC = ICC_WIN95_CLASSES | ICC_LINK_CLASS;
  114. success = InitCommonControlsEx(&CommCtrl);
  115. MYASSERT(success);
  116. //
  117. // at this point, it's now safe for anyone else to assume initialization is done
  118. // even if we haven't released critical section
  119. //
  120. spFusionDoneInit = TRUE;
  121. LeaveCriticalSection(&spFusionInitCritSec);
  122. }
  123. __inline
  124. VOID
  125. spFusionCheckInit()
  126. /*++
  127. Routine Description:
  128. Calls spFusionInitLong iff needed
  129. Arguments:
  130. none
  131. Return Value:
  132. none
  133. --*/
  134. {
  135. if(!spFusionDoneInit) {
  136. //
  137. // either not initialized, or currently going through initialization
  138. //
  139. spFusionInitLong();
  140. }
  141. }
  142. BOOL spFusionUninitialize(BOOL Full)
  143. /*++
  144. Routine Description:
  145. Called at DLL exit (if DLL being unloaded but not process Exit)
  146. Arguments:
  147. none
  148. Return Value:
  149. TRUE successful cleanup
  150. --*/
  151. {
  152. //
  153. // cleanup anything initialized at spFusionInitialize
  154. //
  155. if(spInitFusionCritSec) {
  156. DeleteCriticalSection(&spFusionInitCritSec);
  157. spInitFusionCritSec = FALSE;
  158. }
  159. if(Full && spFusionDoneInit) {
  160. SHFusionUninitialize();
  161. }
  162. return TRUE;
  163. }
  164. //
  165. // generic functions for dealing with 3rd party DLL's
  166. // that might be fusionized
  167. //
  168. HANDLE
  169. spFusionContextFromModule(
  170. IN PCTSTR ModuleName
  171. )
  172. /*++
  173. Routine Description:
  174. Called to get a fusion context for specified module name
  175. given blah.dll look for
  176. 1) blah.dll.manifest in same directory as blah.dll
  177. 2) blah.dll with a fusion resource ID 123.
  178. If either of these provide a valid manifest, use it
  179. otherwise use app global manifest.
  180. Arguments:
  181. name of module that'll later be passed into LoadLibrary
  182. Return Value:
  183. fusion context
  184. --*/
  185. {
  186. ACTCTX act = { 0 };
  187. HANDLE hContext;
  188. TCHAR ManifestName[MAX_PATH+10];
  189. PTSTR End;
  190. DWORD len;
  191. act.cbSize = sizeof(act);
  192. //
  193. // based loosely on rundll32 code
  194. // however we look for manifest in same directory as the dll
  195. // so look for dll first
  196. //
  197. len = SearchPath(NULL,ModuleName,NULL,MAX_PATH,ManifestName,NULL);
  198. if(len>=MAX_PATH) {
  199. //
  200. // path length of DLL too big, just use global context
  201. //
  202. goto deflt;
  203. }
  204. if(!len) {
  205. len = lstrlen(ModuleName);
  206. if(len>=MAX_PATH) {
  207. goto deflt;
  208. }
  209. lstrcpy(ManifestName,ModuleName);
  210. }
  211. if(GetFileAttributes(ManifestName) == -1) {
  212. //
  213. // didn't find DLL?
  214. //
  215. goto deflt;
  216. }
  217. lstrcpy(ManifestName+len,TEXT(".Manifest"));
  218. if(GetFileAttributes(ManifestName) != -1) {
  219. //
  220. // found manifest
  221. //
  222. act.lpSource = ManifestName;
  223. act.dwFlags = 0;
  224. hContext = CreateActCtx(&act);
  225. if(hContext != INVALID_HANDLE_VALUE) {
  226. //
  227. // we created context based on manifest file
  228. //
  229. return hContext;
  230. }
  231. }
  232. deflt:
  233. //
  234. // if the dll has a manifest resource
  235. // then use that
  236. //
  237. act.lpSource = ModuleName;
  238. // act.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID;
  239. // act.lpResourceName = MAKEINTRESOURCE(123);
  240. act.dwFlags = 0;
  241. hContext = CreateActCtx(&act);
  242. if(hContext != INVALID_HANDLE_VALUE) {
  243. //
  244. // we created context based on resource
  245. //
  246. return hContext;
  247. }
  248. //
  249. // if we couldn't find an alternative, use app-global
  250. //
  251. return NULL;
  252. }
  253. BOOL
  254. spFusionKillContext(
  255. IN HANDLE hContext
  256. )
  257. /*++
  258. Routine Description:
  259. Release a context previously obtained by
  260. spFusionContextFromModule
  261. Arguments:
  262. fusion context
  263. Return Value:
  264. TRUE (always)
  265. --*/
  266. {
  267. if(hContext) {
  268. ReleaseActCtx(hContext);
  269. }
  270. return TRUE;
  271. }
  272. BOOL
  273. spFusionEnterContext(
  274. IN HANDLE hContext,
  275. OUT PSPFUSIONINSTANCE pInst
  276. )
  277. /*++
  278. Routine Description:
  279. Enter into a manifest context
  280. status of call is saved into pInst
  281. so that return value does not need
  282. to be checked
  283. Arguments:
  284. hContext = fusion context
  285. pInst = structure to save the "push" information
  286. Return Value:
  287. TRUE if success, FALSE otherwise
  288. --*/
  289. {
  290. pInst->Acquired = ActivateActCtx(hContext,&pInst->Cookie);
  291. MYASSERT(pInst->Acquired);
  292. return pInst->Acquired;
  293. }
  294. BOOL
  295. spFusionLeaveContext(
  296. IN PSPFUSIONINSTANCE pInst
  297. )
  298. /*++
  299. Routine Description:
  300. If pInst indicates that spFusionEnterContext
  301. succeeded, leave same context
  302. Arguments:
  303. pInst = structure initialized by spFusionEnterContext
  304. Return Value:
  305. TRUE if spFusionEnterContext succeeded, FALSE otherwise
  306. --*/
  307. {
  308. if(pInst->Acquired) {
  309. pInst->Acquired = FALSE;
  310. DeactivateActCtx(0,pInst->Cookie);
  311. return TRUE;
  312. } else {
  313. return FALSE;
  314. }
  315. }
  316. HWND spFusionCreateWindow(
  317. LPCTSTR lpClassName, // registered class name
  318. LPCTSTR lpWindowName, // window name
  319. DWORD dwStyle, // window style
  320. int x, // horizontal position of window
  321. int y, // vertical position of window
  322. int nWidth, // window width
  323. int nHeight, // window height
  324. HWND hWndParent, // handle to parent or owner window
  325. HMENU hMenu, // menu handle or child identifier
  326. HINSTANCE hInstance, // handle to application instance
  327. LPVOID lpParam // window-creation data
  328. )
  329. {
  330. spFusionCheckInit();
  331. return SHFusionCreateWindow(lpClassName,
  332. lpWindowName,
  333. dwStyle,
  334. x,
  335. y,
  336. nWidth,
  337. nHeight,
  338. hWndParent,
  339. hMenu,
  340. hInstance,
  341. lpParam
  342. );
  343. }
  344. HWND spFusionCreateWindowEx(
  345. DWORD dwExStyle, // extended window style
  346. LPCTSTR lpClassName, // registered class name
  347. LPCTSTR lpWindowName, // window name
  348. DWORD dwStyle, // window style
  349. int x, // horizontal position of window
  350. int y, // vertical position of window
  351. int nWidth, // window width
  352. int nHeight, // window height
  353. HWND hWndParent, // handle to parent or owner window
  354. HMENU hMenu, // menu handle or child identifier
  355. HINSTANCE hInstance, // handle to application instance
  356. LPVOID lpParam // window-creation data
  357. )
  358. {
  359. spFusionCheckInit();
  360. return SHFusionCreateWindowEx(dwExStyle,
  361. lpClassName,
  362. lpWindowName,
  363. dwStyle,
  364. x,
  365. y,
  366. nWidth,
  367. nHeight,
  368. hWndParent,
  369. hMenu,
  370. hInstance,
  371. lpParam
  372. );
  373. }
  374. HWND spFusionCreateDialogParam(
  375. HINSTANCE hInstance, // handle to module
  376. LPCTSTR lpTemplateName, // dialog box template
  377. HWND hWndParent, // handle to owner window
  378. DLGPROC lpDialogFunc, // dialog box procedure
  379. LPARAM dwInitParam // initialization value
  380. )
  381. {
  382. spFusionCheckInit();
  383. return SHFusionCreateDialogParam(
  384. hInstance,
  385. lpTemplateName,
  386. hWndParent,
  387. lpDialogFunc,
  388. dwInitParam
  389. );
  390. }
  391. HWND spFusionCreateDialogIndirectParam(
  392. HINSTANCE hInstance, // handle to module
  393. LPCDLGTEMPLATE lpTemplate, // dialog box template
  394. HWND hWndParent, // handle to owner window
  395. DLGPROC lpDialogFunc, // dialog box procedure
  396. LPARAM lParamInit // initialization value
  397. )
  398. {
  399. spFusionCheckInit();
  400. return SHFusionCreateDialogIndirectParam(
  401. hInstance,
  402. lpTemplate,
  403. hWndParent,
  404. lpDialogFunc,
  405. lParamInit
  406. );
  407. }
  408. INT_PTR spFusionDialogBoxParam(
  409. HINSTANCE hInstance, // handle to module
  410. LPCTSTR lpTemplateName, // dialog box template
  411. HWND hWndParent, // handle to owner window
  412. DLGPROC lpDialogFunc, // dialog box procedure
  413. LPARAM dwInitParam // initialization value
  414. )
  415. {
  416. spFusionCheckInit();
  417. return SHFusionDialogBoxParam(
  418. hInstance,
  419. lpTemplateName,
  420. hWndParent,
  421. lpDialogFunc,
  422. dwInitParam
  423. );
  424. }
  425. INT_PTR spFusionDialogBoxIndirectParam(
  426. HINSTANCE hInstance, // handle to module
  427. LPCDLGTEMPLATE hDialogTemplate, // dialog box template
  428. HWND hWndParent, // handle to owner window
  429. DLGPROC lpDialogFunc, // dialog box procedure
  430. LPARAM dwInitParam // initialization value
  431. )
  432. {
  433. spFusionCheckInit();
  434. return SHFusionDialogBoxIndirectParam(
  435. hInstance,
  436. hDialogTemplate,
  437. hWndParent,
  438. lpDialogFunc,
  439. dwInitParam
  440. );
  441. }
  442. int spFusionMessageBox(
  443. IN HWND hWnd,
  444. IN LPCTSTR lpText,
  445. IN LPCTSTR lpCaption,
  446. IN UINT uType
  447. )
  448. {
  449. ULONG_PTR dwCookie;
  450. BOOL act;
  451. int iRes = 0;
  452. spFusionCheckInit();
  453. act = SHActivateContext(&dwCookie);
  454. try {
  455. iRes = MessageBoxW(
  456. hWnd,
  457. lpText,
  458. lpCaption,
  459. uType
  460. );
  461. } finally {
  462. if(act) {
  463. SHDeactivateContext(dwCookie);
  464. }
  465. }
  466. return iRes;
  467. }
  468. INT_PTR spFusionPropertySheet(
  469. LPCPROPSHEETHEADER pPropSheetHeader
  470. )
  471. {
  472. spFusionCheckInit();
  473. return PropertySheetW(pPropSheetHeader);
  474. }
  475. HPROPSHEETPAGE spFusionCreatePropertySheetPage(
  476. LPPROPSHEETPAGE pPropSheetPage
  477. )
  478. {
  479. spFusionCheckInit();
  480. MYASSERT(pPropSheetPage->dwFlags & PSP_USEFUSIONCONTEXT);
  481. MYASSERT(!pPropSheetPage->hActCtx);
  482. MYASSERT(pPropSheetPage->dwSize >= sizeof(PROPSHEETPAGE));
  483. return CreatePropertySheetPageW(pPropSheetPage);
  484. }
  485. BOOL spFusionDestroyPropertySheetPage(
  486. HPROPSHEETPAGE hPropSheetPage
  487. )
  488. {
  489. spFusionCheckInit();
  490. return DestroyPropertySheetPage(
  491. hPropSheetPage
  492. );
  493. }
  494. HIMAGELIST spFusionImageList_Create(int cx, int cy, UINT flags, int cInitial, int cGrow)
  495. {
  496. spFusionCheckInit();
  497. return ImageList_Create(
  498. cx,
  499. cy,
  500. flags,
  501. cInitial,
  502. cGrow
  503. );
  504. }
  505. BOOL spFusionImageList_Destroy(HIMAGELIST himl)
  506. {
  507. spFusionCheckInit();
  508. return ImageList_Destroy(
  509. himl
  510. );
  511. }
  512. int spFusionImageList_Add(HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
  513. {
  514. spFusionCheckInit();
  515. return ImageList_Add(
  516. himl,
  517. hbmImage,
  518. hbmMask
  519. );
  520. }
  521. int spFusionImageList_ReplaceIcon(HIMAGELIST himl, int i, HICON hicon)
  522. {
  523. spFusionCheckInit();
  524. return ImageList_ReplaceIcon(
  525. himl,
  526. i,
  527. hicon
  528. );
  529. }
  530. COLORREF spFusionImageList_SetBkColor(HIMAGELIST himl, COLORREF clrBk)
  531. {
  532. spFusionCheckInit();
  533. return ImageList_SetBkColor(
  534. himl,
  535. clrBk
  536. );
  537. }
  538. BOOL spFusionImageList_SetOverlayImage(HIMAGELIST himl, int iImage, int iOverlay)
  539. {
  540. spFusionCheckInit();
  541. return ImageList_SetOverlayImage(
  542. himl,
  543. iImage,
  544. iOverlay
  545. );
  546. }
  547. BOOL spFusionGetOpenFileName(LPOPENFILENAME lpofn)
  548. {
  549. spFusionCheckInit();
  550. return GetOpenFileNameW(lpofn);
  551. }
  552. #endif // FUSIONAWARE