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.

509 lines
11 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxsvc.c
  5. Abstract:
  6. This module contains the service specific code.
  7. Author:
  8. Wesley Witt (wesw) 16-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "faxsvc.h"
  12. #pragma hdrstop
  13. #if DBGX
  14. //
  15. // this is bad place to have these defines
  16. // because they are already in ntexapi.h, but it
  17. // is difficult to include windows headers and
  18. // nt headers together. we will just have to be
  19. // aware that if the global flag definitions in
  20. // ntexapi.h change, they must also change here.
  21. //
  22. #define FLG_SHOW_LDR_SNAPS 0x00000002 // user and kernel mode
  23. #define FLG_USER_STACK_TRACE_DB 0x00001000 // x86 user mode only
  24. #define FLG_HEAP_ENABLE_CALL_TRACING 0x00100000 // user mode only
  25. #define FLG_HEAP_PAGE_ALLOCS 0x02000000 // user mode only
  26. IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used =
  27. {
  28. 0, // Reserved
  29. 0, // Reserved
  30. 0, // Reserved
  31. 0, // Reserved
  32. 0, // GlobalFlagsClear
  33. FLG_USER_STACK_TRACE_DB | FLG_HEAP_ENABLE_CALL_TRACING,
  34. 0, // CriticalSectionTimeout (milliseconds)
  35. 0, // DeCommitFreeBlockThreshold
  36. 0, // DeCommitTotalFreeThreshold
  37. NULL, // LockPrefixTable
  38. 0, 0, 0, 0, 0, 0, 0 // Reserved
  39. };
  40. #endif
  41. SERVICE_STATUS FaxServiceStatus;
  42. SERVICE_STATUS_HANDLE FaxServiceStatusHandle;
  43. BOOL ServiceDebug;
  44. HANDLE FaxSvcHeapHandle;
  45. SERVICE_TABLE_ENTRY ServiceDispatchTable[] = {
  46. { FAX_SERVICE_NAME, FaxServiceMain },
  47. { NULL, NULL }
  48. };
  49. int
  50. WINAPI
  51. #ifdef UNICODE
  52. wWinMain(
  53. #else
  54. WinMain(
  55. #endif
  56. HINSTANCE hInstance,
  57. HINSTANCE hPrevInstance,
  58. LPTSTR lpCmdLine,
  59. int nShowCmd
  60. )
  61. /*++
  62. Routine Description:
  63. Main entry point for the TIFF image viewer.
  64. Arguments:
  65. hInstance - Instance handle
  66. hPrevInstance - Not used
  67. lpCmdLine - Command line arguments
  68. nShowCmd - How to show the window
  69. Return Value:
  70. Return code, zero for success.
  71. --*/
  72. {
  73. int rVal;
  74. LPTSTR p;
  75. DWORD Action = 0;
  76. LPTSTR Username;
  77. LPTSTR Password;
  78. FaxSvcHeapHandle = HeapInitialize(NULL,NULL,NULL,0);
  79. FaxTiffInitialize();
  80. for (p=lpCmdLine; *p; p++) {
  81. if ((*p == TEXT('-')) || (*p == TEXT('/'))) {
  82. switch( _totlower( p[1] ) ) {
  83. case TEXT('i'):
  84. Action = 1;
  85. p += 2;
  86. while( *p == TEXT(' ') ) p++;
  87. Username = p;
  88. while( *p != TEXT(' ') ) p++;
  89. while( *p == TEXT(' ') ) p++;
  90. Password = p;
  91. while( *p != TEXT(' ') ) p++;
  92. break;
  93. case TEXT('r'):
  94. Action = 2;
  95. break;
  96. case TEXT('d'):
  97. Action = 3;
  98. break;
  99. }
  100. }
  101. }
  102. switch( Action ) {
  103. case 1:
  104. rVal = InstallService( Username, Password );
  105. if (rVal == 0) {
  106. LogMessage( MSG_INSTALL_SUCCESS );
  107. } else {
  108. LogMessage( MSG_INSTALL_FAIL, GetLastErrorText( rVal ) );
  109. }
  110. return rVal;
  111. case 2:
  112. rVal = RemoveService();
  113. if (rVal == 0) {
  114. LogMessage( MSG_REMOVE_SUCCESS );
  115. } else {
  116. LogMessage( MSG_REMOVE_FAIL, GetLastErrorText( rVal ) );
  117. }
  118. return rVal;
  119. case 3:
  120. ServiceDebug = TRUE;
  121. ConsoleDebugOutput = TRUE;
  122. return ServiceStart();
  123. }
  124. if (!StartServiceCtrlDispatcher( ServiceDispatchTable)) {
  125. DebugPrint(( TEXT("StartServiceCtrlDispatcher error =%d"), GetLastError() ));
  126. return GetLastError();
  127. }
  128. return 0;
  129. }
  130. DWORD
  131. InstallService(
  132. LPTSTR Username,
  133. LPTSTR Password
  134. )
  135. /*++
  136. Routine Description:
  137. Service installation function. This function just
  138. calls the service controller to install the FAX service.
  139. It is required that the FAX service run in the context
  140. of a user so that the service can access MAPI, files on
  141. disk, the network, etc.
  142. Arguments:
  143. Username - User name where the service runs.
  144. Password - Password for the user name.
  145. Return Value:
  146. Return code. Return zero for success, all other
  147. values indicate errors.
  148. --*/
  149. {
  150. DWORD rVal = 0;
  151. SC_HANDLE hSvcMgr;
  152. SC_HANDLE hService;
  153. hSvcMgr = OpenSCManager(
  154. NULL,
  155. NULL,
  156. SC_MANAGER_ALL_ACCESS
  157. );
  158. if (!hSvcMgr) {
  159. rVal = GetLastError();
  160. DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
  161. return rVal;
  162. }
  163. hService = CreateService(
  164. hSvcMgr,
  165. FAX_SERVICE_NAME,
  166. FAX_DISPLAY_NAME,
  167. SERVICE_ALL_ACCESS,
  168. SERVICE_WIN32_OWN_PROCESS,
  169. SERVICE_AUTO_START,
  170. SERVICE_ERROR_NORMAL,
  171. FAX_IMAGE_NAME,
  172. NULL,
  173. NULL,
  174. NULL,
  175. Username,
  176. Password
  177. );
  178. if (!hService) {
  179. rVal = GetLastError();
  180. DebugPrint(( TEXT("could not create fax service: error code = %u"), rVal ));
  181. return rVal;
  182. }
  183. CloseServiceHandle( hService );
  184. CloseServiceHandle( hSvcMgr );
  185. return rVal;
  186. }
  187. DWORD
  188. RemoveService(
  189. void
  190. )
  191. /*++
  192. Routine Description:
  193. Service removal function. This function just
  194. calls the service controller to remove the FAX service.
  195. Arguments:
  196. None.
  197. Return Value:
  198. Return code. Return zero for success, all other
  199. values indicate errors.
  200. --*/
  201. {
  202. DWORD rVal = 0;
  203. SC_HANDLE hSvcMgr;
  204. SC_HANDLE hService;
  205. hSvcMgr = OpenSCManager(
  206. NULL,
  207. NULL,
  208. SC_MANAGER_ALL_ACCESS
  209. );
  210. if (!hSvcMgr) {
  211. rVal = GetLastError();
  212. DebugPrint(( TEXT("could not open service manager: error code = %u"), rVal ));
  213. return rVal;
  214. }
  215. hService = OpenService(
  216. hSvcMgr,
  217. FAX_SERVICE_NAME,
  218. SERVICE_ALL_ACCESS
  219. );
  220. if (!hService) {
  221. rVal = GetLastError();
  222. DebugPrint(( TEXT("could not open the fax service: error code = %u"), rVal ));
  223. return rVal;
  224. }
  225. if (ControlService( hService, SERVICE_CONTROL_STOP, &FaxServiceStatus )) {
  226. //
  227. // wait for 1 second
  228. //
  229. Sleep( 1000 );
  230. while( QueryServiceStatus( hService, &FaxServiceStatus ) ) {
  231. if ( FaxServiceStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
  232. Sleep( 1000 );
  233. } else {
  234. break;
  235. }
  236. }
  237. if (FaxServiceStatus.dwCurrentState != SERVICE_STOPPED) {
  238. rVal = GetLastError();
  239. DebugPrint(( TEXT("could not stop the fax service: error code = %u"), rVal ));
  240. return rVal;
  241. }
  242. }
  243. if (!DeleteService( hService )) {
  244. rVal = GetLastError();
  245. DebugPrint(( TEXT("could not delete the fax service: error code = %u"), rVal ));
  246. return rVal;
  247. }
  248. CloseServiceHandle( hService );
  249. CloseServiceHandle( hSvcMgr );
  250. return rVal;
  251. }
  252. VOID
  253. FaxServiceMain(
  254. DWORD argc,
  255. LPTSTR *argv
  256. )
  257. /*++
  258. Routine Description:
  259. This is the service main that is called by the
  260. service controller.
  261. Arguments:
  262. argc - argument count
  263. argv - argument array
  264. Return Value:
  265. None.
  266. --*/
  267. {
  268. DWORD Rval;
  269. FaxServiceStatus.dwServiceType = SERVICE_WIN32;
  270. FaxServiceStatus.dwCurrentState = SERVICE_START_PENDING;
  271. FaxServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
  272. FaxServiceStatus.dwWin32ExitCode = 0;
  273. FaxServiceStatus.dwServiceSpecificExitCode = 0;
  274. FaxServiceStatus.dwCheckPoint = 0;
  275. FaxServiceStatus.dwWaitHint = 0;
  276. FaxServiceStatusHandle = RegisterServiceCtrlHandler(
  277. FAX_SERVICE_NAME,
  278. FaxServiceCtrlHandler
  279. );
  280. if (!FaxServiceStatusHandle) {
  281. DebugPrint(( TEXT("RegisterServiceCtrlHandler failed %d"), GetLastError() ));
  282. return;
  283. }
  284. Rval = ServiceStart();
  285. if (!Rval) {
  286. //
  287. // the service failed to start correctly
  288. //
  289. }
  290. return;
  291. }
  292. VOID
  293. FaxServiceCtrlHandler(
  294. DWORD Opcode
  295. )
  296. /*++
  297. Routine Description:
  298. This is the FAX service control dispatch function.
  299. Arguments:
  300. Opcode - requested control code
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. switch(Opcode) {
  306. case SERVICE_CONTROL_PAUSE:
  307. ReportServiceStatus( SERVICE_PAUSED, 0, 0 );
  308. break;
  309. case SERVICE_CONTROL_CONTINUE:
  310. ReportServiceStatus( SERVICE_RUNNING, 0, 0 );
  311. break;
  312. case SERVICE_CONTROL_STOP:
  313. EndFaxSvc(FALSE,FAXLOG_LEVEL_NONE);
  314. return;
  315. case SERVICE_CONTROL_INTERROGATE:
  316. // fall through to send current status
  317. break;
  318. default:
  319. DebugPrint(( TEXT("Unrecognized opcode %ld"), Opcode ));
  320. break;
  321. }
  322. ReportServiceStatus( 0, 0, 0 );
  323. return;
  324. }
  325. DWORD
  326. ReportServiceStatus(
  327. DWORD CurrentState,
  328. DWORD Win32ExitCode,
  329. DWORD WaitHint
  330. )
  331. /*++
  332. Routine Description:
  333. This function updates the service control manager's status information for the FAX service.
  334. Arguments:
  335. CurrentState - Indicates the current state of the service
  336. Win32ExitCode - Specifies a Win32 error code that the service uses to
  337. report an error that occurs when it is starting or stopping.
  338. WaitHint - Specifies an estimate of the amount of time, in milliseconds,
  339. that the service expects a pending start, stop, or continue
  340. operation to take before the service makes its next call to the
  341. SetServiceStatus function with either an incremented dwCheckPoint
  342. value or a change in dwCurrentState.
  343. Return Value:
  344. Return code. Return zero for success, all other
  345. values indicate errors.
  346. --*/
  347. {
  348. static DWORD CheckPoint = 1;
  349. BOOL rVal;
  350. if (ServiceDebug) {
  351. return TRUE;
  352. }
  353. if (CurrentState == SERVICE_START_PENDING) {
  354. FaxServiceStatus.dwControlsAccepted = 0;
  355. } else {
  356. FaxServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
  357. }
  358. if (CurrentState) {
  359. FaxServiceStatus.dwCurrentState = CurrentState;
  360. }
  361. FaxServiceStatus.dwWin32ExitCode = Win32ExitCode;
  362. FaxServiceStatus.dwWaitHint = WaitHint;
  363. if ((FaxServiceStatus.dwCurrentState == SERVICE_RUNNING) ||
  364. (FaxServiceStatus.dwCurrentState == SERVICE_STOPPED ) ) {
  365. FaxServiceStatus.dwCheckPoint = 0;
  366. } else {
  367. FaxServiceStatus.dwCheckPoint = CheckPoint++;
  368. }
  369. //
  370. // Report the status of the service to the service control manager.
  371. //
  372. rVal = SetServiceStatus( FaxServiceStatusHandle, &FaxServiceStatus );
  373. if (!rVal) {
  374. DebugPrint(( TEXT("SetServiceStatus() failed: ec=%d"), GetLastError() ));
  375. }
  376. return rVal;
  377. }