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.

234 lines
6.7 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 2000
  4. *
  5. * TITLE: wiasvc.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ByronC
  10. *
  11. * DATE: 10 May, 2000
  12. *
  13. * DESCRIPTION:
  14. * Class implementation for WIA Service manager. This class controls the
  15. * lifetime of the Wia Service.
  16. *
  17. *******************************************************************************/
  18. #include "precomp.h"
  19. #include "stiexe.h"
  20. #include "wiasvc.h"
  21. HRESULT CWiaSvc::Initialize()
  22. {
  23. return S_OK;
  24. }
  25. bool CWiaSvc::CanShutdown()
  26. {
  27. //
  28. // We are only safe to shutdown if there are no devices capable of generating events,
  29. // and we have no outstanding interfaces.
  30. //
  31. return (! (s_cActiveInterfaces || s_bEventDeviceExists));
  32. }
  33. bool CWiaSvc::ADeviceIsInstalled()
  34. {
  35. bool bRet = TRUE; // On error, we assume there is a device installed
  36. #ifdef WINNT
  37. SC_HANDLE hSCM = NULL;
  38. SC_HANDLE hService = NULL;
  39. QUERY_SERVICE_CONFIG qscDummy;
  40. QUERY_SERVICE_CONFIG *pqscConfig = NULL;
  41. DWORD cbBytesNeeded = 0;
  42. __try {
  43. hSCM = ::OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
  44. if (!hSCM) {
  45. __leave;
  46. }
  47. //
  48. // Check startup type of the service. If it is DEMAND_START, then no devices are
  49. // installed, so return FALSE.
  50. //
  51. // First get a handle to the SCM
  52. //
  53. hService = OpenService(
  54. hSCM,
  55. STI_SERVICE_NAME,
  56. SERVICE_ALL_ACCESS
  57. );
  58. if (hService) {
  59. LONG lQueryRet = 0;
  60. //
  61. // Next, get the size needed for the service config struct.
  62. //
  63. lQueryRet = QueryServiceConfig(hService,
  64. &qscDummy,
  65. 1,
  66. &cbBytesNeeded);
  67. pqscConfig = (QUERY_SERVICE_CONFIG*) LocalAlloc(LPTR, cbBytesNeeded);
  68. if (pqscConfig) {
  69. //
  70. // Now, get the sevice info so we can check the startup type
  71. //
  72. lQueryRet = QueryServiceConfig(hService,
  73. pqscConfig,
  74. cbBytesNeeded,
  75. &cbBytesNeeded);
  76. if (lQueryRet) {
  77. if (pqscConfig->dwStartType == SERVICE_DEMAND_START) {
  78. //
  79. // Startup type is demand start, so no devices are
  80. // currently installed
  81. //
  82. bRet = FALSE;
  83. }
  84. }
  85. }
  86. }
  87. }
  88. __finally {
  89. CloseServiceHandle( hService );
  90. CloseServiceHandle( hSCM );
  91. if (pqscConfig) {
  92. LocalFree(pqscConfig);
  93. pqscConfig = NULL;
  94. }
  95. }
  96. #else
  97. //
  98. // On Win9x systems, always return TRUE. This will keep us active all the time.
  99. //
  100. bRet = TRUE;
  101. #endif
  102. return bRet;
  103. }
  104. unsigned long CWiaSvc::AddRef()
  105. {
  106. //
  107. // NOTE: For now, assume that if any device exists, then it may generate events, so
  108. // set s_bEventDeviceExists to TRUE. Also, note that once s_bEventDeviceExists is
  109. // set to TRUE, it is never set to FALSE. This is to cover the case when the device
  110. // is unplugged. In this case the device count could be zero, but we still need the service
  111. // running to catch when it is plugged in again (so it can launch appropriate app.
  112. // notify event listeners etc.)
  113. //
  114. if (!s_bEventDeviceExists) {
  115. if (ADeviceIsInstalled()) {
  116. s_bEventDeviceExists = TRUE;
  117. }
  118. }
  119. InterlockedIncrement(&s_cActiveInterfaces);
  120. //
  121. // If no devices with events exists, we must live purely on number of outstanding active
  122. // interfaces we have handed out i.e. when the last interface is released by the caller,
  123. // we are free to shut down.
  124. // If a device capable of generating events does exist, we must remain running, since
  125. // we have to listen/poll for event which could come at any time.
  126. //
  127. if (!s_bEventDeviceExists) {
  128. return CoAddRefServerProcess();
  129. }
  130. return 2;
  131. }
  132. unsigned long CWiaSvc::Release()
  133. {
  134. InterlockedIncrement(&s_cActiveInterfaces);
  135. //
  136. // If no devices with events exists, we must live purely on number of outstanding active
  137. // interfaces we have handed out i.e. when the last interface is released by the caller,
  138. // we are free to shut down.
  139. // If a device capable of generating events does exist, we must remain running, since
  140. // we have to listen/poll for event which could come at any time.
  141. //
  142. if (!s_bEventDeviceExists) {
  143. unsigned long ulRef = 1;
  144. /* NOTE!!! This is TEMPORARY.
  145. This will guarantee we don't get errors during setup regarding
  146. StartRPCServerListen(...). A beneficial side-effect is that WIA
  147. Acquisition Manager's event registration will succeed (it will fail
  148. if StartRPCServerListen fails).
  149. One noted side-effect is that the WIA service will not automatically shutdown
  150. if no devices are installed and an imaging application exits.
  151. ulRef = CoReleaseServerProcess();
  152. if (ulRef == 0) {
  153. //
  154. // We have no devices that can generate events, and we have no outstanding
  155. // interfaces, so shutdown...
  156. //
  157. ShutDown();
  158. }
  159. */
  160. return ulRef;
  161. }
  162. //
  163. // NOTE: If a device capable of generating events exists, we NEVER call CoReleaseServerProcess(),
  164. // since this will suspend the creation of our Class Objects when ref count is 0, which means a new
  165. // server process would need to be started when a WIA application did a CoCreate to talk to WIA.
  166. //
  167. return 1;
  168. }
  169. void CWiaSvc::ShutDown()
  170. {
  171. //
  172. // Inform COM to ignore all activation requests
  173. //
  174. CoSuspendClassObjects();
  175. //
  176. // Call the control entry to stop the service
  177. //
  178. StiServiceStop();
  179. }
  180. //
  181. // Initialize static data members
  182. //
  183. long CWiaSvc::s_cActiveInterfaces = 0;
  184. bool CWiaSvc::s_bEventDeviceExists = FALSE;