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.

1924 lines
54 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. server.c
  5. Abstract:
  6. This module contains the code to provide the RPC server.
  7. Author:
  8. Wesley Witt (wesw) 16-Jan-1996
  9. Revision History:
  10. --*/
  11. #include "faxsvc.h"
  12. #pragma hdrstop
  13. DWORD g_dwAllowRemote; // If this is non-zero, the service will allow remote calls even if the local printer is not shared.
  14. DWORD g_dwLastUniqueLineId;
  15. DWORD g_dwRecipientsLimit; // Limits the number of recipients in a single broadcast job. '0' means no limit.
  16. FAX_SERVER_RECEIPTS_CONFIGW g_ReceiptsConfig; // Global receipts configuration
  17. FAX_ARCHIVE_CONFIG g_ArchivesConfig[2]; // Global archives configuration
  18. FAX_SERVER_ACTIVITY_LOGGING_CONFIG g_ActivityLoggingConfig; // Global activity logging configuration
  19. const GUID gc_FaxSvcGuid = { 0xc3a9d640, 0xab07, 0x11d0, { 0x92, 0xbf, 0x0, 0xa0, 0x24, 0xaa, 0x1c, 0x1 } };
  20. CFaxCriticalSection g_CsConfig; // Protects configuration read / write
  21. FAX_SERVER_ACTIVITY g_ServerActivity = {sizeof(FAX_SERVER_ACTIVITY), 0, 0, 0, 0, 0, 0, 0, 0}; // Global Fax Service Activity
  22. CFaxCriticalSection g_CsActivity; // Controls access to g_ServerActivity;
  23. CFaxCriticalSection g_CsPerfCounters;
  24. CFaxCriticalSection g_csUniqueQueueFile;
  25. CFaxCriticalSection g_CsServiceThreads; // Controls service global threads count
  26. LONG g_lServiceThreadsCount; // Service threads count
  27. HANDLE g_hThreadCountEvent; // This Event is set when the service threads count is 0.
  28. BOOL g_bServiceIsDown = FALSE; // This is set to TRUE by FaxEndSvc()
  29. DWORD g_dwOutboundSeconds;
  30. DWORD g_dwInboundSeconds;
  31. DWORD g_dwTotalSeconds;
  32. HANDLE g_hFaxPerfCountersMap;
  33. PFAX_PERF_COUNTERS g_pFaxPerfCounters;
  34. #ifdef DBG
  35. HANDLE g_hCritSecLogFile;
  36. LIST_ENTRY g_CritSecListHead;
  37. CFaxCriticalSection g_CsCritSecList;
  38. #endif
  39. #define PROGRESS_RESOLUTION 1000 * 10 // 10 seconds
  40. #define STARTUP_SHUTDOWN_TIMEOUT 1000 * 30 // 30 seconds per FSP
  41. HANDLE g_hRPCListeningThread;
  42. WCHAR g_wszFaxQueueDir[MAX_PATH];
  43. DWORD
  44. FaxInitThread(
  45. PREG_FAX_SERVICE FaxReg
  46. );
  47. DWORD WINAPI FaxRPCListeningThread(
  48. LPVOID pvUnused
  49. );
  50. VOID
  51. PrintBanner(
  52. VOID
  53. )
  54. {
  55. #ifdef DBG
  56. DWORD LinkTime;
  57. TCHAR FileName[MAX_PATH]={0};
  58. DWORD VerSize;
  59. LPVOID VerInfo;
  60. VS_FIXEDFILEINFO *pvs;
  61. DWORD Tmp;
  62. LPTSTR TimeString;
  63. LinkTime = GetTimestampForLoadedLibrary( GetModuleHandle(NULL) );
  64. TimeString = _tctime( (time_t*) &LinkTime );
  65. TimeString[_tcslen(TimeString)-1] = 0;
  66. if (!GetModuleFileName( NULL, FileName, ARR_SIZE(FileName)-1 )) {
  67. return;
  68. }
  69. VerSize = GetFileVersionInfoSize( FileName, &Tmp );
  70. if (!VerSize) {
  71. return;
  72. }
  73. VerInfo = MemAlloc( VerSize );
  74. if (!VerInfo) {
  75. return;
  76. }
  77. if (!GetFileVersionInfo( FileName, 0, VerSize, VerInfo )) {
  78. return;
  79. }
  80. if (!VerQueryValue( VerInfo, TEXT("\\"), (LPVOID *)&pvs, (UINT *)&VerSize )) {
  81. MemFree( VerInfo );
  82. return;
  83. }
  84. DebugPrint(( TEXT("------------------------------------------------------------") ));
  85. DebugPrint(( TEXT("Windows XP Fax Server") ));
  86. DebugPrint(( TEXT("Copyright (C) Microsoft Corp 1996. All rights reserved.") ));
  87. DebugPrint(( TEXT("Built: %s"), TimeString ));
  88. DebugPrint(( TEXT("Version: %d.%d:%d.%d"),
  89. HIWORD(pvs->dwFileVersionMS), LOWORD(pvs->dwFileVersionMS),
  90. HIWORD(pvs->dwFileVersionLS), LOWORD(pvs->dwFileVersionLS)
  91. ));
  92. DebugPrint(( TEXT("------------------------------------------------------------") ));
  93. MemFree( VerInfo );
  94. #endif //DBG
  95. }
  96. /*
  97. * InitializeDefaultLogCategoryNames
  98. *
  99. * Purpose:
  100. * This function initializes the Name members of DefaultCategories,
  101. * the global array of type FAX_LOG_CATEGORY.
  102. *
  103. * Arguments:
  104. * DefaultCategories - points to an array of FAX_LOG_CATEGORY structures.
  105. * DefaultCategoryCount - the number of entries in DefaultCategories
  106. *
  107. *
  108. * Returns:
  109. * None.
  110. *
  111. */
  112. VOID InitializeDefaultLogCategoryNames( PFAX_LOG_CATEGORY DefaultCategories,
  113. int DefaultCategoryCount )
  114. {
  115. int xCategoryIndex;
  116. int xStringResourceId;
  117. LPTSTR ptszCategoryName;
  118. for ( xCategoryIndex = 0; xCategoryIndex < DefaultCategoryCount; xCategoryIndex++ )
  119. {
  120. xStringResourceId = IDS_FAX_LOG_CATEGORY_INIT_TERM + xCategoryIndex;
  121. ptszCategoryName = GetString( xStringResourceId );
  122. if ( ptszCategoryName != (LPTSTR) NULL )
  123. {
  124. DefaultCategories[xCategoryIndex].Name = ptszCategoryName;
  125. }
  126. else
  127. {
  128. DefaultCategories[xCategoryIndex].Name = TEXT("");
  129. }
  130. }
  131. return;
  132. }
  133. DWORD
  134. LoadConfiguration (
  135. PREG_FAX_SERVICE *ppFaxReg
  136. )
  137. /*++
  138. Routine name : LoadConfiguration
  139. Routine description:
  140. Loads the configuration of the Fax Server from the registry
  141. Author:
  142. Eran Yariv (EranY), Nov, 1999
  143. Arguments:
  144. ppFaxReg [out] - Pointer to fax registry structure to recieve
  145. Return Value:
  146. Standard Win32 error code
  147. --*/
  148. {
  149. DWORD dwRes = ERROR_SUCCESS;
  150. DEBUG_FUNCTION_NAME(TEXT("LoadConfiguration"));
  151. EnterCriticalSection (&g_CsConfig);
  152. //
  153. // Get general settings (including outbox config)
  154. //
  155. dwRes = GetFaxRegistry(ppFaxReg);
  156. if (ERROR_SUCCESS != dwRes)
  157. {
  158. DebugPrintEx(
  159. DEBUG_ERR,
  160. TEXT("GetFaxRegistry() failed (ec: %ld)"),
  161. dwRes);
  162. FaxLog(
  163. FAXLOG_CATEGORY_INIT,
  164. FAXLOG_LEVEL_MIN,
  165. 1,
  166. MSG_BAD_CONFIGURATION,
  167. DWORD2DECIMAL(dwRes)
  168. );
  169. goto exit;
  170. }
  171. g_dwLastUniqueLineId = (*ppFaxReg)->dwLastUniqueLineId;
  172. g_dwMaxLineCloseTime = ((*ppFaxReg)->dwMaxLineCloseTime) ? (*ppFaxReg)->dwMaxLineCloseTime : 60 * 5; //Set default value to 5 minutes
  173. g_dwRecipientsLimit = (*ppFaxReg)->dwRecipientsLimit;
  174. g_dwAllowRemote = (*ppFaxReg)->dwAllowRemote;
  175. //
  176. // Get SMTP configuration
  177. //
  178. dwRes = LoadReceiptsSettings (&g_ReceiptsConfig);
  179. if (ERROR_SUCCESS != dwRes)
  180. {
  181. DebugPrintEx(
  182. DEBUG_ERR,
  183. TEXT("LoadReceiptsSettings() failed (ec: %ld)"),
  184. dwRes);
  185. FaxLog(
  186. FAXLOG_CATEGORY_INIT,
  187. FAXLOG_LEVEL_MIN,
  188. 1,
  189. MSG_BAD_RECEIPTS_CONFIGURATION,
  190. DWORD2DECIMAL(dwRes)
  191. );
  192. goto exit;
  193. }
  194. //
  195. // Get inbox archive configuration
  196. //
  197. dwRes = LoadArchiveSettings (FAX_MESSAGE_FOLDER_INBOX,
  198. &g_ArchivesConfig[FAX_MESSAGE_FOLDER_INBOX]);
  199. if (ERROR_SUCCESS != dwRes)
  200. {
  201. DebugPrintEx(
  202. DEBUG_ERR,
  203. TEXT("LoadArchiveSettings(FAX_MESSAGE_FOLDER_INBOX) failed (ec: %ld)"),
  204. dwRes);
  205. FaxLog(
  206. FAXLOG_CATEGORY_INIT,
  207. FAXLOG_LEVEL_MIN,
  208. 1,
  209. MSG_BAD_ARCHIVE_CONFIGURATION,
  210. DWORD2DECIMAL(dwRes)
  211. );
  212. goto exit;
  213. }
  214. //
  215. // Get SentItems archive configuration
  216. //
  217. dwRes = LoadArchiveSettings (FAX_MESSAGE_FOLDER_SENTITEMS,
  218. &g_ArchivesConfig[FAX_MESSAGE_FOLDER_SENTITEMS]);
  219. if (ERROR_SUCCESS != dwRes)
  220. {
  221. DebugPrintEx(
  222. DEBUG_ERR,
  223. TEXT("LoadArchiveSettings(FAX_MESSAGE_FOLDER_SENTITEMS) failed (ec: %ld)"),
  224. dwRes);
  225. FaxLog(
  226. FAXLOG_CATEGORY_INIT,
  227. FAXLOG_LEVEL_MIN,
  228. 1,
  229. MSG_BAD_ARCHIVE_CONFIGURATION,
  230. DWORD2DECIMAL(dwRes)
  231. );
  232. goto exit;
  233. }
  234. //
  235. // Get activity logging configuration
  236. //
  237. dwRes = LoadActivityLoggingSettings (&g_ActivityLoggingConfig);
  238. if (ERROR_SUCCESS != dwRes)
  239. {
  240. DebugPrintEx(
  241. DEBUG_ERR,
  242. TEXT("LoadActivityLoggingSettings() failed (ec: %ld)"),
  243. dwRes);
  244. FaxLog(
  245. FAXLOG_CATEGORY_INIT,
  246. FAXLOG_LEVEL_MIN,
  247. 1,
  248. MSG_BAD_ACTIVITY_LOGGING_CONFIGURATION,
  249. DWORD2DECIMAL(dwRes)
  250. );
  251. goto exit;
  252. }
  253. dwRes = ReadManualAnswerDeviceId (&g_dwManualAnswerDeviceId);
  254. if (ERROR_SUCCESS != dwRes)
  255. {
  256. //
  257. // Non-critical
  258. //
  259. g_dwManualAnswerDeviceId = 0;
  260. DebugPrintEx(
  261. DEBUG_ERR,
  262. TEXT("ReadManualAnswerDeviceId() failed (ec: %ld)"),
  263. dwRes);
  264. }
  265. exit:
  266. LeaveCriticalSection (&g_CsConfig);
  267. return dwRes;
  268. } // LoadConfiguration
  269. DWORD
  270. ServiceStart(
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. Starts the RPC server. This implementation listens on
  276. a list of protocols. Hopefully this list is inclusive
  277. enough to handle RPC requests from most clients.
  278. Arguments:
  279. None.
  280. .
  281. Return Value:
  282. Return code. Return zero for success, all other
  283. values indicate errors.
  284. --*/
  285. {
  286. DWORD Rval;
  287. DWORD ThreadId;
  288. DWORD dwExitCode;
  289. HANDLE hThread = NULL;
  290. SECURITY_ATTRIBUTES SA;
  291. TCHAR* ptstrSD = NULL; // SDDL string
  292. ULONG uSDSize=0;
  293. PREG_FAX_SERVICE FaxReg = NULL;
  294. RPC_BINDING_VECTOR *BindingVector = NULL;
  295. BOOL bLogEvent = TRUE;
  296. BOOL bRet = TRUE;
  297. #if DBG
  298. HKEY hKeyLog;
  299. LPTSTR LogFileName;
  300. #endif
  301. DEBUG_FUNCTION_NAME(TEXT("ServiceStart"));
  302. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  303. #ifdef DBG
  304. hKeyLog = OpenRegistryKey(HKEY_LOCAL_MACHINE,REGKEY_SOFTWARE,FALSE,KEY_READ);
  305. if (hKeyLog)
  306. {
  307. LogFileName = GetRegistryString(hKeyLog,TEXT("CritSecLogFile"),TEXT("NOFILE"));
  308. if (_wcsicmp(LogFileName, TEXT("NOFILE")) != 0 )
  309. {
  310. g_hCritSecLogFile = SafeCreateFile(LogFileName,
  311. GENERIC_READ | GENERIC_WRITE,
  312. FILE_SHARE_READ,
  313. NULL,
  314. OPEN_ALWAYS,
  315. FILE_ATTRIBUTE_ARCHIVE,
  316. NULL);
  317. if (g_hCritSecLogFile != INVALID_HANDLE_VALUE)
  318. {
  319. char AnsiBuffer[300];
  320. DWORD BytesWritten;
  321. wsprintfA(AnsiBuffer,
  322. "Initializing log at %d\r\nTickCount\tObject\tObject Name\tCritical Section API\tFile\tLine\t(Time Held)\r\n",
  323. GetTickCount()
  324. );
  325. SetFilePointer(g_hCritSecLogFile,0,0,FILE_END);
  326. WriteFile(g_hCritSecLogFile,(LPBYTE)AnsiBuffer,strlen(AnsiBuffer) * sizeof(CHAR),&BytesWritten,NULL);
  327. }
  328. }
  329. MemFree( LogFileName );
  330. RegCloseKey( hKeyLog );
  331. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  332. }
  333. #endif
  334. PrintBanner();
  335. if (!IsFaxShared())
  336. {
  337. //
  338. // Make sure, that on non-shared SKUs, the fax printer is never shared.
  339. //
  340. BOOL bLocalFaxPrinterShared;
  341. DWORD dwRes;
  342. dwRes = IsLocalFaxPrinterShared (&bLocalFaxPrinterShared);
  343. if (ERROR_SUCCESS == dwRes)
  344. {
  345. if (bLocalFaxPrinterShared)
  346. {
  347. DebugPrintEx(
  348. DEBUG_MSG,
  349. TEXT("Local fax printer is shared in desktop SKU - fixing that now."));
  350. dwRes = SetLocalFaxPrinterSharing (FALSE);
  351. if (ERROR_SUCCESS == dwRes)
  352. {
  353. DebugPrintEx(
  354. DEBUG_MSG,
  355. TEXT("Local fax printer is no longer shared"));
  356. }
  357. else
  358. {
  359. DebugPrintEx(
  360. DEBUG_ERR,
  361. TEXT("SetLocalFaxPrinterSharing() failed: err = %d"),
  362. dwRes);
  363. }
  364. }
  365. }
  366. else
  367. {
  368. DebugPrintEx(
  369. DEBUG_ERR,
  370. TEXT("IsLocalFaxPrinterShared() failed: err = %d"),
  371. dwRes);
  372. }
  373. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  374. }
  375. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  376. //
  377. // initialize the event log so we can log events
  378. //
  379. if (!InitializeEventLog( &FaxReg))
  380. {
  381. Rval = GetLastError();
  382. Assert (ERROR_SUCCESS != Rval);
  383. DebugPrintEx(
  384. DEBUG_ERR,
  385. TEXT("InitializeEventLog() failed: err = %d"),
  386. Rval);
  387. return Rval;
  388. }
  389. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  390. //
  391. // Enable SeAuditPrivilege
  392. //
  393. Rval = EnableProcessPrivilege(SE_AUDIT_NAME);
  394. if (ERROR_SUCCESS != Rval)
  395. {
  396. //
  397. // Failed to enable SeAuditPrivilege
  398. //
  399. DebugPrintEx(
  400. DEBUG_ERR,
  401. TEXT("EnableProcessPrivilege() failed: err = %d"),
  402. Rval);
  403. goto Error;
  404. }
  405. //
  406. // initialize the string table
  407. //
  408. if (!InitializeStringTable())
  409. {
  410. Rval = GetLastError();
  411. DebugPrintEx(
  412. DEBUG_ERR,
  413. TEXT("InitializeStringTable() failed: err = %d"),
  414. Rval);
  415. goto Error;
  416. }
  417. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  418. //
  419. // Create an event to signal all service threads are terminated.
  420. // The event is set/reset by the service threads reference count mechanism.
  421. // (IncreaseServiceThreadsCount DecreaseServiceThreadsCount AND CreateThreadAndRefCount).
  422. // The event must be created after g_CsServiceThreads is initialized because it is used also to mark g_CsServiceThreads is initialized.
  423. //
  424. g_hThreadCountEvent = CreateEvent(
  425. NULL, // SD
  426. TRUE, // reset type - Manual
  427. TRUE, // initial state - Signaled. We didn't create any service threads yet. The event is reset when the first thread is created.
  428. NULL // object name
  429. );
  430. if (NULL == g_hThreadCountEvent)
  431. {
  432. Rval = GetLastError();
  433. DebugPrintEx(
  434. DEBUG_ERR,
  435. TEXT("CreateEvent (g_hThreadCountEvent) failed (ec: %ld)"),
  436. Rval);
  437. goto Error;
  438. }
  439. //
  440. // Create the perf counters.
  441. // we must setup a security descriptor so other account (and other desktops) may access
  442. // the shared memory region
  443. //
  444. ptstrSD = TEXT("O:NS") // owner Network Service
  445. TEXT("G:NS") // group Network Service
  446. TEXT("D:") // DACL
  447. TEXT("(A;;GA;;;NS)") // give Network Service full access
  448. TEXT("(A;;0x0004;;;AU)");// give Authenticated users FILE_MAP_READ access
  449. SA.nLength = sizeof(SECURITY_ATTRIBUTES);
  450. SA.bInheritHandle = FALSE;
  451. bRet = ConvertStringSecurityDescriptorToSecurityDescriptor (
  452. ptstrSD,
  453. SDDL_REVISION_1,
  454. &(SA.lpSecurityDescriptor),
  455. &uSDSize);
  456. if (!bRet)
  457. {
  458. Rval = GetLastError();
  459. DebugPrintEx(
  460. DEBUG_ERR,
  461. TEXT("ConvertStringSecurityDescriptorToSecurityDescriptor() failed. (ec: %lu)"),
  462. Rval);
  463. goto Error;
  464. }
  465. g_hFaxPerfCountersMap = CreateFileMapping(
  466. INVALID_HANDLE_VALUE,
  467. &SA,
  468. PAGE_READWRITE | SEC_COMMIT,
  469. 0,
  470. sizeof(FAX_PERF_COUNTERS),
  471. FAXPERF_SHARED_MEMORY
  472. );
  473. if (NULL == g_hFaxPerfCountersMap)
  474. {
  475. Rval = GetLastError();
  476. DebugPrintEx(
  477. DEBUG_ERR,
  478. TEXT("CreateFileMapping() failed. (ec: %ld)"),
  479. Rval);
  480. if (ERROR_ACCESS_DENIED == Rval)
  481. {
  482. //
  483. // A malicious application holds the performance counter
  484. //
  485. FaxLog(
  486. FAXLOG_CATEGORY_INIT,
  487. FAXLOG_LEVEL_MIN,
  488. 0,
  489. MSG_FAX_UNDER_ATTACK
  490. );
  491. bLogEvent = FALSE;
  492. }
  493. LocalFree(SA.lpSecurityDescriptor);
  494. goto Error;
  495. }
  496. LocalFree(SA.lpSecurityDescriptor);
  497. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  498. g_pFaxPerfCounters = (PFAX_PERF_COUNTERS) MapViewOfFile(
  499. g_hFaxPerfCountersMap,
  500. FILE_MAP_WRITE,
  501. 0,
  502. 0,
  503. 0
  504. );
  505. if (NULL == g_pFaxPerfCounters)
  506. {
  507. Rval = GetLastError();
  508. DebugPrintEx(
  509. DEBUG_ERR,
  510. TEXT("MapViewOfFile() failed. (ec: %ld)"),
  511. Rval);
  512. if (ERROR_ACCESS_DENIED == Rval)
  513. {
  514. //
  515. // A malicious application holds the performance counter
  516. //
  517. FaxLog(
  518. FAXLOG_CATEGORY_INIT,
  519. FAXLOG_LEVEL_MIN,
  520. 0,
  521. MSG_FAX_UNDER_ATTACK
  522. );
  523. bLogEvent = FALSE;
  524. }
  525. goto Error;
  526. }
  527. //
  528. // Running totals used in computing total minutes sending and receiving
  529. // If perfmon not running the initial contents of the pages in the file mapping object are zero so this
  530. // globals are also zeroed.
  531. // If perfmon is running the globals will get thier values from the shared memory.
  532. //
  533. EnterCriticalSection( &g_CsPerfCounters );
  534. g_dwOutboundSeconds = g_pFaxPerfCounters->OutboundMinutes * 60;
  535. g_dwTotalSeconds = g_pFaxPerfCounters->TotalMinutes * 60;
  536. g_dwInboundSeconds = g_pFaxPerfCounters->InboundMinutes * 60;
  537. LeaveCriticalSection( &g_CsPerfCounters );
  538. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  539. //
  540. // get the registry data
  541. // the FaxInitThread will free this structure
  542. //
  543. Assert (FaxReg);
  544. Rval = LoadConfiguration (&FaxReg);
  545. if (ERROR_SUCCESS != Rval)
  546. {
  547. //
  548. // Event log issued by LoadConfiguration();
  549. //
  550. bLogEvent = FALSE;
  551. DebugPrintEx(
  552. DEBUG_ERR,
  553. TEXT("LoadConfiguration() failed (ec: %ld)"),
  554. Rval);
  555. goto Error;
  556. }
  557. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  558. if (g_ReceiptsConfig.dwAllowedReceipts & DRT_MSGBOX)
  559. {
  560. //
  561. // Current settings allow message box receipts
  562. //
  563. DWORD dwMessengerStartupType;
  564. if (ERROR_SUCCESS == GetServiceStartupType (NULL, MESSENGER_SERVICE_NAME, &dwMessengerStartupType))
  565. {
  566. if (SERVICE_DISABLED == dwMessengerStartupType)
  567. {
  568. //
  569. // Ooops. The local Messenger service is disabled. We can't send message boxes.
  570. //
  571. g_ReceiptsConfig.dwAllowedReceipts &= ~DRT_MSGBOX;
  572. DebugPrintEx(
  573. DEBUG_WRN,
  574. TEXT("The local Messenger service is disabled. We can't send message boxes."));
  575. FaxLog( FAXLOG_CATEGORY_INIT,
  576. FAXLOG_LEVEL_MIN,
  577. 0,
  578. MSG_FAX_MESSENGER_SVC_DISABLED_WRN);
  579. }
  580. }
  581. }
  582. if (!InitializeFaxQueue(FaxReg))
  583. {
  584. Rval = GetLastError();
  585. DebugPrintEx(
  586. DEBUG_ERR,
  587. TEXT("InitFaxDirectories failed, Queue folder is unavailable (ec = %lu).")
  588. TEXT(" Job submission and receive are disabled."),
  589. Rval);
  590. FaxLog(
  591. FAXLOG_CATEGORY_INIT,
  592. FAXLOG_LEVEL_MIN,
  593. 2,
  594. MSG_FAX_QUEUE_FOLDER_ERR,
  595. g_wszFaxQueueDir,
  596. DWORD2DECIMAL(Rval)
  597. );
  598. //
  599. // disable job submission and receive
  600. //
  601. EnterCriticalSection (&g_CsConfig);
  602. g_dwQueueState |= FAX_INCOMING_BLOCKED | FAX_OUTBOX_BLOCKED | FAX_OUTBOX_PAUSED;
  603. LeaveCriticalSection (&g_CsConfig);
  604. }
  605. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  606. //
  607. // initialize activity logging
  608. //
  609. Rval = InitializeLogging();
  610. if (ERROR_SUCCESS != Rval)
  611. {
  612. DebugPrintEx(
  613. DEBUG_ERR,
  614. TEXT("InitializeLogging failed, (ec = %lu).")
  615. TEXT(" Activity logging is disabled."),
  616. Rval);
  617. FaxLog(
  618. FAXLOG_CATEGORY_INIT,
  619. FAXLOG_LEVEL_MIN,
  620. 2,
  621. MSG_FAX_ACTIVITY_LOG_FOLDER_ERR,
  622. g_ActivityLoggingConfig.lptstrDBPath,
  623. DWORD2DECIMAL(Rval)
  624. );
  625. //
  626. // Disable activity logging
  627. //
  628. EnterCriticalSection (&g_CsInboundActivityLogging);
  629. EnterCriticalSection (&g_CsOutboundActivityLogging);
  630. g_ActivityLoggingConfig.bLogOutgoing = FALSE;
  631. g_ActivityLoggingConfig.bLogIncoming = FALSE;
  632. LeaveCriticalSection (&g_CsOutboundActivityLogging);
  633. LeaveCriticalSection (&g_CsInboundActivityLogging);
  634. }
  635. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  636. //
  637. // Initialize events mechanism
  638. //
  639. Rval = InitializeServerEvents();
  640. if (ERROR_SUCCESS != Rval)
  641. {
  642. DebugPrintEx(
  643. DEBUG_ERR,
  644. TEXT("InitializeServerEvents failed (ec: %ld)"),
  645. Rval);
  646. FaxLog( FAXLOG_CATEGORY_INIT,
  647. FAXLOG_LEVEL_MIN,
  648. 1,
  649. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  650. DWORD2DECIMAL(Rval)
  651. );
  652. bLogEvent = FALSE;
  653. goto Error;
  654. }
  655. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  656. //
  657. // Initilaize the extension configuration notification map
  658. //
  659. Rval = g_pNotificationMap->Init ();
  660. if (ERROR_SUCCESS != Rval)
  661. {
  662. DebugPrintEx(
  663. DEBUG_ERR,
  664. TEXT("CNotificationMap.Init() failed (ec: %ld)"),
  665. Rval);
  666. goto Error;
  667. }
  668. ReportServiceStatus( SERVICE_START_PENDING, 0, 60000 );
  669. //
  670. // Create a thread to do the rest of the initialization.
  671. // See FaxInitThread comments for details.
  672. //
  673. hThread = CreateThread(
  674. NULL,
  675. 0,
  676. (LPTHREAD_START_ROUTINE) FaxInitThread,
  677. LPVOID(FaxReg),
  678. 0,
  679. &ThreadId
  680. );
  681. if (!hThread)
  682. {
  683. DebugPrintEx( DEBUG_ERR,
  684. _T("Failed to create FaxInitThread (CreateThread)(ec: %ld)."),
  685. Rval = GetLastError());
  686. bLogEvent = FALSE;
  687. goto Error;
  688. }
  689. //
  690. // Wait for FaxInitThread to terminate while report service status as PENDING to SCM
  691. //
  692. ReportServiceStatus( SERVICE_START_PENDING, 0, 2*PROGRESS_RESOLUTION );
  693. do
  694. {
  695. Rval = WaitForSingleObject(hThread,PROGRESS_RESOLUTION);
  696. if (Rval==WAIT_OBJECT_0)
  697. {
  698. bRet = GetExitCodeThread(hThread,&dwExitCode);
  699. if (!bRet)
  700. {
  701. DebugPrintEx( DEBUG_ERR,
  702. _T("GetExitCodeThread Failed (ec: %ld)."),
  703. Rval = GetLastError());
  704. bLogEvent = FALSE;
  705. CloseHandle(hThread);
  706. goto Error;
  707. }
  708. // FaxInitThread finished successfully
  709. Rval = dwExitCode;
  710. break;
  711. }
  712. else if (Rval==WAIT_TIMEOUT)
  713. {
  714. DebugPrintEx(DEBUG_MSG,_T("Waiting for FaxInitThread to terminate.") );
  715. ReportServiceStatus( SERVICE_START_PENDING, 0, 3*PROGRESS_RESOLUTION );
  716. }
  717. else
  718. {
  719. // WAIT_FAILED
  720. DebugPrintEx( DEBUG_ERR,
  721. _T("WaitForSingleObject Failed (ec: %ld)."),
  722. Rval = GetLastError());
  723. bLogEvent = FALSE;
  724. CloseHandle(hThread);
  725. goto Error;
  726. }
  727. }
  728. while (Rval==WAIT_TIMEOUT);
  729. CloseHandle(hThread);
  730. if (ERROR_SUCCESS != Rval)
  731. {
  732. //
  733. // FaxInitThread failed
  734. //
  735. DebugPrintEx( DEBUG_ERR,
  736. _T("FaxInitThread Failed (ec: %ld)."),
  737. Rval);
  738. bLogEvent = FALSE;
  739. goto Error;
  740. }
  741. FaxLog(
  742. FAXLOG_CATEGORY_INIT,
  743. FAXLOG_LEVEL_MAX,
  744. 0,
  745. MSG_SERVICE_STARTED
  746. );
  747. //
  748. // Get RPC going
  749. //
  750. Rval = StartFaxRpcServer( FAX_RPC_ENDPOINTW, fax_ServerIfHandle );
  751. if (Rval != 0 )
  752. {
  753. DebugPrintEx(
  754. DEBUG_ERR,
  755. TEXT("StartFaxRpcServer() failed (ec: %ld)"),
  756. Rval);
  757. goto Error;
  758. }
  759. //
  760. // Create a thread to wait for all RPC calls to terminate.
  761. // This thread Performs the wait operation associated with RpcServerListen only, NOT the listening.
  762. //
  763. g_hRPCListeningThread = CreateThread(
  764. NULL,
  765. 0,
  766. (LPTHREAD_START_ROUTINE) FaxRPCListeningThread,
  767. NULL,
  768. 0,
  769. &ThreadId);
  770. if (!g_hRPCListeningThread)
  771. {
  772. DebugPrintEx( DEBUG_ERR,
  773. _T("Failed to create FaxRPCListeningThread (CreateThread)(ec: %ld)."),
  774. Rval = GetLastError());
  775. goto Error;
  776. }
  777. return ERROR_SUCCESS;
  778. Error:
  779. //
  780. // the fax server did not initialize correctly
  781. //
  782. Assert (ERROR_SUCCESS != Rval);
  783. if (TRUE == bLogEvent)
  784. {
  785. FaxLog(
  786. FAXLOG_CATEGORY_INIT,
  787. FAXLOG_LEVEL_MIN,
  788. 1,
  789. MSG_SERVICE_INIT_FAILED_INTERNAL,
  790. DWORD2DECIMAL(Rval)
  791. );
  792. }
  793. return Rval;
  794. }
  795. BOOL
  796. NotifyServiceThreadsToTerminate(
  797. VOID
  798. )
  799. /*++
  800. Routine name : NotifyServiceThreadsToTerminate
  801. Routine description:
  802. Notifies all service threads except TapiWorkerThreads that do not wait on g_hServiceShutDownEvent,
  803. that the service is going down.
  804. Author:
  805. Oded Sacher (OdedS), Dec, 2000
  806. Arguments:
  807. VOID [ ]
  808. Return Value:
  809. BOOL
  810. --*/
  811. {
  812. BOOL rVal = TRUE;
  813. DEBUG_FUNCTION_NAME(TEXT("NotifyServiceThreadsToTerminate"));
  814. //
  815. // Notify FaxArchiveQuotaWarningThread &
  816. // FaxArchiveQuotaAutoDeleteThread &
  817. // JobQueueThread
  818. //
  819. if (!SetEvent(g_hServiceShutDownEvent))
  820. {
  821. DebugPrintEx(
  822. DEBUG_ERR,
  823. TEXT("SetEvent failed (g_hServiceShutDownEvent) (ec = %ld)"),
  824. GetLastError());
  825. rVal = FALSE;
  826. }
  827. //
  828. // Notify FaxSendEventThread
  829. //
  830. if (NULL != g_hSendEventsCompPort)
  831. {
  832. if (!PostQueuedCompletionStatus( g_hSendEventsCompPort,
  833. 0,
  834. SERVICE_SHUT_DOWN_KEY,
  835. (LPOVERLAPPED) NULL))
  836. {
  837. DebugPrintEx(
  838. DEBUG_ERR,
  839. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY - g_hSendEventsCompPort). (ec: %ld)"),
  840. GetLastError());
  841. rVal = FALSE;
  842. }
  843. }
  844. //
  845. // Notify FaxDispatchEventThread
  846. //
  847. if (NULL != g_hDispatchEventsCompPort)
  848. {
  849. if (!PostQueuedCompletionStatus( g_hDispatchEventsCompPort,
  850. 0,
  851. SERVICE_SHUT_DOWN_KEY,
  852. (LPOVERLAPPED) NULL))
  853. {
  854. DebugPrintEx(
  855. DEBUG_ERR,
  856. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY - g_hDispatchEventsCompPort). (ec: %ld)"),
  857. GetLastError());
  858. rVal = FALSE;
  859. }
  860. }
  861. //
  862. // Notify CNotificationMap::ExtNotificationThread
  863. //
  864. if (NULL != g_pNotificationMap->m_hCompletionPort)
  865. {
  866. if (!PostQueuedCompletionStatus( g_pNotificationMap->m_hCompletionPort,
  867. 0,
  868. SERVICE_SHUT_DOWN_KEY,
  869. (LPOVERLAPPED) NULL))
  870. {
  871. DebugPrintEx(
  872. DEBUG_ERR,
  873. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY - ExtNotificationThread). (ec: %ld)"),
  874. GetLastError());
  875. rVal = FALSE;
  876. }
  877. }
  878. //
  879. // Notify FaxStatusThread
  880. //
  881. if (NULL != g_StatusCompletionPortHandle)
  882. {
  883. if (!PostQueuedCompletionStatus( g_StatusCompletionPortHandle,
  884. 0,
  885. SERVICE_SHUT_DOWN_KEY,
  886. (LPOVERLAPPED) NULL))
  887. {
  888. DebugPrintEx(
  889. DEBUG_ERR,
  890. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY - FaxStatusThread). (ec: %ld)"),
  891. GetLastError());
  892. rVal = FALSE;
  893. }
  894. }
  895. return rVal;
  896. }
  897. BOOL
  898. StopFaxServiceProviders()
  899. {
  900. DWORD ThreadId;
  901. DWORD dwExitCode;
  902. BOOL bRet = TRUE;
  903. HANDLE hThread;
  904. DWORD Rval;
  905. DEBUG_FUNCTION_NAME(TEXT("StopFaxServiceProviders"));
  906. //
  907. // Call FaxDevShutDown() for all loaded FSPs
  908. //
  909. hThread = CreateThread( NULL,
  910. 0,
  911. (LPTHREAD_START_ROUTINE) ShutdownDeviceProviders,
  912. (LPVOID)0,
  913. 0,
  914. &ThreadId
  915. );
  916. if (NULL == hThread)
  917. {
  918. DebugPrintEx( DEBUG_ERR,
  919. _T("Failed to create ShutdownDeviceProviders (ec: %ld)."),
  920. GetLastError());
  921. bRet = FALSE;
  922. }
  923. else
  924. {
  925. //
  926. // Wait for FaxDevShutDown to terminate
  927. //
  928. ReportServiceStatus( SERVICE_STOP_PENDING, 0, 2*PROGRESS_RESOLUTION );
  929. do
  930. {
  931. Rval = WaitForSingleObject(hThread, PROGRESS_RESOLUTION);
  932. if (Rval == WAIT_OBJECT_0)
  933. {
  934. bRet = GetExitCodeThread(hThread, &dwExitCode);
  935. if (!bRet)
  936. {
  937. DebugPrintEx( DEBUG_ERR,
  938. _T("GetExitCodeThread Failed (ec: %ld)."),
  939. GetLastError());
  940. bRet = FALSE;
  941. break;
  942. }
  943. // ShutdownDeviceProviders finished successfully
  944. bRet = (dwExitCode == ERROR_SUCCESS);
  945. SetLastError(dwExitCode);
  946. break;
  947. }
  948. else if (Rval == WAIT_TIMEOUT)
  949. {
  950. DebugPrintEx(DEBUG_MSG,_T("Waiting for ShutdownDeviceProviders to terminate"));
  951. ReportServiceStatus( SERVICE_STOP_PENDING, 0, 3*PROGRESS_RESOLUTION );
  952. }
  953. else
  954. {
  955. // WAIT_FAILED
  956. DebugPrintEx( DEBUG_ERR,
  957. _T("WaitForSingleObject Failed (ec: %ld)."),
  958. GetLastError());
  959. bRet = FALSE;
  960. break;
  961. }
  962. }
  963. while (Rval == WAIT_TIMEOUT);
  964. CloseHandle(hThread);
  965. }
  966. return bRet;
  967. } // StopFaxServiceProviders
  968. void
  969. EndFaxSvc(
  970. DWORD SeverityLevel
  971. )
  972. /*++
  973. Routine Description:
  974. End the fax service.
  975. Service Shut down process:
  976. 1) Send a fax-event to legacy RPC clients notifying the service shutdown.
  977. 2) Stop service RPC server. Wait for all RPC threads to terminate and report to SCM.
  978. 3) Set g_ServiceIsDownFlag to indicate that the service is going down
  979. TapiWorkerThread and JobQueueThread become in-active (do not create new jobs).
  980. Setting it is done by synchronization with TapiWorkerThread
  981. and JobQueueThreadand making sure that no new job will be created after the flag is set.
  982. The setting is done using a separate thread while reporting SERVICE_STOP_PENDING to SCM.
  983. 4) Notify server threads (except TapiWorkerThread) to terminate. this is done by setting the
  984. g_hServiceShutDownEvent and posting to completion ports.
  985. 5) Destroy all in progress jobs (sends and recieves) by calling FaxDevAbortOperation.
  986. 6) Wait for all service threads (except TapiWorkerThread) to terminate while reporting
  987. SERVICE_STOP_PENDING to SCM. this can last for few minutes, waiting for FSP to terminate.
  988. 7) Notify TapiWorkerThread to terminate by posting to it's completion post.
  989. 8) Wait for TapiWorkerThread to terminate while reporting SERVICE_STOP_PENDING to SCM.
  990. 9) Stop service providers.
  991. 10) Memory, resources and libraries clean up.
  992. Arguments:
  993. SeverityLevel - Event log severity level.
  994. Return Value:
  995. None.
  996. --*/
  997. {
  998. DWORD Rval;
  999. DEBUG_FUNCTION_NAME(TEXT("EndFaxSvc"));
  1000. Assert (g_hThreadCountEvent);
  1001. //
  1002. // let our legacy RPC clients know we're ending
  1003. //
  1004. if( !CreateFaxEvent(0,FEI_FAXSVC_ENDED,0xFFFFFFFF) )
  1005. {
  1006. DebugPrintEx(
  1007. DEBUG_ERR,
  1008. TEXT("CreateFaxEvent failed. (ec: %ld)"),
  1009. GetLastError());
  1010. }
  1011. //
  1012. // Stop the service RPC server
  1013. //
  1014. Rval = StopFaxRpcServer();
  1015. if (ERROR_SUCCESS != Rval)
  1016. {
  1017. DebugPrintEx(
  1018. DEBUG_ERR,
  1019. TEXT("StopFaxRpcServer failed. (ec: %ld)"),
  1020. Rval);
  1021. }
  1022. //
  1023. // set g_ServiceIsDownFlag to indicate that the service is going down
  1024. // TapiWorkerThread and JobQueueThread become in-active (do not create new jobs)
  1025. //
  1026. if(!SetServiceIsDownFlag())
  1027. {
  1028. DebugPrintEx(
  1029. DEBUG_ERR,
  1030. TEXT("SetServiceIsDownFlagAndReportServiceStatus() failed. (ec=%ld"),
  1031. GetLastError());
  1032. }
  1033. //
  1034. // Notify all service threads (except TapiWorkerThread) that we go down
  1035. //
  1036. if (!NotifyServiceThreadsToTerminate())
  1037. {
  1038. DebugPrintEx(
  1039. DEBUG_ERR,
  1040. TEXT("At least one thread did not get the shut down event, NotifyServiceThreadsToTerminate() failed"));
  1041. }
  1042. //
  1043. // Destroy all in-progress jobs (sends and recieves)
  1044. //
  1045. if (!StopAllInProgressJobs())
  1046. {
  1047. DebugPrintEx(DEBUG_ERR,
  1048. _T("StopAllInProgressJobs failed, not all jobs could be destroyed."));
  1049. }
  1050. //
  1051. // Wait for all threads to terminate
  1052. //
  1053. //
  1054. // Check if threads count mechanism is initialized
  1055. //
  1056. if (NULL != g_hThreadCountEvent)
  1057. {
  1058. if (!WaitAndReportForThreadToTerminate( g_hThreadCountEvent,
  1059. TEXT("Waiting for all threads (except TapiWorkerThread) to terminate.")))
  1060. {
  1061. DebugPrintEx(
  1062. DEBUG_ERR,
  1063. _T("WaitAndReportForThreadToTerminate failed (ec: %ld)"),
  1064. GetLastError());
  1065. }
  1066. ReportServiceStatus( SERVICE_STOP_PENDING, 0, 6*MILLISECONDS_PER_SECOND );
  1067. //
  1068. // EndFaxSvc() waits on g_hThreadCountEvent before returning to FaxServiceMain() that calls FreeServiceGlobals().
  1069. // g_hThreadCountEvent is set inside critical section g_CsServiceThreads only when the service thread count is 0, yet when the event is set,
  1070. // the last thread that set it, is still alive, and is calling LeaveCriritcalSection(g_CsServiceThreads).
  1071. // We must block FreeServiceGlobals() from deleting g_CsServiceThreads, untill the last thread is out of the
  1072. // g_CsServiceThreads critical section.
  1073. //
  1074. EnterCriticalSection (&g_CsServiceThreads);
  1075. //
  1076. // Now we are sure that the last thread is out of g_CsServiceThreads critical section,
  1077. // so we can proceed and delete it.
  1078. //
  1079. LeaveCriticalSection (&g_CsServiceThreads);
  1080. }
  1081. //
  1082. // Notify TapiWorkerThread to go down
  1083. //
  1084. if (NULL != g_TapiCompletionPort)
  1085. {
  1086. if (!PostQueuedCompletionStatus( g_TapiCompletionPort,
  1087. 0,
  1088. SERVICE_SHUT_DOWN_KEY,
  1089. (LPOVERLAPPED) NULL))
  1090. {
  1091. DebugPrintEx(
  1092. DEBUG_ERR,
  1093. TEXT("PostQueuedCompletionStatus failed (SERVICE_SHUT_DOWN_KEY - TapiWorkerThread). (ec: %ld)"),
  1094. GetLastError());
  1095. }
  1096. }
  1097. //
  1098. // Wait for TapiWorkerThread to terminate. This call is blocking! It reports STOP_PENDING to SCM!
  1099. //
  1100. if (NULL != g_hTapiWorkerThread)
  1101. {
  1102. if (!WaitAndReportForThreadToTerminate( g_hTapiWorkerThread,
  1103. TEXT("Waiting for TapiWorkerThread to terminate.")))
  1104. {
  1105. DebugPrintEx(
  1106. DEBUG_ERR,
  1107. _T("WaitAndReportForThreadToTerminate failed (ec: %ld)"),
  1108. GetLastError());
  1109. }
  1110. }
  1111. //
  1112. // Tell all FSP's to shut down. This call is blocking! It reprts STOP_PENDING to SCM!
  1113. //
  1114. if (!StopFaxServiceProviders())
  1115. {
  1116. DebugPrintEx(
  1117. DEBUG_ERR,
  1118. _T("StopFaxServiceProviders failed (ec: %ld)"),
  1119. GetLastError());
  1120. }
  1121. //
  1122. // Free extensions (FSPs and Routing extensions)
  1123. //
  1124. UnloadDeviceProviders();
  1125. FreeRoutingExtensions();
  1126. //
  1127. // Free service global lists
  1128. //
  1129. FreeServiceContextHandles();
  1130. FreeTapiLines();
  1131. //
  1132. // Free the service queue
  1133. //
  1134. FreeServiceQueue();
  1135. FaxLog(
  1136. FAXLOG_CATEGORY_INIT,
  1137. SeverityLevel,
  1138. 0,
  1139. MSG_SERVICE_STOPPED
  1140. );
  1141. } // EndFaxSvc
  1142. BOOL WaitAndReportForThreadToTerminate(HANDLE hThread, LPCTSTR strWaitMessage )
  1143. /*++
  1144. Routine Description:
  1145. Wait for thread to terminate using it's handle.
  1146. During the wait this function reports to SCM SERVICE_STOP_PENDING
  1147. Arguments:
  1148. hThread - thread handle
  1149. Return Value:
  1150. TRUE on success.
  1151. FALSE - on failure, To get extended error information, call GetLastError()
  1152. --*/
  1153. {
  1154. BOOL bRval=TRUE;
  1155. DWORD rVal;
  1156. DWORD ec = ERROR_SUCCESS;
  1157. DEBUG_FUNCTION_NAME(TEXT("WaitAndReportForThreadToTerminate"));
  1158. if (NULL == hThread)
  1159. {
  1160. //
  1161. // No thread to wait for
  1162. //
  1163. DebugPrintEx(DEBUG_MSG,_T("No thread to wait for . (NULL == hThread)") );
  1164. return TRUE;
  1165. }
  1166. //
  1167. // Wait for SetServiceIsDownFlagThread to terminate while report service status as PENDING to SCM
  1168. //
  1169. ReportServiceStatus( SERVICE_STOP_PENDING, 0, 2*PROGRESS_RESOLUTION );
  1170. do
  1171. {
  1172. rVal = WaitForSingleObject(hThread,PROGRESS_RESOLUTION);
  1173. if (rVal == WAIT_OBJECT_0)
  1174. {
  1175. // ok thread terminate
  1176. DebugPrintEx(DEBUG_MSG,_T("Wait terminated successfully.") );
  1177. }
  1178. else
  1179. if (rVal == WAIT_TIMEOUT)
  1180. {
  1181. DebugPrintEx(DEBUG_MSG,strWaitMessage);
  1182. ReportServiceStatus( SERVICE_START_PENDING, 0, 2*PROGRESS_RESOLUTION );
  1183. }
  1184. else
  1185. {
  1186. // WAIT_FAILED
  1187. Assert(WAIT_FAILED == rVal);
  1188. ec = GetLastError();
  1189. DebugPrintEx( DEBUG_ERR,
  1190. _T("WaitForSingleObject Failed (ec: %ld)."),
  1191. ec);
  1192. goto Exit;
  1193. }
  1194. }
  1195. while (rVal==WAIT_TIMEOUT);
  1196. Exit:
  1197. if (ERROR_SUCCESS != ec)
  1198. {
  1199. SetLastError(ec);
  1200. }
  1201. return (ERROR_SUCCESS == ec);
  1202. }
  1203. BOOL StopAllInProgressJobs(VOID)
  1204. /*++
  1205. Routine Description:
  1206. Call this routine to abort all in-progress jobs.
  1207. This routine is called during service shutdown.
  1208. to insure that no other job will be created during or after calling this
  1209. function you must make TapiWorkerThread and JobQueueThread inactive using g_ServiceIsDownFlag.
  1210. You must *NOT* kill TapiWorkerThread for it must still send events to FSPs.
  1211. Arguments:
  1212. None.
  1213. Return Value:
  1214. TRUE
  1215. on success.
  1216. FALSE
  1217. at least one job couldn't be aborted
  1218. --*/
  1219. {
  1220. BOOL bRval=TRUE;
  1221. DEBUG_FUNCTION_NAME(TEXT("StopAllInProgressJobs"));
  1222. //
  1223. // iterate through the in-proggress jobs and destroy them
  1224. //
  1225. EnterCriticalSectionJobAndQueue;
  1226. PLIST_ENTRY Next = g_QueueListHead.Flink;
  1227. while ((ULONG_PTR)Next != (ULONG_PTR)&g_QueueListHead)
  1228. {
  1229. PJOB_QUEUE JobQueue = CONTAINING_RECORD( Next, JOB_QUEUE, ListEntry );
  1230. Next = JobQueue->ListEntry.Flink;
  1231. if (NULL != JobQueue->JobEntry &&
  1232. TRUE == JobQueue->JobEntry->bFSPJobInProgress &&
  1233. FALSE == JobQueue->JobEntry->Aborting)
  1234. {
  1235. DebugPrintEx(DEBUG_MSG,
  1236. _T("[Job: %ld] Aborting in progress job due to service shut down."),
  1237. JobQueue->JobId);
  1238. //
  1239. // abort each job
  1240. //
  1241. __try
  1242. {
  1243. if (!JobQueue->JobEntry->LineInfo->Provider->FaxDevAbortOperation((HANDLE)JobQueue->JobEntry->InstanceData))
  1244. {
  1245. DebugPrintEx(DEBUG_ERR,
  1246. _T("[Job: %ld] Trying to abort in progress job failed."),
  1247. JobQueue->JobId);
  1248. bRval = FALSE;
  1249. }
  1250. }
  1251. __except (HandleFaxExtensionFault(EXCEPTION_SOURCE_FSP, JobQueue->JobEntry->LineInfo->Provider->FriendlyName, GetExceptionCode()))
  1252. {
  1253. ASSERT_FALSE;
  1254. }
  1255. //
  1256. // Mark the job as system abort
  1257. //
  1258. JobQueue->JobEntry->fSystemAbort = TRUE;
  1259. }
  1260. }
  1261. LeaveCriticalSectionJobAndQueue;
  1262. return bRval;
  1263. }
  1264. DWORD
  1265. FaxInitThread(
  1266. PREG_FAX_SERVICE FaxReg
  1267. )
  1268. /*++
  1269. Routine Description:
  1270. Initialize device providers, TAPI, job manager and router.
  1271. This is done in a separate thread because NT Services should
  1272. not block for long periods of time before setting the service status
  1273. to SERVICE_RUNNING. While a service is marked as START_PENDING, the SCM
  1274. blocks all calls to StartService. During TAPI initialization, StartService
  1275. is called to start tapisrv and then tapisrv calls UNIMODEM that in turn
  1276. calls StartService.
  1277. Starts the RPC server. This implementation listens on
  1278. a list of protocols. Hopefully this list is inclusive
  1279. enough to handle RPC requests from most clients.
  1280. Arguments:
  1281. None.
  1282. Return Value:
  1283. Return code. Return zero for success, all other
  1284. values indicate errors.
  1285. --*/
  1286. {
  1287. DWORD ec = ERROR_SUCCESS;
  1288. ULONG i = 0;
  1289. BOOL GoodProt = FALSE;
  1290. DWORD dwProviders;
  1291. DEBUG_FUNCTION_NAME(TEXT("FaxInitThread"));
  1292. //
  1293. // Initialize archives quota
  1294. //
  1295. ec = InitializeServerQuota();
  1296. if (ERROR_SUCCESS != ec)
  1297. {
  1298. DebugPrintEx(
  1299. DEBUG_ERR,
  1300. TEXT("InitializeServerQuota failed (ec: %ld)"),
  1301. ec);
  1302. FaxLog( FAXLOG_CATEGORY_INIT,
  1303. FAXLOG_LEVEL_MIN,
  1304. 1,
  1305. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1306. DWORD2DECIMAL(ec)
  1307. );
  1308. goto exit;
  1309. }
  1310. ec = InitializeServerSecurity();
  1311. if (ERROR_SUCCESS != ec)
  1312. {
  1313. DebugPrintEx(
  1314. DEBUG_ERR,
  1315. TEXT("InitializeServerSecurity failed with %ld."),
  1316. ec);
  1317. goto exit;
  1318. }
  1319. //
  1320. // load the device providers (generates its own event log msgs)
  1321. //
  1322. if (!LoadDeviceProviders( FaxReg ))
  1323. {
  1324. DebugPrintEx(
  1325. DEBUG_ERR,
  1326. TEXT("At least one provider failed to load."));
  1327. }
  1328. //
  1329. // Initialize the job manager data structures (inlcuding critical sections).
  1330. // The job queue thread is NOT started here !!!
  1331. // This must be called here since the rest of the initialization depends
  1332. // on having the job queue related job structures in placed and initialized !
  1333. //
  1334. if (!InitializeJobManager( FaxReg ))
  1335. {
  1336. ec = ERROR_GEN_FAILURE;
  1337. goto exit;
  1338. }
  1339. //
  1340. // get the inbound fax router up and running (generates its own event log messages)
  1341. //
  1342. // generates event log for any failed routing module.
  1343. if (!InitializeRouting( FaxReg ))
  1344. {
  1345. ec = GetLastError();
  1346. DebugPrintEx(
  1347. DEBUG_ERR,
  1348. TEXT("InitializeRouting() failed (ec: %ld)."),
  1349. ec);
  1350. goto exit;
  1351. }
  1352. //
  1353. // initialize TAPI devices (Note that it sets g_dwDeviceCount to the number of valid TAPI devices)
  1354. //
  1355. ec = TapiInitialize( FaxReg );
  1356. if (ec)
  1357. {
  1358. //
  1359. // Note: If ec is not 0 it can be a WINERROR or TAPI ERROR value.
  1360. //+ g_ServerActivity {...}
  1361. DebugPrintEx(
  1362. DEBUG_ERR,
  1363. TEXT("TapiInitialize() failed (ec: %ld)"),
  1364. ec);
  1365. FaxLog(
  1366. FAXLOG_CATEGORY_INIT,
  1367. FAXLOG_LEVEL_MIN,
  1368. 1,
  1369. MSG_SERVICE_INIT_FAILED_TAPI,
  1370. DWORD2DECIMAL(ec)
  1371. );
  1372. goto exit;
  1373. }
  1374. //
  1375. // Initialize the device providers extension configuration.
  1376. // Must be called before InitializeDeviceProviders()
  1377. //
  1378. if (!InitializeDeviceProvidersConfiguration())
  1379. {
  1380. DebugPrintEx(
  1381. DEBUG_ERR,
  1382. TEXT("At least one provider failed failed to initialize the extension configuration."),
  1383. ec);
  1384. //
  1385. // Event log for each failed provider issued by InitializeDeviceProvidersConfiguration().
  1386. //
  1387. }
  1388. //
  1389. // Create the Legacy Virtual Devices. They must be created before the providers are initialized
  1390. // (backword compatability).
  1391. //
  1392. g_dwDeviceCount += CreateVirtualDevices( FaxReg,FSPI_API_VERSION_1 );
  1393. //
  1394. // initialize the device providers [Note: we now initialize the providers before enumerating devices]
  1395. // The Legacy FSPI did not specify when FaxDevVirtualDeviceCreation() will be called so we can
  1396. // "safely" change that.
  1397. //
  1398. if (!InitializeDeviceProviders())
  1399. {
  1400. DebugPrintEx(
  1401. DEBUG_ERR,
  1402. TEXT("At least one provider failed failed to initialize."),
  1403. ec);
  1404. //
  1405. // Event log for each failed provider issued by InitializeDeviceProviders().
  1406. //
  1407. }
  1408. dwProviders = GetSuccessfullyLoadedProvidersCount();
  1409. if (0 == dwProviders)
  1410. {
  1411. DebugPrintEx(
  1412. DEBUG_ERR,
  1413. TEXT("No device provider was initialized."));
  1414. FaxLog(
  1415. FAXLOG_CATEGORY_INIT,
  1416. FAXLOG_LEVEL_MED,
  1417. 0,
  1418. MSG_NO_FSP_INITIALIZED
  1419. );
  1420. }
  1421. if (g_dwDeviceCount == 0)
  1422. {
  1423. //
  1424. // No TAPI devices and no virtual devices.
  1425. //
  1426. DebugPrintEx(
  1427. DEBUG_WRN,
  1428. TEXT("No devices (TAPI + Virtual) found. exiting !!!."));
  1429. FaxLog(
  1430. FAXLOG_CATEGORY_INIT,
  1431. FAXLOG_LEVEL_MED,
  1432. 0,
  1433. MSG_NO_FAX_DEVICES
  1434. );
  1435. }
  1436. //
  1437. // Update the manual answer device
  1438. //
  1439. UpdateManualAnswerDevice();
  1440. //
  1441. // Make sure we do not exceed device limit
  1442. //
  1443. ec = UpdateDevicesFlags();
  1444. if (ERROR_SUCCESS != ec)
  1445. {
  1446. DebugPrintEx(
  1447. DEBUG_ERR,
  1448. TEXT("UpdateDevicesFlags() failed (ec: %ld)"),
  1449. ec);
  1450. FaxLog(
  1451. FAXLOG_CATEGORY_INIT,
  1452. FAXLOG_LEVEL_MIN,
  1453. 1,
  1454. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1455. DWORD2DECIMAL(ec)
  1456. );
  1457. goto exit;
  1458. }
  1459. UpdateVirtualDevices();
  1460. //
  1461. // Count number of devices that are receive-enabled
  1462. //
  1463. UpdateReceiveEnabledDevicesCount ();
  1464. //
  1465. // Get Outbound routing groups configuration
  1466. //
  1467. ec = g_pGroupsMap->Load();
  1468. if (ERROR_SUCCESS != ec)
  1469. {
  1470. DebugPrintEx(
  1471. DEBUG_ERR,
  1472. TEXT("COutboundRoutingGroupsMap::Load() failed (ec: %ld)"),
  1473. ec);
  1474. FaxLog(
  1475. FAXLOG_CATEGORY_INIT,
  1476. FAXLOG_LEVEL_MIN,
  1477. 1,
  1478. MSG_BAD_OUTBOUND_ROUTING_CONFIGURATION,
  1479. DWORD2DECIMAL(ec)
  1480. );
  1481. goto exit;
  1482. }
  1483. if (!g_pGroupsMap->UpdateAllDevicesGroup())
  1484. {
  1485. ec = GetLastError();
  1486. DebugPrintEx(
  1487. DEBUG_ERR,
  1488. TEXT("COutboundRoutingGroupsMap::UpdateAllDevicesGroup() failed (ec: %ld)"),
  1489. ec);
  1490. FaxLog(
  1491. FAXLOG_CATEGORY_INIT,
  1492. FAXLOG_LEVEL_MIN,
  1493. 1,
  1494. MSG_BAD_OUTBOUND_ROUTING_CONFIGURATION,
  1495. DWORD2DECIMAL(ec)
  1496. );
  1497. goto exit;
  1498. }
  1499. #if DBG
  1500. g_pGroupsMap->Dump();
  1501. #endif
  1502. //
  1503. // Get Outbound routing rules configuration
  1504. //
  1505. ec = g_pRulesMap->Load();
  1506. if (ERROR_SUCCESS != ec)
  1507. {
  1508. DebugPrintEx(
  1509. DEBUG_ERR,
  1510. TEXT("COutboundRoutingGroupsMap::Load() failed (ec: %ld)"),
  1511. ec);
  1512. FaxLog(
  1513. FAXLOG_CATEGORY_INIT,
  1514. FAXLOG_LEVEL_MIN,
  1515. 1,
  1516. MSG_BAD_OUTBOUND_ROUTING_CONFIGURATION,
  1517. DWORD2DECIMAL(ec)
  1518. );
  1519. goto exit;
  1520. }
  1521. if (!g_pRulesMap->CreateDefaultRule())
  1522. {
  1523. ec = GetLastError();
  1524. DebugPrintEx(
  1525. DEBUG_ERR,
  1526. TEXT("COutboundRoutingGroupsMap::CreateDefaultRule() failed (ec: %ld)"),
  1527. ec);
  1528. FaxLog(
  1529. FAXLOG_CATEGORY_INIT,
  1530. FAXLOG_LEVEL_MIN,
  1531. 1,
  1532. MSG_BAD_OUTBOUND_ROUTING_CONFIGURATION,
  1533. DWORD2DECIMAL(ec)
  1534. );
  1535. goto exit;
  1536. }
  1537. #if DBG
  1538. g_pRulesMap->Dump();
  1539. #endif
  1540. //
  1541. // Create the JobQueueThread resources
  1542. //
  1543. g_hQueueTimer = CreateWaitableTimer( NULL, FALSE, NULL );
  1544. if (NULL == g_hQueueTimer)
  1545. {
  1546. ec = GetLastError();
  1547. DebugPrintEx(
  1548. DEBUG_ERR,
  1549. TEXT("CreateWaitableTimer() failed (ec: %ld)"),
  1550. ec);
  1551. FaxLog(
  1552. FAXLOG_CATEGORY_INIT,
  1553. FAXLOG_LEVEL_MIN,
  1554. 1,
  1555. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1556. DWORD2DECIMAL(ec)
  1557. );
  1558. goto exit;
  1559. }
  1560. g_hJobQueueEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  1561. if (NULL == g_hJobQueueEvent)
  1562. {
  1563. ec = GetLastError();
  1564. DebugPrintEx(
  1565. DEBUG_ERR,
  1566. TEXT("CreateEvent() failed (ec: %ld)"),
  1567. ec);
  1568. FaxLog(
  1569. FAXLOG_CATEGORY_INIT,
  1570. FAXLOG_LEVEL_MIN,
  1571. 1,
  1572. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1573. DWORD2DECIMAL(ec)
  1574. );
  1575. goto exit;
  1576. }
  1577. if (!CreateStatusThreads())
  1578. {
  1579. ec = GetLastError();
  1580. DebugPrintEx(
  1581. DEBUG_ERR,
  1582. TEXT("Failed to create status threads (ec: %ld)"),
  1583. ec);
  1584. FaxLog(
  1585. FAXLOG_CATEGORY_INIT,
  1586. FAXLOG_LEVEL_MIN,
  1587. 1,
  1588. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1589. DWORD2DECIMAL(ec)
  1590. );
  1591. goto exit;
  1592. }
  1593. if (!CreateTapiThread())
  1594. {
  1595. ec = GetLastError();
  1596. DebugPrintEx(
  1597. DEBUG_ERR,
  1598. TEXT("Failed to create tapi thread (ec: %ld)"),
  1599. ec);
  1600. FaxLog(
  1601. FAXLOG_CATEGORY_INIT,
  1602. FAXLOG_LEVEL_MIN,
  1603. 1,
  1604. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1605. DWORD2DECIMAL(ec)
  1606. );
  1607. goto exit;
  1608. }
  1609. if (!CreateJobQueueThread())
  1610. {
  1611. ec = GetLastError();
  1612. DebugPrintEx(
  1613. DEBUG_ERR,
  1614. TEXT("Failed to create job queue thread (ec: %ld)"),
  1615. ec);
  1616. FaxLog(
  1617. FAXLOG_CATEGORY_INIT,
  1618. FAXLOG_LEVEL_MIN,
  1619. 1,
  1620. MSG_SERVICE_INIT_FAILED_SYS_RESOURCE,
  1621. DWORD2DECIMAL(ec)
  1622. );
  1623. goto exit;
  1624. }
  1625. //
  1626. // free the registry data
  1627. //
  1628. FreeFaxRegistry( FaxReg ); // It used to be a thread so it frees the input parameter itself
  1629. exit:
  1630. return ec;
  1631. } // FaxInitThread
  1632. DWORD WINAPI FaxRPCListeningThread(
  1633. LPVOID pvUnused
  1634. )
  1635. /*++
  1636. Routine Description:
  1637. Performs the wait operation associated with RpcServerListen
  1638. Arguments:
  1639. None.
  1640. Return Value:
  1641. Return code. Return zero for success, all other
  1642. values indicate errors.
  1643. --*/
  1644. {
  1645. RPC_STATUS RpcStatus = RPC_S_OK;
  1646. DEBUG_FUNCTION_NAME(TEXT("FaxRPCListeningThread"));
  1647. RpcStatus = RpcMgmtWaitServerListen();
  1648. if (RPC_S_OK != RpcStatus)
  1649. {
  1650. DebugPrintEx(
  1651. DEBUG_ERR,
  1652. TEXT("RpcMgmtStopServerListening failed. (ec: %ld)"),
  1653. RpcStatus);
  1654. }
  1655. return RpcStatus;
  1656. }