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.

1941 lines
64 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. route.c
  5. Abstract:
  6. This module implements the inbound routing rules.
  7. Author:
  8. Wesley Witt (wesw) 1-Apr-1997
  9. Revision History:
  10. --*/
  11. #include "faxsvc.h"
  12. #include "tiff.h"
  13. #pragma hdrstop
  14. #include "..\faxroute\FaxRouteP.h"
  15. extern DWORD FaxPrinters;
  16. LIST_ENTRY g_lstRoutingExtensions;
  17. LIST_ENTRY g_lstRoutingMethods;
  18. DWORD g_dwCountRoutingMethods;
  19. CFaxCriticalSection g_CsRouting;
  20. LONG WINAPI
  21. FaxRouteAddFile(
  22. IN DWORD JobId,
  23. IN LPCWSTR FileName,
  24. IN GUID *Guid
  25. )
  26. {
  27. PJOB_QUEUE JobQueueEntry;
  28. PFAX_ROUTE_FILE FaxRouteFile;
  29. WCHAR FullPathName[MAX_PATH];
  30. LPWSTR fnp;
  31. DWORD Count;
  32. WCHAR RouteGuid[MAX_GUID_STRING_LEN];
  33. StringFromGUID2( *Guid, RouteGuid, MAX_GUID_STRING_LEN );
  34. if (!JobId || !Guid || !FileName) {
  35. SetLastError( ERROR_INVALID_PARAMETER );
  36. return -1;
  37. }
  38. JobQueueEntry = FindJobQueueEntry( JobId );
  39. if (!JobQueueEntry) {
  40. SetLastError( ERROR_INVALID_DATA );
  41. return -1;
  42. }
  43. if ((!IsEqualGUID(*Guid,gc_FaxSvcGuid)) && (!FindRoutingMethodByGuid(RouteGuid))) {
  44. SetLastError( ERROR_INVALID_DATA );
  45. return -1;
  46. }
  47. if (!GetFullPathName( FileName, sizeof(FullPathName)/sizeof(WCHAR), FullPathName, &fnp )) {
  48. return -1;
  49. }
  50. FaxRouteFile = (PFAX_ROUTE_FILE) MemAlloc( sizeof(FAX_ROUTE_FILE) );
  51. if (!FaxRouteFile) {
  52. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  53. return -1;
  54. }
  55. FaxRouteFile->FileName = StringDup( FullPathName );
  56. CopyMemory( &FaxRouteFile->Guid, Guid, sizeof(GUID) );
  57. EnterCriticalSection( &JobQueueEntry->CsFileList );
  58. InsertTailList( &JobQueueEntry->FaxRouteFiles, &FaxRouteFile->ListEntry );
  59. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  60. //
  61. // increment file count
  62. //
  63. EnterCriticalSection( &g_CsJob );
  64. EnterCriticalSection( &g_CsQueue );
  65. JobQueueEntry->CountFaxRouteFiles += 1;
  66. Count = JobQueueEntry->CountFaxRouteFiles;
  67. LeaveCriticalSection( &g_CsQueue );
  68. LeaveCriticalSection( &g_CsJob );
  69. return Count;
  70. }
  71. LONG WINAPI
  72. FaxRouteDeleteFile(
  73. IN DWORD JobId,
  74. IN LPCWSTR FileName
  75. )
  76. {
  77. PJOB_QUEUE JobQueueEntry;
  78. PFAX_ROUTE_FILE FaxRouteFile;
  79. PLIST_ENTRY Next;
  80. LONG Index = 1;
  81. if (!FileName) {
  82. SetLastError( ERROR_INVALID_PARAMETER );
  83. return -1;
  84. }
  85. JobQueueEntry = FindJobQueueEntry( JobId );
  86. if (!JobQueueEntry) {
  87. SetLastError( ERROR_INVALID_DATA );
  88. return -1;
  89. }
  90. Next = JobQueueEntry->FaxRouteFiles.Flink;
  91. if (Next == &JobQueueEntry->FaxRouteFiles) {
  92. SetLastError( ERROR_NO_MORE_FILES );
  93. return -1;
  94. }
  95. EnterCriticalSection( &JobQueueEntry->CsFileList );
  96. while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
  97. FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
  98. Next = FaxRouteFile->ListEntry.Flink;
  99. if (_wcsicmp( FileName, FaxRouteFile->FileName ) == 0) {
  100. //
  101. // the initial file is read-only for all extensions
  102. //
  103. if (Index == 1) {
  104. SetLastError( ERROR_INVALID_DATA );
  105. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  106. return -1;
  107. }
  108. //
  109. // remove from list, delete the file, cleanup memory
  110. //
  111. RemoveEntryList( &FaxRouteFile->ListEntry );
  112. DeleteFile( FaxRouteFile->FileName );
  113. MemFree ( FaxRouteFile->FileName ) ;
  114. MemFree ( FaxRouteFile );
  115. //
  116. // decrement file count
  117. //
  118. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  119. EnterCriticalSection( &g_CsJob );
  120. EnterCriticalSection( &g_CsQueue );
  121. JobQueueEntry->CountFaxRouteFiles -= 1;
  122. LeaveCriticalSection( &g_CsQueue );
  123. LeaveCriticalSection( &g_CsJob );
  124. return Index;
  125. }
  126. Index += 1;
  127. }
  128. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  129. SetLastError( ERROR_FILE_NOT_FOUND );
  130. return -1;
  131. }
  132. BOOL WINAPI
  133. FaxRouteGetFile(
  134. IN DWORD JobId,
  135. IN DWORD FileNumber,
  136. OUT LPWSTR FileNameBuffer,
  137. OUT LPDWORD RequiredSize
  138. )
  139. {
  140. PJOB_QUEUE JobQueueEntry;
  141. PFAX_ROUTE_FILE FaxRouteFile;
  142. PLIST_ENTRY Next;
  143. ULONG Index = 1;
  144. if (RequiredSize == NULL) {
  145. SetLastError( ERROR_INVALID_PARAMETER );
  146. return FALSE;
  147. }
  148. JobQueueEntry = FindJobQueueEntry( JobId );
  149. if (!JobQueueEntry) {
  150. SetLastError( ERROR_INVALID_DATA );
  151. return FALSE;
  152. }
  153. if (JobQueueEntry->CountFaxRouteFiles < Index) {
  154. SetLastError( ERROR_INVALID_DATA );
  155. }
  156. Next = JobQueueEntry->FaxRouteFiles.Flink;
  157. //
  158. // make sure list isn't empty
  159. //
  160. if (Next == &JobQueueEntry->FaxRouteFiles) {
  161. SetLastError( ERROR_NO_MORE_FILES );
  162. return FALSE;
  163. }
  164. EnterCriticalSection( &JobQueueEntry->CsFileList );
  165. while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
  166. FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
  167. Next = FaxRouteFile->ListEntry.Flink;
  168. if (Index == FileNumber) {
  169. if (*RequiredSize < (wcslen(FaxRouteFile->FileName)+1)*sizeof(WCHAR)) {
  170. if (FileNameBuffer == NULL) {
  171. *RequiredSize = (wcslen(FaxRouteFile->FileName) + 1)*sizeof(WCHAR);
  172. }
  173. SetLastError( ERROR_INSUFFICIENT_BUFFER );
  174. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  175. return FALSE;
  176. } else if (FileNameBuffer) {
  177. wcscpy( FileNameBuffer, FaxRouteFile->FileName );
  178. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  179. return TRUE;
  180. } else {
  181. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  182. SetLastError( ERROR_INVALID_PARAMETER );
  183. return TRUE;
  184. }
  185. }
  186. Index += 1;
  187. }
  188. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  189. SetLastError( ERROR_NO_MORE_FILES );
  190. return FALSE;
  191. }
  192. BOOL WINAPI
  193. FaxRouteEnumFiles(
  194. IN DWORD JobId,
  195. IN GUID *Guid,
  196. IN PFAXROUTEENUMFILE FileEnumerator,
  197. IN PVOID Context
  198. )
  199. {
  200. PJOB_QUEUE JobQueueEntry;
  201. PFAX_ROUTE_FILE FaxRouteFile;
  202. PLIST_ENTRY Next;
  203. if (!FileEnumerator) {
  204. SetLastError( ERROR_INVALID_PARAMETER );
  205. return FALSE;
  206. }
  207. JobQueueEntry = FindJobQueueEntry( JobId );
  208. if (!JobQueueEntry) {
  209. SetLastError( ERROR_INVALID_DATA );
  210. return FALSE;
  211. }
  212. Next = JobQueueEntry->FaxRouteFiles.Flink;
  213. if (Next == &JobQueueEntry->FaxRouteFiles) {
  214. SetLastError( ERROR_NO_MORE_FILES );
  215. return FALSE;
  216. }
  217. EnterCriticalSection( &JobQueueEntry->CsFileList );
  218. while ((ULONG_PTR)Next != (ULONG_PTR)&JobQueueEntry->FaxRouteFiles) {
  219. FaxRouteFile = CONTAINING_RECORD( Next, FAX_ROUTE_FILE, ListEntry );
  220. Next = FaxRouteFile->ListEntry.Flink;
  221. if (!FileEnumerator( JobId, &FaxRouteFile->Guid, Guid, FaxRouteFile->FileName, Context )) {
  222. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  223. return FALSE;
  224. }
  225. }
  226. LeaveCriticalSection( &JobQueueEntry->CsFileList );
  227. SetLastError( ERROR_NO_MORE_FILES );
  228. return TRUE;
  229. }
  230. PROUTING_METHOD
  231. FindRoutingMethodByGuid(
  232. IN LPCWSTR RoutingGuidString
  233. )
  234. {
  235. PLIST_ENTRY pNextMethod;
  236. PROUTING_METHOD pRoutingMethod;
  237. GUID RoutingGuid;
  238. IIDFromString( (LPWSTR)RoutingGuidString, &RoutingGuid );
  239. EnterCriticalSection( &g_CsRouting );
  240. pNextMethod = g_lstRoutingMethods.Flink;
  241. if (pNextMethod == NULL)
  242. {
  243. LeaveCriticalSection( &g_CsRouting );
  244. return NULL;
  245. }
  246. while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods) {
  247. pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
  248. pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
  249. if (IsEqualGUID( RoutingGuid, pRoutingMethod->Guid ))
  250. {
  251. LeaveCriticalSection( &g_CsRouting );
  252. return pRoutingMethod;
  253. }
  254. }
  255. LeaveCriticalSection( &g_CsRouting );
  256. return NULL;
  257. }
  258. DWORD
  259. EnumerateRoutingMethods(
  260. IN PFAXROUTEMETHODENUM Enumerator,
  261. IN LPVOID Context
  262. )
  263. {
  264. PLIST_ENTRY pNextMethod;
  265. PROUTING_METHOD pRoutingMethod;
  266. DWORD dwCount = 0;
  267. EnterCriticalSection( &g_CsRouting );
  268. pNextMethod = g_lstRoutingMethods.Flink;
  269. Assert(pNextMethod != NULL);
  270. while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods)
  271. {
  272. pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
  273. pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
  274. if (!Enumerator( pRoutingMethod, Context ))
  275. {
  276. LeaveCriticalSection( &g_CsRouting );
  277. SetLastError(ERROR_INVALID_FUNCTION);
  278. return dwCount;
  279. }
  280. dwCount += 1;
  281. }
  282. LeaveCriticalSection(&g_CsRouting);
  283. SetLastError(ERROR_SUCCESS);
  284. return dwCount;
  285. }
  286. BOOL
  287. FaxRouteModifyRoutingData(
  288. DWORD JobId,
  289. LPCWSTR RoutingGuid,
  290. LPBYTE RoutingData,
  291. DWORD RoutingDataSize
  292. )
  293. {
  294. PJOB_QUEUE JobQueueEntry = NULL;
  295. PROUTING_METHOD RoutingMethod = NULL;
  296. PROUTING_DATA_OVERRIDE RoutingDataOverride = NULL;
  297. if (JobId == 0 || RoutingGuid == NULL || RoutingData == NULL || RoutingDataSize == 0) {
  298. SetLastError( ERROR_INVALID_PARAMETER );
  299. return FALSE;
  300. }
  301. JobQueueEntry = FindJobQueueEntry( JobId );
  302. if (!JobQueueEntry) {
  303. SetLastError( ERROR_INVALID_DATA );
  304. return FALSE;
  305. }
  306. RoutingMethod = FindRoutingMethodByGuid( RoutingGuid );
  307. if (RoutingMethod == NULL) {
  308. SetLastError( ERROR_INVALID_DATA );
  309. return FALSE;
  310. }
  311. RoutingDataOverride = (PROUTING_DATA_OVERRIDE) MemAlloc( sizeof(ROUTING_DATA_OVERRIDE) );
  312. if (RoutingDataOverride == NULL) {
  313. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  314. return FALSE;
  315. }
  316. RoutingDataOverride->RoutingData = (LPBYTE)MemAlloc( RoutingDataSize );
  317. if (RoutingDataOverride->RoutingData == NULL) {
  318. MemFree( RoutingDataOverride );
  319. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  320. return FALSE;
  321. }
  322. RoutingDataOverride->RoutingDataSize = RoutingDataSize;
  323. RoutingDataOverride->RoutingMethod = RoutingMethod;
  324. CopyMemory( RoutingDataOverride->RoutingData, RoutingData, RoutingDataSize );
  325. EnterCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
  326. InsertTailList( &JobQueueEntry->RoutingDataOverride, &RoutingDataOverride->ListEntry );
  327. LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
  328. return TRUE;
  329. }
  330. int
  331. __cdecl
  332. MethodPriorityCompare(
  333. const void *arg1,
  334. const void *arg2
  335. )
  336. {
  337. if (((PMETHOD_SORT)arg1)->Priority < ((PMETHOD_SORT)arg2)->Priority) {
  338. return -1;
  339. }
  340. if (((PMETHOD_SORT)arg1)->Priority > ((PMETHOD_SORT)arg2)->Priority) {
  341. return 1;
  342. }
  343. return 0;
  344. }
  345. BOOL
  346. SortMethodPriorities(
  347. VOID
  348. )
  349. {
  350. PLIST_ENTRY pNext;
  351. PROUTING_METHOD pRoutingMethod;
  352. PMETHOD_SORT pMethodSort;
  353. DWORD i;
  354. EnterCriticalSection( &g_CsRouting );
  355. pNext = g_lstRoutingMethods.Flink;
  356. if (pNext == NULL)
  357. {
  358. LeaveCriticalSection( &g_CsRouting );
  359. return FALSE;
  360. }
  361. pMethodSort = (PMETHOD_SORT) MemAlloc( g_dwCountRoutingMethods * sizeof(METHOD_SORT) );
  362. if (pMethodSort == NULL)
  363. {
  364. LeaveCriticalSection( &g_CsRouting );
  365. return FALSE;
  366. }
  367. i = 0;
  368. while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingMethods)
  369. {
  370. pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD, ListEntryMethod );
  371. pNext = pRoutingMethod->ListEntryMethod.Flink;
  372. pMethodSort[i].Priority = pRoutingMethod->Priority;
  373. pMethodSort[i].RoutingMethod = pRoutingMethod;
  374. i += 1;
  375. }
  376. qsort(
  377. (PVOID)pMethodSort,
  378. (int)g_dwCountRoutingMethods,
  379. sizeof(METHOD_SORT),
  380. MethodPriorityCompare
  381. );
  382. InitializeListHead( &g_lstRoutingMethods );
  383. for (i=0; i<g_dwCountRoutingMethods; i++)
  384. {
  385. pMethodSort[i].RoutingMethod->Priority = i + 1;
  386. pMethodSort[i].RoutingMethod->ListEntryMethod.Flink = NULL;
  387. pMethodSort[i].RoutingMethod->ListEntryMethod.Blink = NULL;
  388. InsertTailList( &g_lstRoutingMethods, &pMethodSort[i].RoutingMethod->ListEntryMethod );
  389. }
  390. MemFree( pMethodSort );
  391. LeaveCriticalSection( &g_CsRouting );
  392. return TRUE;
  393. }
  394. BOOL
  395. CommitMethodChanges(
  396. VOID
  397. )
  398. /*++
  399. Routine Description:
  400. sticks changes to routing into the registry
  401. Arguments:
  402. NONE
  403. Return Value:
  404. TRUE for success
  405. --*/
  406. {
  407. PLIST_ENTRY pNext;
  408. PROUTING_METHOD pRoutingMethod;
  409. TCHAR StrGuid[100];
  410. EnterCriticalSection(&g_CsRouting);
  411. pNext = g_lstRoutingMethods.Flink;
  412. while ((UINT_PTR)pNext != (UINT_PTR)&g_lstRoutingMethods)
  413. {
  414. pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD , ListEntryMethod );
  415. pNext = pRoutingMethod->ListEntryMethod.Flink;
  416. StringFromGUID2( pRoutingMethod->Guid,
  417. StrGuid,
  418. sizeof(StrGuid)/sizeof(TCHAR)
  419. );
  420. SetFaxRoutingInfo( pRoutingMethod->RoutingExtension->InternalName,
  421. pRoutingMethod->InternalName,
  422. StrGuid,
  423. pRoutingMethod->Priority,
  424. pRoutingMethod->FunctionName,
  425. pRoutingMethod->FriendlyName
  426. );
  427. }
  428. LeaveCriticalSection(&g_CsRouting);
  429. return TRUE;
  430. }
  431. static
  432. void
  433. FreeRoutingMethod(
  434. PROUTING_METHOD pRoutingMethod
  435. )
  436. {
  437. Assert (pRoutingMethod);
  438. MemFree(pRoutingMethod->FriendlyName);
  439. MemFree(pRoutingMethod->FunctionName);
  440. MemFree(pRoutingMethod->InternalName);
  441. MemFree(pRoutingMethod);
  442. return;
  443. }
  444. static
  445. void
  446. FreeRoutingExtension(
  447. PROUTING_EXTENSION pRoutingExtension
  448. )
  449. {
  450. DEBUG_FUNCTION_NAME(TEXT("FreeRoutingExtension"));
  451. Assert (pRoutingExtension);
  452. if (pRoutingExtension->hModule)
  453. {
  454. FreeLibrary (pRoutingExtension->hModule);
  455. }
  456. if (pRoutingExtension->HeapHandle &&
  457. FALSE == pRoutingExtension->MicrosoftExtension)
  458. {
  459. HeapDestroy(pRoutingExtension->HeapHandle);
  460. }
  461. MemFree(pRoutingExtension);
  462. return;
  463. }
  464. void
  465. FreeRoutingExtensions(
  466. void
  467. )
  468. {
  469. PLIST_ENTRY pNext;
  470. PROUTING_EXTENSION pRoutingExtension;
  471. PROUTING_METHOD pRoutingMethod;
  472. //
  473. // Free routing methods
  474. //
  475. pNext = g_lstRoutingMethods.Flink;
  476. while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingMethods)
  477. {
  478. pRoutingMethod = CONTAINING_RECORD( pNext, ROUTING_METHOD, ListEntryMethod );
  479. pNext = pRoutingMethod->ListEntryMethod.Flink;
  480. RemoveEntryList(&pRoutingMethod->ListEntryMethod);
  481. FreeRoutingMethod(pRoutingMethod);
  482. }
  483. //
  484. // Free routing extensions
  485. //
  486. pNext = g_lstRoutingExtensions.Flink;
  487. while ((ULONG_PTR)pNext != (ULONG_PTR)&g_lstRoutingExtensions)
  488. {
  489. pRoutingExtension = CONTAINING_RECORD( pNext, ROUTING_EXTENSION, ListEntry );
  490. pNext = pRoutingExtension->ListEntry.Flink;
  491. RemoveEntryList(&pRoutingExtension->ListEntry);
  492. FreeRoutingExtension(pRoutingExtension);
  493. }
  494. return;
  495. }
  496. BOOL
  497. InitializeRouting(
  498. PREG_FAX_SERVICE pFaxReg
  499. )
  500. /*++
  501. Routine Description:
  502. Initializes routing
  503. Arguments:
  504. NONE
  505. Return Value:
  506. NONE
  507. --*/
  508. {
  509. DWORD i,j;
  510. DWORD dwRes;
  511. BOOL bRes;
  512. PROUTING_EXTENSION pRoutingExtension;
  513. PROUTING_METHOD pRoutingMethod;
  514. FAX_ROUTE_CALLBACKROUTINES Callbacks;
  515. FAX_ROUTE_CALLBACKROUTINES_P Callbacks_private;
  516. HRESULT hr = NOERROR;
  517. PLIST_ENTRY ple;
  518. DEBUG_FUNCTION_NAME(TEXT("InitializeRouting"));
  519. Assert (wcslen (g_wszFaxQueueDir));
  520. Callbacks.SizeOfStruct = sizeof(FAX_ROUTE_CALLBACKROUTINES);
  521. Callbacks.FaxRouteAddFile = FaxRouteAddFile;
  522. Callbacks.FaxRouteDeleteFile = FaxRouteDeleteFile;
  523. Callbacks.FaxRouteGetFile = FaxRouteGetFile;
  524. Callbacks.FaxRouteEnumFiles = FaxRouteEnumFiles;
  525. Callbacks.FaxRouteModifyRoutingData = FaxRouteModifyRoutingData;
  526. Callbacks_private.SizeOfStruct = sizeof(FAX_ROUTE_CALLBACKROUTINES_P);
  527. Callbacks_private.FaxRouteAddFile = FaxRouteAddFile;
  528. Callbacks_private.FaxRouteDeleteFile = FaxRouteDeleteFile;
  529. Callbacks_private.FaxRouteGetFile = FaxRouteGetFile;
  530. Callbacks_private.FaxRouteEnumFiles = FaxRouteEnumFiles;
  531. Callbacks_private.FaxRouteModifyRoutingData = FaxRouteModifyRoutingData;
  532. Callbacks_private.GetRecieptsConfiguration = GetRecieptsConfiguration;
  533. Callbacks_private.FreeRecieptsConfiguration = FreeRecieptsConfiguration;
  534. Callbacks_private.lptstrFaxQueueDir = g_wszFaxQueueDir;
  535. for (i = 0; i < pFaxReg->RoutingExtensionsCount; i++)
  536. {
  537. HMODULE hModule = NULL;
  538. WCHAR wszImageFileName[_MAX_FNAME] = {0};
  539. WCHAR wszImageFileExt[_MAX_EXT] = {0};
  540. pRoutingExtension = (PROUTING_EXTENSION) MemAlloc( sizeof(ROUTING_EXTENSION) );
  541. if (!pRoutingExtension)
  542. {
  543. DebugPrintEx(
  544. DEBUG_ERR,
  545. TEXT("Could not allocate memory for routing extension %s"),
  546. pFaxReg->RoutingExtensions[i].ImageName );
  547. goto InitializationFailed;
  548. }
  549. memset(pRoutingExtension, 0, sizeof(ROUTING_EXTENSION));
  550. InitializeListHead( &pRoutingExtension->RoutingMethods );
  551. //
  552. // Copy registry constant info
  553. //
  554. wcsncpy( pRoutingExtension->FriendlyName,
  555. pFaxReg->RoutingExtensions[i].FriendlyName ?
  556. pFaxReg->RoutingExtensions[i].FriendlyName : EMPTY_STRING ,
  557. sizeof (pRoutingExtension->FriendlyName) / sizeof (TCHAR) );
  558. pRoutingExtension->FriendlyName[(sizeof (pRoutingExtension->FriendlyName) / sizeof (TCHAR)) - 1] = TEXT('\0');
  559. wcsncpy( pRoutingExtension->ImageName,
  560. pFaxReg->RoutingExtensions[i].ImageName ?
  561. pFaxReg->RoutingExtensions[i].ImageName : EMPTY_STRING,
  562. sizeof (pRoutingExtension->ImageName) / sizeof (TCHAR) );
  563. pRoutingExtension->ImageName[(sizeof (pRoutingExtension->ImageName) / sizeof (TCHAR)) - 1] = TEXT('\0');
  564. wcsncpy( pRoutingExtension->InternalName,
  565. pFaxReg->RoutingExtensions[i].InternalName ?
  566. pFaxReg->RoutingExtensions[i].InternalName : EMPTY_STRING,
  567. sizeof (pRoutingExtension->InternalName) / sizeof (TCHAR) );
  568. pRoutingExtension->InternalName[(sizeof (pRoutingExtension->InternalName) / sizeof (TCHAR)) - 1] = TEXT('\0');
  569. _wsplitpath( pRoutingExtension->ImageName, NULL, NULL, wszImageFileName, wszImageFileExt );
  570. if (_wcsicmp( wszImageFileName, FAX_ROUTE_MODULE_NAME ) == 0 &&
  571. _wcsicmp( wszImageFileExt, TEXT(".DLL") ) == 0)
  572. {
  573. pRoutingExtension->MicrosoftExtension = TRUE;
  574. }
  575. hModule = LoadLibrary( pFaxReg->RoutingExtensions[i].ImageName );
  576. if (!hModule)
  577. {
  578. dwRes = GetLastError ();
  579. DebugPrintEx(
  580. DEBUG_WRN,
  581. TEXT("LoadLibrary() failed: [%s], ec=%d"),
  582. pFaxReg->RoutingExtensions[i].ImageName,
  583. dwRes);
  584. pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LOAD;
  585. pRoutingExtension->dwLastError = dwRes;
  586. goto InitializationFailed;
  587. }
  588. pRoutingExtension->hModule = hModule;
  589. //
  590. // Retrieve the routing extension's version from the DLL
  591. //
  592. pRoutingExtension->Version.dwSizeOfStruct = sizeof (FAX_VERSION);
  593. dwRes = GetFileVersion ( pFaxReg->RoutingExtensions[i].ImageName,
  594. &pRoutingExtension->Version);
  595. if (ERROR_SUCCESS != dwRes)
  596. {
  597. //
  598. // If the routing extension's DLL does not have version data or the
  599. // version data is non-retrievable, we consider this a
  600. // warning (debug print) but carry on with the DLL's load.
  601. //
  602. DebugPrintEx(
  603. DEBUG_ERR,
  604. TEXT("GetFileVersion() failed: [%s] (ec: %ld)"),
  605. pFaxReg->RoutingExtensions[i].ImageName,
  606. dwRes);
  607. }
  608. pRoutingExtension->FaxRouteInitialize = (PFAXROUTEINITIALIZE) GetProcAddress(
  609. hModule,
  610. "FaxRouteInitialize"
  611. );
  612. pRoutingExtension->FaxRouteGetRoutingInfo = (PFAXROUTEGETROUTINGINFO) GetProcAddress(
  613. hModule,
  614. "FaxRouteGetRoutingInfo"
  615. );
  616. pRoutingExtension->FaxRouteSetRoutingInfo = (PFAXROUTESETROUTINGINFO) GetProcAddress(
  617. hModule,
  618. "FaxRouteSetRoutingInfo"
  619. );
  620. pRoutingExtension->FaxRouteDeviceEnable = (PFAXROUTEDEVICEENABLE) GetProcAddress(
  621. hModule,
  622. "FaxRouteDeviceEnable"
  623. );
  624. pRoutingExtension->FaxRouteDeviceChangeNotification = (PFAXROUTEDEVICECHANGENOTIFICATION) GetProcAddress(
  625. hModule,
  626. "FaxRouteDeviceChangeNotification"
  627. );
  628. if (pRoutingExtension->FaxRouteInitialize == NULL ||
  629. pRoutingExtension->FaxRouteGetRoutingInfo == NULL ||
  630. pRoutingExtension->FaxRouteSetRoutingInfo == NULL ||
  631. pRoutingExtension->FaxRouteDeviceChangeNotification == NULL ||
  632. pRoutingExtension->FaxRouteDeviceEnable == NULL)
  633. {
  634. //
  635. // the routing extension dll does not have a complete export list
  636. //
  637. dwRes = GetLastError ();
  638. DebugPrintEx(
  639. DEBUG_ERR,
  640. TEXT("Routing extension FAILED to initialized [%s], ec=%ld"),
  641. pFaxReg->RoutingExtensions[i].FriendlyName,
  642. dwRes);
  643. pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LINK;
  644. pRoutingExtension->dwLastError = dwRes;
  645. goto InitializationFailed;
  646. }
  647. //
  648. // Link to the extension configuration and notification init functions
  649. //
  650. pRoutingExtension->pFaxExtInitializeConfig = (PFAX_EXT_INITIALIZE_CONFIG) GetProcAddress(
  651. hModule,
  652. "FaxExtInitializeConfig"
  653. );
  654. if (!pRoutingExtension->pFaxExtInitializeConfig)
  655. {
  656. //
  657. // Optional function
  658. //
  659. DebugPrintEx(
  660. DEBUG_MSG,
  661. TEXT("FaxExtInitializeConfig() not found for routing extension %s. This is not an error."),
  662. pRoutingExtension->FriendlyName);
  663. }
  664. //
  665. // create the routing extension's heap and add it to the list
  666. //
  667. pRoutingExtension->HeapHandle = pRoutingExtension->MicrosoftExtension ?
  668. GetProcessHeap() : HeapCreate( 0, 1024*100, 1024*1024*2 );
  669. if (!pRoutingExtension->HeapHandle)
  670. {
  671. dwRes = GetLastError();
  672. DebugPrintEx(
  673. DEBUG_ERR,
  674. TEXT("Can't create heap, ec=%ld"),
  675. dwRes);
  676. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  677. pRoutingExtension->dwLastError = dwRes;
  678. goto InitializationFailed;
  679. }
  680. //
  681. // We 1st call the RoutingExtension->pFaxExtInitializeConfig function (if exported)
  682. //
  683. if (pRoutingExtension->pFaxExtInitializeConfig)
  684. {
  685. __try
  686. {
  687. hr = pRoutingExtension->pFaxExtInitializeConfig(
  688. FaxExtGetData,
  689. FaxExtSetData,
  690. FaxExtRegisterForEvents,
  691. FaxExtUnregisterForEvents,
  692. FaxExtFreeBuffer);
  693. }
  694. __except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingExtension->FriendlyName, GetExceptionCode()))
  695. {
  696. ASSERT_FALSE;
  697. }
  698. if (FAILED(hr))
  699. {
  700. //
  701. // Failed to init ext. config.
  702. //
  703. DebugPrintEx(
  704. DEBUG_ERR,
  705. TEXT("FaxExtInitializeConfig() failed (hr = 0x%08x) for extension [%s]"),
  706. hr,
  707. pRoutingExtension->FriendlyName );
  708. pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_INIT;
  709. pRoutingExtension->dwLastError = hr;
  710. goto InitializationFailed;
  711. }
  712. }
  713. //
  714. // Next, call the initialization routing of the routing ext.
  715. //
  716. __try
  717. {
  718. if (pRoutingExtension->MicrosoftExtension)
  719. {
  720. //
  721. // Special hack - for the MS routing extension, pass the extra private structure which
  722. // contains a pointer to the service's g_CsConfig.
  723. //
  724. bRes = pRoutingExtension->FaxRouteInitialize( pRoutingExtension->HeapHandle, (PFAX_ROUTE_CALLBACKROUTINES)(&Callbacks_private) );
  725. }
  726. else
  727. {
  728. bRes = pRoutingExtension->FaxRouteInitialize( pRoutingExtension->HeapHandle, &Callbacks );
  729. }
  730. }
  731. __except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingExtension->FriendlyName, GetExceptionCode()))
  732. {
  733. ASSERT_FALSE;
  734. }
  735. if (!bRes)
  736. {
  737. //
  738. // Either init faulted or failed
  739. //
  740. dwRes = GetLastError ();
  741. DebugPrintEx(DEBUG_ERR,
  742. TEXT("FaxRouteInitialize() failed / faulted: ec=%ld"),
  743. dwRes);
  744. pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_INIT;
  745. pRoutingExtension->dwLastError = dwRes;
  746. goto InitializationFailed;
  747. }
  748. //
  749. // All initialization succeeded - proceed with routing methods.
  750. //
  751. for (j = 0; j < pFaxReg->RoutingExtensions[i].RoutingMethodsCount; j++)
  752. {
  753. LPSTR lpstrProcName = NULL;
  754. //
  755. // Send mail is not supported on desktop SKUs
  756. //
  757. if (0 == _wcsicmp(pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid, REGVAL_RM_EMAIL_GUID) &&
  758. TRUE == IsDesktopSKU())
  759. {
  760. DebugPrintEx(
  761. DEBUG_MSG,
  762. TEXT("Email is not supported on desktop SKU."));
  763. continue;
  764. }
  765. pRoutingMethod = (PROUTING_METHOD) MemAlloc( sizeof(ROUTING_METHOD) );
  766. if (!pRoutingMethod)
  767. {
  768. dwRes = GetLastError ();
  769. DebugPrintEx(
  770. DEBUG_ERR,
  771. TEXT("Could not allocate memory for routing method %s"),
  772. pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName);
  773. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  774. pRoutingExtension->dwLastError = dwRes;
  775. goto InitializationFailed;
  776. }
  777. memset (pRoutingMethod, 0, sizeof (ROUTING_METHOD));
  778. pRoutingMethod->RoutingExtension = pRoutingExtension;
  779. pRoutingMethod->Priority = pFaxReg->RoutingExtensions[i].RoutingMethods[j].Priority;
  780. pRoutingMethod->FriendlyName =
  781. StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName ?
  782. pFaxReg->RoutingExtensions[i].RoutingMethods[j].FriendlyName : EMPTY_STRING );
  783. if (!pRoutingMethod->FriendlyName)
  784. {
  785. dwRes = GetLastError ();
  786. DebugPrintEx(
  787. DEBUG_ERR,
  788. TEXT("Could not create routing function name [%s]"),
  789. pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName);
  790. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  791. pRoutingExtension->dwLastError = dwRes;
  792. goto MethodError;
  793. }
  794. pRoutingMethod->FunctionName =
  795. StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName ?
  796. pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName : EMPTY_STRING);
  797. if (!pRoutingMethod->FunctionName)
  798. {
  799. dwRes = GetLastError ();
  800. DebugPrintEx(
  801. DEBUG_ERR,
  802. TEXT("Could not create routing function name [%s]"),
  803. pFaxReg->RoutingExtensions[i].RoutingMethods[j].FunctionName );
  804. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  805. pRoutingExtension->dwLastError = dwRes;
  806. goto MethodError;
  807. }
  808. pRoutingMethod->InternalName =
  809. StringDup( pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName ?
  810. pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName : EMPTY_STRING);
  811. if (!pRoutingMethod->InternalName)
  812. {
  813. dwRes = GetLastError ();
  814. DebugPrintEx(
  815. DEBUG_ERR,
  816. TEXT("Could not create routing internal name [%s]"),
  817. pFaxReg->RoutingExtensions[i].RoutingMethods[j].InternalName );
  818. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  819. pRoutingExtension->dwLastError = dwRes;
  820. goto MethodError;
  821. }
  822. hr = IIDFromString( pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid, &pRoutingMethod->Guid );
  823. if (S_OK != hr)
  824. {
  825. DebugPrintEx(
  826. DEBUG_ERR,
  827. TEXT("Invalid GUID string [%s], hr = 0x%x"),
  828. pFaxReg->RoutingExtensions[i].RoutingMethods[j].Guid,
  829. hr );
  830. pRoutingExtension->Status = FAX_PROVIDER_STATUS_BAD_GUID;
  831. pRoutingExtension->dwLastError = hr;
  832. goto MethodError;
  833. }
  834. lpstrProcName = UnicodeStringToAnsiString( pRoutingMethod->FunctionName );
  835. if (!lpstrProcName)
  836. {
  837. dwRes = GetLastError ();
  838. DebugPrintEx(
  839. DEBUG_ERR,
  840. TEXT("Could not create routing function name [%s]"),
  841. pRoutingMethod->FunctionName );
  842. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SERVER_ERROR;
  843. pRoutingExtension->dwLastError = dwRes;
  844. goto MethodError;
  845. }
  846. pRoutingMethod->FaxRouteMethod = (PFAXROUTEMETHOD) GetProcAddress(
  847. hModule,
  848. lpstrProcName
  849. );
  850. if (!pRoutingMethod->FaxRouteMethod)
  851. {
  852. dwRes = GetLastError ();
  853. DebugPrintEx(DEBUG_ERR,
  854. TEXT("Could not get function address [%S], ec=%ld"),
  855. lpstrProcName,
  856. dwRes
  857. );
  858. pRoutingExtension->Status = FAX_PROVIDER_STATUS_CANT_LINK;
  859. pRoutingExtension->dwLastError = dwRes;
  860. goto MethodError;
  861. }
  862. MemFree( lpstrProcName );
  863. goto MethodOk;
  864. MethodError:
  865. MemFree( pRoutingMethod->FriendlyName );
  866. MemFree( pRoutingMethod->FunctionName );
  867. MemFree( pRoutingMethod->InternalName );
  868. MemFree( pRoutingMethod );
  869. MemFree( lpstrProcName );
  870. goto InitializationFailed;
  871. MethodOk:
  872. //
  873. // Success - add this routing method to the routing extension's list of methods
  874. //
  875. InsertTailList( &pRoutingExtension->RoutingMethods, &pRoutingMethod->ListEntry );
  876. } // Loop of extension's routing methods
  877. //
  878. // Success while loading and initializing this extension
  879. //
  880. pRoutingExtension->Status = FAX_PROVIDER_STATUS_SUCCESS;
  881. pRoutingExtension->dwLastError = ERROR_SUCCESS;
  882. //
  883. // All methods successfully initialized.
  884. // Add all methods to global list of methods (and increase global counter)
  885. //
  886. ple = pRoutingExtension->RoutingMethods.Flink;
  887. while ((ULONG_PTR)ple != (ULONG_PTR)&pRoutingExtension->RoutingMethods)
  888. {
  889. pRoutingMethod = CONTAINING_RECORD( ple, ROUTING_METHOD, ListEntry );
  890. ple = ple->Flink;
  891. InsertTailList( &g_lstRoutingMethods, &pRoutingMethod->ListEntryMethod );
  892. g_dwCountRoutingMethods++;
  893. }
  894. goto next;
  895. InitializationFailed:
  896. {
  897. FaxLog(
  898. FAXLOG_CATEGORY_INIT,
  899. FAXLOG_LEVEL_MIN,
  900. 4,
  901. MSG_ROUTE_INIT_FAILED,
  902. pFaxReg->RoutingExtensions[i].FriendlyName,
  903. pFaxReg->RoutingExtensions[i].ImageName,
  904. pRoutingExtension ? DWORD2DECIMAL(pRoutingExtension->Status) : NULL,
  905. pRoutingExtension ? DWORD2DECIMAL(pRoutingExtension->dwLastError) : DWORD2DECIMAL(ERROR_OUTOFMEMORY)
  906. );
  907. }
  908. if (pRoutingExtension)
  909. {
  910. if (pRoutingExtension->hModule)
  911. {
  912. FreeLibrary (pRoutingExtension->hModule);
  913. pRoutingExtension->hModule = NULL;
  914. }
  915. //
  916. // If we created a heap for the routing extension, destroy it
  917. //
  918. if ((pRoutingExtension->HeapHandle) &&
  919. (FALSE == pRoutingExtension->MicrosoftExtension))
  920. {
  921. HeapDestroy (pRoutingExtension->HeapHandle);
  922. pRoutingExtension->HeapHandle = NULL;
  923. }
  924. //
  925. // Clear the list of routing methods and free method structures.
  926. //
  927. ple = pRoutingExtension->RoutingMethods.Flink;
  928. while ((ULONG_PTR)ple != (ULONG_PTR)&pRoutingExtension->RoutingMethods)
  929. {
  930. pRoutingMethod = CONTAINING_RECORD(ple, ROUTING_METHOD, ListEntry);
  931. ple = ple->Flink;
  932. MemFree( pRoutingMethod->FriendlyName );
  933. MemFree( pRoutingMethod->FunctionName );
  934. MemFree( pRoutingMethod->InternalName );
  935. MemFree( pRoutingMethod );
  936. }
  937. //
  938. // Make the extension have an empty list of methods.
  939. //
  940. InitializeListHead( &pRoutingExtension->RoutingMethods );
  941. }
  942. next:
  943. if (pRoutingExtension)
  944. {
  945. //
  946. // we have a routing extension object (successful or not), add it to the list
  947. //
  948. InsertTailList( &g_lstRoutingExtensions, &pRoutingExtension->ListEntry );
  949. }
  950. }
  951. SortMethodPriorities();
  952. if (0 == g_dwCountRoutingMethods)
  953. {
  954. //
  955. // No routing methods available
  956. //
  957. DebugPrintEx(DEBUG_WRN,
  958. TEXT("No routing methods are available on the server !!!!"));
  959. }
  960. return TRUE;
  961. } // InitializeRouting
  962. BOOL
  963. FaxRoute(
  964. PJOB_QUEUE JobQueueEntry,
  965. LPTSTR TiffFileName,
  966. PFAX_ROUTE FaxRoute,
  967. PROUTE_FAILURE_INFO *RouteFailureInfo,
  968. LPDWORD RouteFailureCount
  969. )
  970. /*++
  971. Routine Description:
  972. Routes a FAX.
  973. Arguments:
  974. JobQueueEntry - the job queue entry for the job
  975. TiffFileName - filename of the received fax
  976. FaxRoute - struct describing received FAX
  977. RouteFailureInfo - pointer to receive pointr to eceive buffer ROUTE_FAILURE_INFO structures
  978. RouteFailureCount - receives the total number of route failures recorded
  979. Return Value:
  980. TRUE
  981. if fax routing succeded ( some methods may still fail )
  982. check RouteFailureCount to see how many Routing Methods failed
  983. FALSE
  984. if the function itself failed ( MemAlloc etc. )
  985. --*/
  986. {
  987. PLIST_ENTRY pNextMethod;
  988. PROUTING_METHOD pRoutingMethod;
  989. DWORD FailureCount = 0;
  990. PROUTE_FAILURE_INFO pRouteFailure;
  991. PLIST_ENTRY pNextRoutingOverride;
  992. PROUTING_DATA_OVERRIDE pRoutingDataOverride;
  993. BOOL RetVal = TRUE;
  994. DEBUG_FUNCTION_NAME(TEXT("FaxRoute"));
  995. *RouteFailureInfo = NULL;
  996. *RouteFailureCount = 0;
  997. //
  998. // if the tiff file has been deleted ==> return
  999. //
  1000. if (GetFileAttributes( TiffFileName ) == 0xffffffff)
  1001. {
  1002. return FALSE;
  1003. }
  1004. EnterCriticalSection( &g_CsRouting );
  1005. pNextMethod = g_lstRoutingMethods.Flink;
  1006. if (pNextMethod)
  1007. {
  1008. //
  1009. // allocate memory to record the GUIDs of the failed routing methods
  1010. //
  1011. pRouteFailure = (PROUTE_FAILURE_INFO) MemAlloc( g_dwCountRoutingMethods * sizeof(ROUTE_FAILURE_INFO) );
  1012. if (pRouteFailure == NULL)
  1013. {
  1014. RetVal = FALSE;
  1015. goto Exit;
  1016. }
  1017. //
  1018. // add the tiff file as the first file
  1019. // in the file name list, the owner is the fax service
  1020. //
  1021. if (FaxRouteAddFile( FaxRoute->JobId, TiffFileName, const_cast<GUID*>(&gc_FaxSvcGuid) ) < 1)
  1022. {
  1023. RetVal = FALSE;
  1024. goto Exit;
  1025. }
  1026. //
  1027. // walk thru all of the routing methods and call them
  1028. //
  1029. while ((ULONG_PTR)pNextMethod != (ULONG_PTR)&g_lstRoutingMethods)
  1030. {
  1031. BOOL bSuccess;
  1032. pRoutingMethod = CONTAINING_RECORD( pNextMethod, ROUTING_METHOD, ListEntryMethod );
  1033. pNextMethod = pRoutingMethod->ListEntryMethod.Flink;
  1034. FaxRoute->RoutingInfoData = NULL;
  1035. FaxRoute->RoutingInfoDataSize = 0;
  1036. EnterCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
  1037. pNextRoutingOverride = JobQueueEntry->RoutingDataOverride.Flink;
  1038. if (pNextRoutingOverride != NULL)
  1039. {
  1040. while ((ULONG_PTR)pNextRoutingOverride != (ULONG_PTR)&JobQueueEntry->RoutingDataOverride)
  1041. {
  1042. pRoutingDataOverride = CONTAINING_RECORD( pNextRoutingOverride, ROUTING_DATA_OVERRIDE, ListEntry );
  1043. pNextRoutingOverride = pRoutingDataOverride->ListEntry.Flink;
  1044. if (pRoutingDataOverride->RoutingMethod == pRoutingMethod)
  1045. {
  1046. FaxRoute->RoutingInfoData = (LPBYTE)MemAlloc(pRoutingDataOverride->RoutingDataSize);
  1047. if (NULL == FaxRoute->RoutingInfoData)
  1048. {
  1049. DebugPrintEx(DEBUG_ERR,
  1050. _T("MemAlloc Failed (ec: %ld)"),
  1051. GetLastError());
  1052. LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
  1053. RetVal = FALSE;
  1054. goto Exit;
  1055. }
  1056. CopyMemory (FaxRoute->RoutingInfoData,
  1057. pRoutingDataOverride->RoutingData,
  1058. pRoutingDataOverride->RoutingDataSize);
  1059. FaxRoute->RoutingInfoDataSize = pRoutingDataOverride->RoutingDataSize;
  1060. }
  1061. }
  1062. }
  1063. LeaveCriticalSection( &JobQueueEntry->CsRoutingDataOverride );
  1064. pRouteFailure[FailureCount].FailureData = NULL;
  1065. pRouteFailure[FailureCount].FailureSize = 0;
  1066. __try
  1067. {
  1068. bSuccess = pRoutingMethod->FaxRouteMethod(
  1069. FaxRoute,
  1070. &pRouteFailure[FailureCount].FailureData,
  1071. &pRouteFailure[FailureCount].FailureSize );
  1072. }
  1073. __except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, pRoutingMethod->RoutingExtension->FriendlyName, GetExceptionCode()))
  1074. {
  1075. ASSERT_FALSE;
  1076. }
  1077. if (!bSuccess)
  1078. {
  1079. WCHAR TmpStr[20] = {0};
  1080. swprintf(TmpStr,TEXT("0x%016I64x"), JobQueueEntry->UniqueId);
  1081. FaxLog(FAXLOG_CATEGORY_INBOUND,
  1082. FAXLOG_LEVEL_MIN,
  1083. 6,
  1084. MSG_FAX_ROUTE_METHOD_FAILED,
  1085. TmpStr,
  1086. JobQueueEntry->FaxRoute->DeviceName,
  1087. JobQueueEntry->FaxRoute->Tsid,
  1088. JobQueueEntry->FileName,
  1089. pRoutingMethod->RoutingExtension->FriendlyName,
  1090. pRoutingMethod->FriendlyName
  1091. );
  1092. StringFromGUID2(pRoutingMethod->Guid,
  1093. pRouteFailure[FailureCount].GuidString,
  1094. MAX_GUID_STRING_LEN);
  1095. //
  1096. // Allocate failure data using MemAlloc
  1097. //
  1098. if (pRouteFailure[FailureCount].FailureSize)
  1099. {
  1100. PVOID pOriginalFailureData = pRouteFailure[FailureCount].FailureData;
  1101. pRouteFailure[FailureCount].FailureData = MemAlloc (pRouteFailure[FailureCount].FailureSize);
  1102. if (pRouteFailure[FailureCount].FailureData)
  1103. {
  1104. CopyMemory (pRouteFailure[FailureCount].FailureData,
  1105. pOriginalFailureData,
  1106. pRouteFailure[FailureCount].FailureSize);
  1107. }
  1108. else
  1109. {
  1110. //
  1111. // Failed to allocate retry failure data - data will be lost.
  1112. //
  1113. DebugPrintEx(DEBUG_ERR,
  1114. _T("Failed to allocate failure date"));
  1115. RetVal = FALSE;
  1116. goto Exit;
  1117. }
  1118. if (!HeapFree(pRoutingMethod->RoutingExtension->HeapHandle, // handle to extension heap
  1119. 0,
  1120. pOriginalFailureData
  1121. ))
  1122. {
  1123. //
  1124. // Failed to free retry failure data from extension heap - data will be lost.
  1125. //
  1126. DebugPrintEx(DEBUG_ERR,
  1127. _T("HeapFree Failed (ec: %ld)"),
  1128. GetLastError());
  1129. RetVal = FALSE;
  1130. goto Exit;
  1131. }
  1132. }
  1133. if (0 == pRouteFailure[FailureCount].FailureSize ||
  1134. NULL == pRouteFailure[FailureCount].FailureData)
  1135. {
  1136. //
  1137. // Make sure failure data will not be freed
  1138. //
  1139. pRouteFailure[FailureCount].FailureData = NULL;
  1140. pRouteFailure[FailureCount].FailureSize = 0;
  1141. }
  1142. FailureCount++;
  1143. }
  1144. }
  1145. }
  1146. Assert (RetVal == TRUE);
  1147. Exit:
  1148. LeaveCriticalSection( &g_CsRouting );
  1149. if (pRouteFailure && FailureCount == 0)
  1150. {
  1151. //
  1152. // We do not delete the routed TIFF file here.
  1153. // RemoveReceiveJob() will take care of that.
  1154. //
  1155. MemFree( pRouteFailure );
  1156. pRouteFailure = NULL;
  1157. }
  1158. *RouteFailureInfo = pRouteFailure;
  1159. *RouteFailureCount = FailureCount;
  1160. return RetVal;
  1161. }
  1162. BOOL
  1163. LoadRouteInfo(
  1164. IN LPWSTR RouteFileName,
  1165. OUT PROUTE_INFO *RouteInfo,
  1166. OUT PROUTE_FAILURE_INFO *RouteFailure,
  1167. OUT LPDWORD RouteFailureCount
  1168. )
  1169. /*++
  1170. Routine Description:
  1171. Load routing information from a routing information file.
  1172. Arguments:
  1173. RouteFileName - Name of routing information file.
  1174. Return value:
  1175. Pointer to routing information structure if success. NULL if fail.
  1176. --*/
  1177. {
  1178. return TRUE;
  1179. }
  1180. BOOL
  1181. FaxRouteRetry(
  1182. PFAX_ROUTE FaxRoute,
  1183. PROUTE_FAILURE_INFO pRouteFailureInfo
  1184. )
  1185. {
  1186. PROUTING_METHOD RoutingMethod;
  1187. BOOL RetVal = TRUE;
  1188. DEBUG_FUNCTION_NAME(TEXT("FaxRouteRetry"));
  1189. //
  1190. // in this case, we've already retried this method and it succeeded.
  1191. //
  1192. if (!*pRouteFailureInfo->GuidString) {
  1193. return TRUE;
  1194. }
  1195. RoutingMethod = FindRoutingMethodByGuid( pRouteFailureInfo->GuidString );
  1196. if (RoutingMethod)
  1197. {
  1198. BOOL bSuccess;
  1199. PVOID pOriginalFailureData = NULL;
  1200. PVOID pFailureData = pRouteFailureInfo->FailureData;
  1201. //
  1202. // Allocate failure data using the extension heap
  1203. //
  1204. if (pRouteFailureInfo->FailureSize)
  1205. {
  1206. pOriginalFailureData = HeapAlloc (RoutingMethod->RoutingExtension->HeapHandle,
  1207. HEAP_ZERO_MEMORY,
  1208. pRouteFailureInfo->FailureSize);
  1209. if (!pOriginalFailureData)
  1210. {
  1211. DebugPrintEx(
  1212. DEBUG_ERR,
  1213. TEXT("Failed to allocate failure date")
  1214. );
  1215. return FALSE;
  1216. }
  1217. pRouteFailureInfo->FailureData = pOriginalFailureData;
  1218. CopyMemory (pRouteFailureInfo->FailureData,
  1219. pFailureData,
  1220. pRouteFailureInfo->FailureSize);
  1221. }
  1222. else
  1223. {
  1224. Assert (NULL == pRouteFailureInfo->FailureData);
  1225. }
  1226. MemFree (pFailureData);
  1227. __try
  1228. {
  1229. bSuccess = RoutingMethod->FaxRouteMethod(
  1230. FaxRoute,
  1231. &(pRouteFailureInfo->FailureData),
  1232. &(pRouteFailureInfo->FailureSize));
  1233. }
  1234. __except (HandleFaxExtensionFault(EXCEPTION_SOURCE_ROUTING_EXT, RoutingMethod->RoutingExtension->FriendlyName, GetExceptionCode()))
  1235. {
  1236. ASSERT_FALSE;
  1237. }
  1238. if (!bSuccess)
  1239. {
  1240. RetVal = FALSE;
  1241. //
  1242. // Allocate failure data using MemAlloc
  1243. //
  1244. if (pRouteFailureInfo->FailureSize)
  1245. {
  1246. pOriginalFailureData = pRouteFailureInfo->FailureData;
  1247. pRouteFailureInfo->FailureData = MemAlloc (pRouteFailureInfo->FailureSize);
  1248. if (pRouteFailureInfo->FailureData)
  1249. {
  1250. CopyMemory (pRouteFailureInfo->FailureData,
  1251. pOriginalFailureData,
  1252. pRouteFailureInfo->FailureSize);
  1253. }
  1254. else
  1255. {
  1256. //
  1257. // Failed to allocate retry failure data - data will be lost.
  1258. //
  1259. DebugPrintEx(DEBUG_ERR,
  1260. _T("Failed to allocate failure date"));
  1261. return FALSE;
  1262. }
  1263. if (!HeapFree(RoutingMethod->RoutingExtension->HeapHandle, // handle to extension heap
  1264. 0,
  1265. pOriginalFailureData
  1266. ))
  1267. {
  1268. //
  1269. // Failed to free retry failure data from extension heap - data will be lost.
  1270. //
  1271. DebugPrintEx(DEBUG_ERR,
  1272. _T("HeapFree Failed (ec: %ld)"),
  1273. GetLastError());
  1274. return FALSE;
  1275. }
  1276. }
  1277. }
  1278. else
  1279. {
  1280. //
  1281. // set the routing guid to zero so we don't try to route this guy again. He is
  1282. // deallocated when we delete the queue entry.
  1283. //
  1284. ZeroMemory(pRouteFailureInfo->GuidString, MAX_GUID_STRING_LEN*sizeof(WCHAR) );
  1285. }
  1286. if (0 == pRouteFailureInfo->FailureSize ||
  1287. NULL == pRouteFailureInfo->FailureData ||
  1288. TRUE == RetVal)
  1289. {
  1290. //
  1291. // Make sure failure data will not be freed
  1292. //
  1293. pRouteFailureInfo->FailureData = NULL;
  1294. pRouteFailureInfo->FailureSize = 0;
  1295. }
  1296. }
  1297. else
  1298. {
  1299. return FALSE;
  1300. }
  1301. return RetVal;
  1302. }
  1303. PFAX_ROUTE
  1304. SerializeFaxRoute(
  1305. PFAX_ROUTE FaxRoute,
  1306. LPDWORD Size,
  1307. BOOL bSizeOnly
  1308. )
  1309. {
  1310. DWORD ByteCount = sizeof(FAX_ROUTE);
  1311. DWORD_PTR Offset;
  1312. PFAX_ROUTE SerFaxRoute; // the serialized version
  1313. *Size = 0;
  1314. // Add the size of the strings
  1315. ByteCount += StringSize( FaxRoute->Csid );
  1316. ByteCount += StringSize( FaxRoute->Tsid );
  1317. ByteCount += StringSize( FaxRoute->CallerId );
  1318. ByteCount += StringSize( FaxRoute->RoutingInfo );
  1319. ByteCount += StringSize( FaxRoute->ReceiverName );
  1320. ByteCount += StringSize( FaxRoute->ReceiverNumber );
  1321. ByteCount += StringSize( FaxRoute->DeviceName );
  1322. ByteCount += FaxRoute->RoutingInfoDataSize;
  1323. if (bSizeOnly) {
  1324. *Size = ByteCount;
  1325. return NULL;
  1326. }
  1327. SerFaxRoute = (PFAX_ROUTE) MemAlloc( ByteCount );
  1328. if (SerFaxRoute == NULL) {
  1329. return NULL;
  1330. }
  1331. *Size = ByteCount;
  1332. CopyMemory( (PVOID) SerFaxRoute, (PVOID) FaxRoute, sizeof(FAX_ROUTE) );
  1333. Offset = sizeof( FAX_ROUTE );
  1334. StoreString( FaxRoute->Csid, (PDWORD_PTR)&SerFaxRoute->Csid, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1335. StoreString( FaxRoute->Tsid, (PDWORD_PTR)&SerFaxRoute->Tsid, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1336. StoreString( FaxRoute->CallerId, (PDWORD_PTR)&SerFaxRoute->CallerId, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1337. StoreString( FaxRoute->RoutingInfo, (PDWORD_PTR)&SerFaxRoute->RoutingInfo, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1338. StoreString( FaxRoute->ReceiverName, (PDWORD_PTR)&SerFaxRoute->ReceiverName, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1339. StoreString( FaxRoute->ReceiverNumber, (PDWORD_PTR)&SerFaxRoute->ReceiverNumber, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1340. StoreString( FaxRoute->DeviceName, (PDWORD_PTR)&SerFaxRoute->DeviceName, (LPBYTE) SerFaxRoute, &Offset, *Size);
  1341. SerFaxRoute->RoutingInfoData = (LPBYTE) Offset;
  1342. Offset += FaxRoute->RoutingInfoDataSize;
  1343. CopyMemory(
  1344. (PVOID) ((LPBYTE) &SerFaxRoute + Offset),
  1345. (PVOID) FaxRoute->RoutingInfoData,
  1346. FaxRoute->RoutingInfoDataSize
  1347. );
  1348. return SerFaxRoute;
  1349. }
  1350. PFAX_ROUTE
  1351. DeSerializeFaxRoute(
  1352. PFAX_ROUTE FaxRoute
  1353. )
  1354. {
  1355. PFAX_ROUTE NewFaxRoute = NULL;
  1356. DEBUG_FUNCTION_NAME(TEXT("DeSerializeFaxRoute"));
  1357. FixupString( FaxRoute, FaxRoute->Csid );
  1358. FixupString( FaxRoute, FaxRoute->Tsid );
  1359. FixupString( FaxRoute, FaxRoute->CallerId );
  1360. FixupString( FaxRoute, FaxRoute->RoutingInfo );
  1361. FixupString( FaxRoute, FaxRoute->ReceiverName );
  1362. FixupString( FaxRoute, FaxRoute->DeviceName );
  1363. FixupString( FaxRoute, FaxRoute->ReceiverNumber );
  1364. FaxRoute->RoutingInfoData = (LPBYTE) FaxRoute + (ULONG_PTR) FaxRoute->RoutingInfoData;
  1365. //
  1366. // Make a copy where each item is individually malloced so it can be freed properly
  1367. //
  1368. NewFaxRoute = (PFAX_ROUTE)MemAlloc( sizeof( FAX_ROUTE ) );
  1369. if (NULL == NewFaxRoute)
  1370. {
  1371. DebugPrintEx(DEBUG_ERR,TEXT("Failed to allocate FAX_ROUTE"));
  1372. return NULL;
  1373. }
  1374. ZeroMemory (NewFaxRoute, sizeof( FAX_ROUTE ));
  1375. NewFaxRoute->SizeOfStruct = sizeof( FAX_ROUTE );
  1376. NewFaxRoute->JobId = FaxRoute->JobId;
  1377. NewFaxRoute->ElapsedTime = FaxRoute->ElapsedTime;
  1378. NewFaxRoute->ReceiveTime = FaxRoute->ReceiveTime;
  1379. NewFaxRoute->PageCount = FaxRoute->PageCount;
  1380. NewFaxRoute->DeviceId = FaxRoute->DeviceId;
  1381. NewFaxRoute->RoutingInfoDataSize = FaxRoute->RoutingInfoDataSize;
  1382. int nRes;
  1383. STRING_PAIR pairs[] =
  1384. {
  1385. { (LPWSTR)FaxRoute->Csid, (LPWSTR*)&(NewFaxRoute->Csid)},
  1386. { (LPWSTR)FaxRoute->Tsid, (LPWSTR*)&(NewFaxRoute->Tsid)},
  1387. { (LPWSTR)FaxRoute->CallerId, (LPWSTR*)&(NewFaxRoute->CallerId)},
  1388. { (LPWSTR)FaxRoute->RoutingInfo, (LPWSTR*)&(NewFaxRoute->RoutingInfo)},
  1389. { (LPWSTR)FaxRoute->ReceiverName, (LPWSTR*)&(NewFaxRoute->ReceiverName)},
  1390. { (LPWSTR)FaxRoute->DeviceName, (LPWSTR*)&(NewFaxRoute->DeviceName)},
  1391. { (LPWSTR)FaxRoute->ReceiverNumber, (LPWSTR*)&(NewFaxRoute->ReceiverNumber)}
  1392. };
  1393. nRes = MultiStringDup(pairs, sizeof(pairs)/sizeof(STRING_PAIR));
  1394. if (nRes != 0)
  1395. {
  1396. // MultiStringDup takes care of freeing the memory for the pairs for which the copy succeeded
  1397. DebugPrintEx(DEBUG_ERR,TEXT("Failed to copy string with index %d"), nRes-1);
  1398. goto Error;
  1399. }
  1400. NewFaxRoute->RoutingInfoData = (LPBYTE)MemAlloc( FaxRoute->RoutingInfoDataSize );
  1401. if (NULL == NewFaxRoute->RoutingInfoData)
  1402. {
  1403. DebugPrintEx(DEBUG_ERR,TEXT("Failed to allocate RoutingInfoData"));
  1404. goto Error;
  1405. }
  1406. CopyMemory( NewFaxRoute->RoutingInfoData, FaxRoute->RoutingInfoData, FaxRoute->RoutingInfoDataSize );
  1407. return NewFaxRoute;
  1408. Error:
  1409. MemFree ((void*)NewFaxRoute->Csid);
  1410. MemFree ((void*)NewFaxRoute->Tsid);
  1411. MemFree ((void*)NewFaxRoute->CallerId);
  1412. MemFree ((void*)NewFaxRoute->RoutingInfo);
  1413. MemFree ((void*)NewFaxRoute->ReceiverName);
  1414. MemFree ((void*)NewFaxRoute->DeviceName);
  1415. MemFree ((void*)NewFaxRoute->ReceiverNumber);
  1416. MemFree ((void*)NewFaxRoute->RoutingInfoData);
  1417. MemFree ((void*)NewFaxRoute);
  1418. return NULL;
  1419. }
  1420. extern "C"
  1421. DWORD
  1422. GetRecieptsConfiguration(
  1423. PFAX_SERVER_RECEIPTS_CONFIGW* ppServerRecieptConfig,
  1424. BOOL bNeedNTLMToken
  1425. )
  1426. /*++
  1427. Routine name : GetRecieptsConfiguration
  1428. Routine description:
  1429. Private callback used by MS Routing Extension to get the server reciept configuration. Also used by the service SendReceipt()
  1430. Used to get a copy of the receipts configuration.
  1431. Author:
  1432. Oded Sacher (OdedS), Mar, 2001
  1433. Arguments:
  1434. ppServerRecieptConfig [out] - Address to a pointer to a private server reciepts configuration struct.
  1435. The caller should free the resources by calling FreeRecieptsConfiguration()
  1436. bNeedNTLMToken [in] - If TRUE, the caller is interested in the user token for NTLM authentication
  1437. for SMTP connections. The token is returned in the hLoggedOnUser member
  1438. of the FAX_SERVER_RECEIPTS_CONFIGW structure.
  1439. if FALSE, the caller is only interested in the receipts configuration and
  1440. is not about to perform any activity based on that configration
  1441. (such as sending mail via CDO2).
  1442. Return Value:
  1443. Win32 error code
  1444. --*/
  1445. {
  1446. HKEY hReceiptsKey = NULL;
  1447. DWORD dwRes = ERROR_SUCCESS;
  1448. PFAX_SERVER_RECEIPTS_CONFIGW pServerRecieptConfig = NULL;
  1449. DEBUG_FUNCTION_NAME(TEXT("GetRecieptsConfiguration"));
  1450. Assert (ppServerRecieptConfig);
  1451. pServerRecieptConfig = (PFAX_SERVER_RECEIPTS_CONFIGW)MemAlloc(sizeof(FAX_SERVER_RECEIPTS_CONFIGW));
  1452. if (NULL == pServerRecieptConfig)
  1453. {
  1454. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  1455. return ERROR_NOT_ENOUGH_MEMORY;
  1456. }
  1457. ZeroMemory (pServerRecieptConfig, sizeof(FAX_SERVER_RECEIPTS_CONFIGW));
  1458. EnterCriticalSection (&g_CsConfig);
  1459. pServerRecieptConfig->dwSizeOfStruct = sizeof (FAX_SERVER_RECEIPTS_CONFIGW);
  1460. pServerRecieptConfig->bIsToUseForMSRouteThroughEmailMethod = g_ReceiptsConfig.bIsToUseForMSRouteThroughEmailMethod;
  1461. pServerRecieptConfig->dwSMTPPort = g_ReceiptsConfig.dwSMTPPort;
  1462. pServerRecieptConfig->dwAllowedReceipts = g_ReceiptsConfig.dwAllowedReceipts;
  1463. pServerRecieptConfig->SMTPAuthOption = g_ReceiptsConfig.SMTPAuthOption;
  1464. pServerRecieptConfig->lptstrReserved = NULL;
  1465. if (NULL != g_ReceiptsConfig.lptstrSMTPServer &&
  1466. NULL == (pServerRecieptConfig->lptstrSMTPServer = StringDup(g_ReceiptsConfig.lptstrSMTPServer)))
  1467. {
  1468. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1469. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  1470. goto exit;
  1471. }
  1472. if (NULL != g_ReceiptsConfig.lptstrSMTPFrom &&
  1473. NULL == (pServerRecieptConfig->lptstrSMTPFrom = StringDup(g_ReceiptsConfig.lptstrSMTPFrom)))
  1474. {
  1475. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1476. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  1477. goto exit;
  1478. }
  1479. if (NULL != g_ReceiptsConfig.lptstrSMTPUserName &&
  1480. NULL == (pServerRecieptConfig->lptstrSMTPUserName = StringDup(g_ReceiptsConfig.lptstrSMTPUserName)))
  1481. {
  1482. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1483. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  1484. goto exit;
  1485. }
  1486. //
  1487. // Read stored password
  1488. //
  1489. hReceiptsKey = OpenRegistryKey(
  1490. HKEY_LOCAL_MACHINE,
  1491. REGKEY_SOFTWARE TEXT("\\") REGKEY_RECEIPTS_CONFIG,
  1492. FALSE,
  1493. KEY_READ | KEY_WRITE);
  1494. if (NULL == hReceiptsKey)
  1495. {
  1496. dwRes = GetLastError ();
  1497. DebugPrintEx(
  1498. DEBUG_ERR,
  1499. TEXT("OpenRegistryKey failed. (ec=%lu)"),
  1500. dwRes);
  1501. goto exit;
  1502. }
  1503. if ( NULL == (pServerRecieptConfig->lptstrSMTPPassword = GetRegistrySecureString(hReceiptsKey, REGVAL_RECEIPTS_PASSWORD, EMPTY_STRING, TRUE, NULL) ) )
  1504. {
  1505. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  1506. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  1507. goto exit;
  1508. }
  1509. if (bNeedNTLMToken &&
  1510. FAX_SMTP_AUTH_NTLM == g_ReceiptsConfig.SMTPAuthOption)
  1511. {
  1512. //
  1513. // User needs the NTLM token and NTLM authentication is configured.
  1514. //
  1515. HANDLE hDupToken;
  1516. if (NULL == g_ReceiptsConfig.hLoggedOnUser)
  1517. {
  1518. HANDLE hLoggedOnUserToken;
  1519. WCHAR wszUser[CREDUI_MAX_USERNAME_LENGTH] = {0};
  1520. WCHAR wszDomain[CREDUI_MAX_DOMAIN_TARGET_LENGTH] = {0};
  1521. //
  1522. // Parse user name into user name and domain
  1523. //
  1524. dwRes = CredUIParseUserName (g_ReceiptsConfig.lptstrSMTPUserName,
  1525. wszUser,
  1526. ARR_SIZE(wszUser),
  1527. wszDomain,
  1528. ARR_SIZE(wszDomain));
  1529. if (ERROR_SUCCESS != dwRes)
  1530. {
  1531. DebugPrintEx(
  1532. DEBUG_ERR,
  1533. TEXT("CredUIParseUserName failed. (ec: %ld)"),
  1534. dwRes);
  1535. goto exit;
  1536. }
  1537. //
  1538. // We get the a logged on user token
  1539. //
  1540. if (!LogonUser (wszUser,
  1541. wszDomain,
  1542. pServerRecieptConfig->lptstrSMTPPassword,
  1543. LOGON32_LOGON_INTERACTIVE,
  1544. LOGON32_PROVIDER_DEFAULT,
  1545. &hLoggedOnUserToken))
  1546. {
  1547. dwRes = GetLastError();
  1548. DebugPrintEx(
  1549. DEBUG_ERR,
  1550. TEXT("LogonUser failed. (ec: %ld)"),
  1551. dwRes);
  1552. goto exit;
  1553. }
  1554. g_ReceiptsConfig.hLoggedOnUser = hLoggedOnUserToken;
  1555. }
  1556. //
  1557. // Duplicate that Token
  1558. //
  1559. if (!DuplicateToken(g_ReceiptsConfig.hLoggedOnUser, // Source token
  1560. SecurityDelegation, // The server process can impersonate the client's security context on remote systems
  1561. &hDupToken)) // Duplicate token
  1562. {
  1563. dwRes = GetLastError();
  1564. DebugPrintEx(
  1565. DEBUG_ERR,
  1566. TEXT("DuplicateToken failed. (ec: %ld)"),
  1567. dwRes);
  1568. goto exit;
  1569. }
  1570. pServerRecieptConfig->hLoggedOnUser = hDupToken;
  1571. }
  1572. *ppServerRecieptConfig = pServerRecieptConfig;
  1573. Assert (ERROR_SUCCESS == dwRes);
  1574. exit:
  1575. LeaveCriticalSection (&g_CsConfig);
  1576. if (NULL != hReceiptsKey)
  1577. {
  1578. DWORD ec = RegCloseKey(hReceiptsKey);
  1579. if (ERROR_SUCCESS != ec)
  1580. {
  1581. DebugPrintEx(
  1582. DEBUG_ERR,
  1583. TEXT("RegCloseKey failed (ec: %lu)"),
  1584. ec);
  1585. }
  1586. }
  1587. if (ERROR_SUCCESS != dwRes)
  1588. {
  1589. FreeRecieptsConfiguration( pServerRecieptConfig, TRUE);
  1590. }
  1591. return dwRes;
  1592. } // GetRecieptsConfiguration
  1593. extern "C"
  1594. void
  1595. FreeRecieptsConfiguration(
  1596. PFAX_SERVER_RECEIPTS_CONFIGW pServerRecieptConfig,
  1597. BOOL fDestroy
  1598. )
  1599. /*++
  1600. Routine name : FreeRecieptsConfiguration
  1601. Routine description:
  1602. Private callback used by MS Routing Extension to get the server reciept configuration.
  1603. Used by the extension to decide on the authentication when sending mail.
  1604. Author:
  1605. Oded Sacher (OdedS), Mar, 2001
  1606. Arguments:
  1607. pServerRecieptConfig [in ] - Pointer to a private server reciepts configuration struct to be freed.
  1608. fDestroy [in ] - TRUE if to free the struct as well
  1609. Return Value:
  1610. Win32 error code
  1611. --*/
  1612. {
  1613. DEBUG_FUNCTION_NAME(TEXT("FreeRecieptsConfiguration"));
  1614. Assert (pServerRecieptConfig);
  1615. MemFree(pServerRecieptConfig->lptstrSMTPServer);
  1616. pServerRecieptConfig->lptstrSMTPServer = NULL;
  1617. MemFree(pServerRecieptConfig->lptstrSMTPFrom);
  1618. pServerRecieptConfig->lptstrSMTPFrom = NULL;
  1619. MemFree(pServerRecieptConfig->lptstrSMTPUserName);
  1620. pServerRecieptConfig->lptstrSMTPUserName = NULL;
  1621. if (NULL != pServerRecieptConfig->lptstrSMTPPassword)
  1622. {
  1623. SecureZeroMemory(pServerRecieptConfig->lptstrSMTPPassword, _tcslen(pServerRecieptConfig->lptstrSMTPPassword)*sizeof(TCHAR));
  1624. MemFree(pServerRecieptConfig->lptstrSMTPPassword);
  1625. pServerRecieptConfig->lptstrSMTPPassword = NULL;
  1626. }
  1627. if (NULL != pServerRecieptConfig->hLoggedOnUser )
  1628. {
  1629. if (!CloseHandle(pServerRecieptConfig->hLoggedOnUser))
  1630. {
  1631. DebugPrintEx(
  1632. DEBUG_ERR,
  1633. TEXT("CloseHandle failed. (ec: %ld)"),
  1634. GetLastError());
  1635. }
  1636. pServerRecieptConfig->hLoggedOnUser = NULL;
  1637. }
  1638. if (TRUE == fDestroy)
  1639. {
  1640. MemFree (pServerRecieptConfig);
  1641. }
  1642. return;
  1643. }