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.

587 lines
15 KiB

  1. /*****************************************************************************
  2. *
  3. * Sti.c
  4. *
  5. * Copyright (C) Microsoft Corporation, 1996 - 1998 All Rights Reserved.
  6. *
  7. * Abstract:
  8. *
  9. * DLL Initialization/termination routines and global
  10. * exported functions
  11. *
  12. * Contents:
  13. *
  14. * StiCreateInstance() - exported function to create top level instance
  15. *
  16. *****************************************************************************/
  17. #define INITGUID
  18. #include "pch.h"
  19. //
  20. // Externs found in STIRT
  21. //
  22. extern DWORD g_cRef;
  23. extern CRITICAL_SECTION g_crstDll;
  24. extern CHAR szProcessCommandLine[MAX_PATH];
  25. #ifdef DEBUG
  26. extern int g_cCrit;
  27. #endif
  28. extern VOID RegSTIforWiaHelper(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
  29. extern VOID MigrateSTIAppsHelper(HWND hWnd, HINSTANCE hInst, PTSTR pszCommandLine, INT iParam);
  30. #include <rpcproxy.h>
  31. #define DbgFl DbgFlSti
  32. BOOL APIENTRY
  33. DmPrxyDllMain(
  34. HINSTANCE hinst,
  35. DWORD dwReason,
  36. LPVOID lpReserved
  37. );
  38. STDAPI
  39. DmPrxyDllGetClassObject(
  40. REFCLSID rclsid,
  41. RIID riid,
  42. PPV ppvObj
  43. );
  44. STDMETHODIMP
  45. DmPrxyDllCanUnloadNow(
  46. void
  47. );
  48. /*****************************************************************************
  49. *
  50. * @doc INTERNAL
  51. *
  52. * @func void | DllEnterCrit |
  53. *
  54. * Take the DLL critical section.
  55. *
  56. * The DLL critical section is the lowest level critical section.
  57. * You may not attempt to acquire any other critical sections or
  58. * yield while the DLL critical section is held.
  59. *
  60. *****************************************************************************/
  61. void EXTERNAL
  62. DllEnterCrit(void)
  63. {
  64. EnterCriticalSection(&g_crstDll);
  65. #ifdef DEBUG
  66. // Save thread ID , taking critical section first , it becomes owner
  67. if (++g_cCrit == 0) {
  68. g_thidCrit = GetCurrentThreadId();
  69. }
  70. AssertF(g_thidCrit == GetCurrentThreadId());
  71. #endif
  72. }
  73. /*****************************************************************************
  74. *
  75. * @doc INTERNAL
  76. *
  77. * @func void | DllLeaveCrit |
  78. *
  79. * Leave the DLL critical section.
  80. *
  81. *****************************************************************************/
  82. void EXTERNAL
  83. DllLeaveCrit(void)
  84. {
  85. #ifdef DEBUG
  86. AssertF(g_thidCrit == GetCurrentThreadId());
  87. AssertF(g_cCrit >= 0);
  88. if (--g_cCrit < 0) {
  89. g_thidCrit = 0;
  90. }
  91. #endif
  92. LeaveCriticalSection(&g_crstDll);
  93. }
  94. /*****************************************************************************
  95. *
  96. * @doc INTERNAL
  97. *
  98. * @func void | DllAddRef |
  99. *
  100. * Increment the reference count on the DLL.
  101. *
  102. *****************************************************************************/
  103. void EXTERNAL
  104. DllAddRef(void)
  105. {
  106. InterlockedIncrement((LPLONG)&g_cRef);
  107. }
  108. /*****************************************************************************
  109. *
  110. * @doc INTERNAL
  111. *
  112. * @func void | DllRelease |
  113. *
  114. * Decrement the reference count on the DLL.
  115. *
  116. *****************************************************************************/
  117. void EXTERNAL
  118. DllRelease(void)
  119. {
  120. InterlockedDecrement((LPLONG)&g_cRef);
  121. }
  122. /*****************************************************************************
  123. *
  124. * @doc INTERNAL
  125. *
  126. * @func HRESULT | DllGetClassObject |
  127. *
  128. * Create an <i IClassFactory> instance for this DLL.
  129. *
  130. * @parm REFCLSID | rclsid |
  131. *
  132. * The object being requested.
  133. *
  134. * @parm RIID | riid |
  135. *
  136. * The desired interface on the object.
  137. *
  138. * @parm PPV | ppvOut |
  139. *
  140. * Output pointer.
  141. *
  142. *****************************************************************************/
  143. #pragma BEGIN_CONST_DATA
  144. CLSIDMAP c_rgclsidmap[cclsidmap] = {
  145. { &CLSID_Sti, CStiObj_New, IDS_STIOBJ },
  146. // { &CLSID_StiDevice, CStiDevice_New, IDS_STIDEVICE },
  147. };
  148. #pragma END_CONST_DATA
  149. STDAPI
  150. DllGetClassObject(REFCLSID rclsid, RIID riid, PPV ppvObj)
  151. {
  152. HRESULT hres;
  153. UINT iclsidmap;
  154. EnterProcR(DllGetClassObject, (_ "G", rclsid));
  155. //
  156. // Bump global ref count temporarily. By doing so we minimize chances of
  157. // faulting on potential race condition when another thread just called
  158. // DllCanUnloadNow while we are inside ClassFactory.
  159. //
  160. DllAddRef();
  161. for (iclsidmap = 0; iclsidmap < cA(c_rgclsidmap); iclsidmap++) {
  162. if (IsEqualIID(rclsid, c_rgclsidmap[iclsidmap].rclsid)) {
  163. hres = CSti_Factory_New(c_rgclsidmap[iclsidmap].pfnCreate,
  164. riid, ppvObj);
  165. goto done;
  166. }
  167. }
  168. DebugOutPtszV(DbgFlDll | DbgFlError, TEXT("%s: Wrong CLSID"),"");
  169. *ppvObj = 0;
  170. hres = CLASS_E_CLASSNOTAVAILABLE;
  171. done:;
  172. //
  173. // If unsucessful - try DM Proxy
  174. //
  175. if (!SUCCEEDED(hres)) {
  176. hres = DmPrxyDllGetClassObject(rclsid, riid, ppvObj);
  177. }
  178. ExitOleProcPpv(ppvObj);
  179. DllRelease();
  180. return hres;
  181. }
  182. /*****************************************************************************
  183. *
  184. * @doc INTERNAL
  185. *
  186. * @func HRESULT | DllCanUnloadNow |
  187. *
  188. * Determine whether the DLL has any outstanding interfaces.
  189. *
  190. * @returns
  191. *
  192. * Returns <c S_OK> if the DLL can unload, <c S_FALSE> if
  193. * it is not safe to unload.
  194. *
  195. *****************************************************************************/
  196. STDMETHODIMP
  197. DllCanUnloadNow(void)
  198. {
  199. HRESULT hres;
  200. //
  201. // First ask DM proxy and it says OK - check out ref count
  202. //
  203. hres = DmPrxyDllCanUnloadNow();
  204. if (hres == S_OK) {
  205. #ifdef DEBUG
  206. DebugOutPtszV(DbgFlDll, TEXT("DllCanUnloadNow() - g_cRef = %d"), g_cRef);
  207. Common_DumpObjects();
  208. #endif
  209. hres = g_cRef ? S_FALSE : S_OK;
  210. }
  211. return hres;
  212. }
  213. /*****************************************************************************
  214. *
  215. * @doc INTERNAL
  216. *
  217. * @func BOOL | DllEntryPoint |
  218. *
  219. * Called to notify the DLL about various things that can happen.
  220. *
  221. * We are not interested in thread attaches and detaches,
  222. * so we disable thread notifications for performance reasons.
  223. *
  224. * @parm HINSTANCE | hinst |
  225. *
  226. * The instance handle of this DLL.
  227. *
  228. * @parm DWORD | dwReason |
  229. *
  230. * Notification code.
  231. *
  232. * @parm LPVOID | lpReserved |
  233. *
  234. * Not used.
  235. *
  236. * @returns
  237. *
  238. * Returns <c TRUE> to allow the DLL to load.
  239. *
  240. *****************************************************************************/
  241. #pragma BEGIN_CONST_DATA
  242. #pragma END_CONST_DATA
  243. BOOL APIENTRY
  244. DllEntryPoint(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
  245. {
  246. //RPC_STATUS RpcStatus;
  247. DWORD dwLocalSTIServerVer = 0;
  248. UINT uiCmdLineLength;
  249. switch (dwReason) {
  250. case DLL_PROCESS_ATTACH:
  251. g_hInst = hinst;
  252. __try {
  253. // Disable thread library calls to avoid
  254. // deadlock when we spin up the worker thread
  255. DisableThreadLibraryCalls(hinst);
  256. if(!InitializeCriticalSectionAndSpinCount(&g_crstDll, MINLONG)) {
  257. // refuse to load if we can't initialize critsect
  258. return FALSE;
  259. }
  260. // Set global flags
  261. g_NoUnicodePlatform = !OSUtil_IsPlatformUnicode();
  262. //
  263. // Save command line for use in GetLaunchInformation
  264. //
  265. uiCmdLineLength = min(lstrlenA(GetCommandLineA()),sizeof(szProcessCommandLine)-1);
  266. lstrcpyn(szProcessCommandLine,GetCommandLineA(),uiCmdLineLength);
  267. szProcessCommandLine[uiCmdLineLength] = '\0';
  268. #ifdef DEBUG
  269. // Debugging flags
  270. InitializeDebuggingSupport();
  271. #endif
  272. //
  273. // Initialize file logging
  274. //
  275. g_hStiFileLog = CreateStiFileLog(TEXT("STICLI"),NULL,
  276. STI_TRACE_ERROR |
  277. STI_TRACE_ADD_THREAD | STI_TRACE_ADD_PROCESS
  278. );
  279. #if CHECK_LOCAL_SERVER
  280. // Check version of the local server
  281. RpcStatus = RpcStiApiGetVersion(NULL,
  282. 0,
  283. &dwLocalSTIServerVer);
  284. DebugOutPtszV(DbgFlDll, TEXT("STIINIT : Getting server version : RpcStatus = %d LocalServerVer=%d"),
  285. RpcStatus,dwLocalSTIServerVer);
  286. #endif
  287. }
  288. __except(EXCEPTION_EXECUTE_HANDLER) {
  289. return FALSE;
  290. }
  291. break;
  292. case DLL_PROCESS_DETACH:
  293. if (g_cRef) {
  294. DebugOutPtszV(DbgFl,"Unloaded before all objects Release()d! Crash soon!\r\n");
  295. }
  296. // Close file logging
  297. CloseStiFileLog(g_hStiFileLog);
  298. //
  299. // Don't forget to delete our critical section. (It is safe to
  300. // do this because we definitely tried to initialize it and so
  301. // it should be in a sane state)
  302. //
  303. DeleteCriticalSection(&g_crstDll);
  304. break;
  305. }
  306. return 1;
  307. }
  308. BOOL APIENTRY
  309. DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID lpReserved)
  310. {
  311. // First call proxy dll main
  312. DmPrxyDllMain(hinst, dwReason, lpReserved);
  313. return DllEntryPoint(hinst, dwReason, lpReserved);
  314. }
  315. /*****************************************************************************
  316. *
  317. * @doc EXTERNAL
  318. *
  319. * @func HRESULT | StiCreateInstance |
  320. *
  321. * <bnew>This function creates a new Sti object
  322. * which supports the <i ISti> COM interface.
  323. *
  324. * On success, the function returns a pointer to the new object in
  325. * *<p lplpSti>.
  326. * <enew>
  327. *
  328. * @parm IN HINSTANCE | hinst |
  329. *
  330. * Instance handle of the application or DLL that is creating
  331. * the Sti object.
  332. *
  333. * Sti uses this value to determine whether the
  334. * application or DLL has been certified.
  335. *
  336. * @parm DWORD | dwVersion |
  337. *
  338. * Version number of the sti.h header file that was used.
  339. * This value must be <c STI_VERSION>.
  340. *
  341. * Sti uses this value to determine what version of
  342. * Sti the application or DLL was designed for.
  343. *
  344. * @parm OUT LPSti * | lplpSti |
  345. * Points to where to return
  346. * the pointer to the <i ISti> interface, if successful.
  347. *
  348. * @parm IN LPUNKNOWN | punkOuter | Pointer to controlling unknown
  349. * for OLE aggregation, or 0 if the interface is not aggregated.
  350. * Most callers will pass 0.
  351. *
  352. * Note that if aggregation is requested, the object returned
  353. * in *<p lplpSti> will be a pointer to an
  354. * <i IUnknown> rather than an <i ISti>, as required
  355. * by OLE aggregation.
  356. *
  357. * @returns
  358. *
  359. * Returns a COM error code. The following error codes are
  360. * intended to be illustrative and not necessarily comprehensive.
  361. *
  362. * <c STI_OK> = <c S_OK>: The operation completed successfully.
  363. *
  364. * <c STIERR_INVALIDPARAM> = <c E_INVALIDARG>: The
  365. * <p lplpSti> parameter is not a valid pointer.
  366. *
  367. * <c STIERR_OUTOFMEMORY> = <c E_OUTOFMEMORY>:
  368. * Out of memory.
  369. *
  370. * <c STIERR_STIERR_OLDStiVERSION>: The application
  371. * requires a newer version of Sti.
  372. *
  373. * <c STIERR_STIERR_BETAStiVERSION>: The application
  374. * was written for an unsupported prerelease version
  375. * of Sti.
  376. *
  377. * @comm Calling this function with <p punkOuter> = NULL
  378. * is equivalent to creating the object via
  379. * <f CoCreateInstance>(&CLSID_Sti, <p punkOuter>,
  380. * CLSCTX_INPROC_SERVER, &IID_ISti, <p lplpSti>);
  381. * then initializing it with <f Initialize>.
  382. *
  383. * Calling this function with <p punkOuter> != NULL
  384. * is equivalent to creating the object via
  385. * <f CoCreateInstance>(&CLSID_Sti, <p punkOuter>,
  386. * CLSCTX_INPROC_SERVER, &IID_IUnknown, <p lplpSti>).
  387. * The aggregated object must be initialized manually.
  388. *
  389. *****************************************************************************/
  390. STDMETHODIMP
  391. StiCreateInstanceW(HINSTANCE hinst, DWORD dwVer, PSTI *ppSti, PUNK punkOuter)
  392. {
  393. HRESULT hres;
  394. EnterProc(StiCreateInstance, (_ "xxx", hinst, dwVer, punkOuter));
  395. hres = StiCreateHelper(hinst, dwVer, (PPV)ppSti, punkOuter,&IID_IStillImageW);
  396. ExitOleProcPpv(ppSti);
  397. return hres;
  398. }
  399. STDMETHODIMP
  400. StiCreateInstanceA(HINSTANCE hinst, DWORD dwVer, PSTIA *ppSti, PUNK punkOuter)
  401. {
  402. HRESULT hres;
  403. EnterProc(StiCreateInstance, (_ "xxx", hinst, dwVer, punkOuter));
  404. hres = StiCreateHelper(hinst, dwVer, (PPV)ppSti, punkOuter,&IID_IStillImageA);
  405. ExitOleProcPpv(ppSti);
  406. return hres;
  407. }
  408. /*****************************************************************************
  409. *
  410. * @doc INTERNAL
  411. *
  412. * @func HRESULT | DllInitializeCOM |
  413. *
  414. * Initialize COM libraries
  415. *
  416. * @parm IN | |
  417. *
  418. * @returns
  419. *
  420. * Returns a boolean error code.
  421. *
  422. *****************************************************************************/
  423. BOOL
  424. EXTERNAL
  425. DllInitializeCOM(
  426. void
  427. )
  428. {
  429. DllEnterCrit();
  430. if(!g_COMInitialized) {
  431. #ifdef USE_REAL_OLE32
  432. if(SUCCEEDED(CoInitializeEx(NULL,
  433. COINIT_MULTITHREADED |
  434. COINIT_DISABLE_OLE1DDE))
  435. ) {
  436. g_COMInitialized = TRUE;
  437. }
  438. #else
  439. g_COMInitialized = TRUE;
  440. #endif
  441. }
  442. DllLeaveCrit();
  443. return g_COMInitialized;
  444. }
  445. /*****************************************************************************
  446. *
  447. * @doc INTERNAL
  448. *
  449. * @func HRESULT | DllUnInitializeCOM |
  450. *
  451. * UnInitialize COM libraries
  452. *
  453. * @parm IN | |
  454. *
  455. * @returns
  456. *
  457. * Returns a boolean error code.
  458. *
  459. *****************************************************************************/
  460. BOOL EXTERNAL
  461. DllUnInitializeCOM(
  462. void
  463. )
  464. {
  465. DllEnterCrit();
  466. #ifdef USE_REAL_OLE32
  467. if(g_COMInitialized) {
  468. CoUninitialize();
  469. g_COMInitialized = FALSE;
  470. }
  471. #endif
  472. DllLeaveCrit();
  473. return TRUE;
  474. }
  475. /*****************************************************************************
  476. *
  477. * @doc INTERNAL
  478. *
  479. * @func VOID | RegSTIforWia |
  480. *
  481. * Private server entry point to register STI apps for WIA events
  482. *
  483. * @parm IN | |
  484. *
  485. * @returns
  486. *
  487. * VOID
  488. *
  489. *****************************************************************************/
  490. VOID
  491. EXTERNAL
  492. RegSTIforWia(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  493. {
  494. RegSTIforWiaHelper(hwnd, hinst, lpszCmdLine, nCmdShow);
  495. }
  496. VOID
  497. WINAPI
  498. MigrateRegisteredSTIAppsForWIAEvents(
  499. HWND hWnd,
  500. HINSTANCE hInst,
  501. PTSTR pszCommandLine,
  502. INT iParam
  503. )
  504. {
  505. MigrateSTIAppsHelper(hWnd,
  506. hInst,
  507. pszCommandLine,
  508. iParam);
  509. }