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.

1203 lines
34 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. faxapi.c
  5. Abstract:
  6. This module contains the Win32 FAX APIs.
  7. The function implemented here are simply very
  8. thin wrappers around the RPC stubs. The wrappers
  9. are necessary so that the last error value
  10. is set properly.
  11. Author:
  12. Wesley Witt (wesw) 16-Jan-1996
  13. Revision History:
  14. --*/
  15. #include "faxapi.h"
  16. #pragma hdrstop
  17. static
  18. DWORD
  19. ConnectToFaxServer(
  20. PHANDLE_ENTRY pHandleEntry,
  21. PFAX_HANDLE_DATA pFaxData
  22. )
  23. /*++
  24. Routine Description:
  25. Helper function that wrap RPC call for connecting to the fax service.
  26. The function first attempt to call FAX_ConnectFaxServer in order to connect to .NET or XP fax servers,
  27. if the call fails with RPC_S_PROCNUM_OUT_OF_RANGE, that indicates that we are dealing with BOS 2000, we try
  28. to connect to BOS fax server with FAX_ConnectionRefCount.
  29. Arguments:
  30. pHandleEntry - [in/out] pointer to fax service handle entry.
  31. the function will use the binding handle and update the context handle.
  32. pFaxData - [in/out] pointer to fax handle data.
  33. the function will update the server's API version within this handle data
  34. Return Value:
  35. Win32 error code
  36. --*/
  37. {
  38. DWORD dwRes = ERROR_SUCCESS;
  39. DEBUG_FUNCTION_NAME(TEXT("ConnectToFaxServer"));
  40. Assert (pHandleEntry);
  41. Assert (pFaxData);
  42. __try
  43. {
  44. dwRes = FAX_ConnectFaxServer( FH_FAX_HANDLE(pHandleEntry), // Binding handle
  45. CURRENT_FAX_API_VERSION, // Our API version
  46. &(pFaxData->dwReportedServerAPIVersion), // Server's API version
  47. &FH_CONTEXT_HANDLE(pHandleEntry)); // Server's context handle
  48. }
  49. __except (EXCEPTION_EXECUTE_HANDLER)
  50. {
  51. //
  52. // For some reason we crashed.
  53. //
  54. dwRes = GetExceptionCode();
  55. }
  56. if (ERROR_SUCCESS != dwRes)
  57. {
  58. if (RPC_S_PROCNUM_OUT_OF_RANGE == dwRes)
  59. {
  60. //
  61. // Got "The procedure number is out of range.".
  62. // This is because we're trying to call an RPC function which doesn't exist in BOS 2000 Fax server.
  63. // Try the 'old' FaxConnectionRefCount() call
  64. //
  65. DWORD dwShare; // Igonred
  66. __try
  67. {
  68. dwRes = FAX_ConnectionRefCount( FH_FAX_HANDLE(pHandleEntry),
  69. &FH_CONTEXT_HANDLE(pHandleEntry),
  70. 1,
  71. &dwShare);
  72. }
  73. __except (EXCEPTION_EXECUTE_HANDLER)
  74. {
  75. //
  76. // For some reason we crashed.
  77. //
  78. dwRes = GetExceptionCode();
  79. }
  80. if (ERROR_SUCCESS == dwRes)
  81. {
  82. //
  83. // Hooray!!! This is a BOS 2000 Fax Server
  84. //
  85. pFaxData->dwReportedServerAPIVersion = FAX_API_VERSION_0;
  86. }
  87. else
  88. {
  89. DebugPrintEx(
  90. DEBUG_ERR,
  91. TEXT("Exception on RPC call to FAX_ConnectionRefCount. (ec: %lu)"),
  92. dwRes);
  93. DumpRPCExtendedStatus ();
  94. }
  95. }
  96. else
  97. {
  98. DebugPrintEx(
  99. DEBUG_ERR,
  100. TEXT("Exception on RPC call to FAX_ConnectFaxServer. (ec: %lu)"),
  101. dwRes);
  102. DumpRPCExtendedStatus ();
  103. }
  104. }
  105. return dwRes;
  106. } // ConnectToFaxServer
  107. //
  108. // Note: the name of this function is actually a macro that expands to FaxConnectFaxServerW
  109. // or FaxConnectFaxServerA depnding on the UNICODE macro.
  110. //
  111. BOOL
  112. WINAPI
  113. FaxConnectFaxServer(
  114. IN LPCTSTR lpMachineName OPTIONAL,
  115. OUT LPHANDLE FaxHandle
  116. )
  117. /*++
  118. Routine Description:
  119. Creates a connection to a FAX server. The binding handle that is
  120. returned is used for all subsequent FAX API calls.
  121. Arguments:
  122. lpMachineName - Machine name, NULL, or "."
  123. FaxHandle - Pointer to a FAX handle
  124. Return Value:
  125. TRUE - Success
  126. FALSE - Failure, call GetLastError() for more error information.
  127. --*/
  128. {
  129. PFAX_HANDLE_DATA pFaxData = NULL;
  130. PHANDLE_ENTRY pHandleEntry = NULL;
  131. DWORD dwRes = ERROR_SUCCESS;
  132. BOOL bLocalConnection = IsLocalMachineName (lpMachineName);
  133. DEBUG_FUNCTION_NAME(TEXT("FaxConnectFaxServer"));
  134. if (!FaxHandle)
  135. {
  136. SetLastError(ERROR_INVALID_PARAMETER);
  137. DebugPrintEx(DEBUG_ERR, _T("FaxHandle is NULL."));
  138. return FALSE;
  139. }
  140. pFaxData = (PFAX_HANDLE_DATA)MemAlloc( sizeof(FAX_HANDLE_DATA) );
  141. if (!pFaxData)
  142. {
  143. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  144. DebugPrintEx(DEBUG_ERR, _T("MemAlloc is failed."));
  145. return FALSE;
  146. }
  147. ZeroMemory (pFaxData, sizeof(FAX_HANDLE_DATA));
  148. pFaxData->bLocalConnection = bLocalConnection;
  149. InitializeListHead( &pFaxData->HandleTableListHead );
  150. //
  151. // Create new Service handle, in case of an error
  152. // after this function succeeded cleanup code must call CloseFaxHandle()
  153. //
  154. pHandleEntry = CreateNewServiceHandle( pFaxData );
  155. if (!pHandleEntry)
  156. {
  157. dwRes = GetLastError ();
  158. DebugPrintEx(DEBUG_ERR, _T("CreateNewServiceHandle() failed."));
  159. MemFree(pFaxData);
  160. return FALSE;
  161. }
  162. dwRes = FaxClientBindToFaxServer( lpMachineName, FAX_RPC_ENDPOINT, NULL, &pFaxData->FaxHandle );
  163. if (ERROR_SUCCESS != dwRes)
  164. {
  165. DebugPrintEx(DEBUG_ERR, _T("FaxClientBindToFaxServer() failed with %ld."), dwRes);
  166. pFaxData->FaxHandle = NULL;
  167. goto ErrorExit;
  168. }
  169. if (!bLocalConnection)
  170. {
  171. //
  172. // This is not the local machine, Remove all \\ from machine name
  173. //
  174. LPCTSTR lpctstrDelim = _tcsrchr(lpMachineName, TEXT('\\'));
  175. if (NULL == lpctstrDelim)
  176. {
  177. lpctstrDelim = lpMachineName;
  178. }
  179. else
  180. {
  181. lpctstrDelim = _tcsinc(lpctstrDelim);
  182. }
  183. pFaxData->MachineName = StringDup (lpctstrDelim);
  184. if (!pFaxData->MachineName)
  185. {
  186. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  187. goto ErrorExit;
  188. }
  189. }
  190. //
  191. // Ask for the highest level of privacy (autnetication + encryption)
  192. //
  193. dwRes = RpcBindingSetAuthInfo (
  194. FH_FAX_HANDLE(pHandleEntry), // RPC binding handle
  195. RPC_SERVER_PRINCIPAL_NAME, // Server principal name
  196. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, // Authentication level - fullest
  197. // Authenticates, verifies, and privacy-encrypts the arguments passed
  198. // to every remote call.
  199. RPC_C_AUTHN_WINNT, // Authentication service (NTLMSSP)
  200. NULL, // Authentication identity - use currently logged on user
  201. 0); // Unused when Authentication service == RPC_C_AUTHN_WINNT
  202. if (ERROR_SUCCESS != dwRes)
  203. {
  204. //
  205. // Couldn't set RPC authentication mode
  206. //
  207. DebugPrintEx(
  208. DEBUG_ERR,
  209. TEXT("RpcBindingSetAuthInfo (RPC_C_AUTHN_LEVEL_PKT_PRIVACY) failed. (ec: %ld)"),
  210. dwRes);
  211. goto ErrorExit;
  212. }
  213. //
  214. // On local connections make sure that the fax service is up
  215. //
  216. if (bLocalConnection)
  217. {
  218. if (!EnsureFaxServiceIsStarted (NULL))
  219. {
  220. dwRes = GetLastError ();
  221. DebugPrintEx(
  222. DEBUG_ERR,
  223. TEXT("EnsureFaxServiceIsStarted failed (ec = %ld"),
  224. dwRes);
  225. goto ErrorExit;
  226. }
  227. else
  228. {
  229. //
  230. // Wait till the RPC service is up an running
  231. //
  232. if (!WaitForServiceRPCServer (60 * 1000))
  233. {
  234. dwRes = GetLastError ();
  235. DebugPrintEx(
  236. DEBUG_ERR,
  237. TEXT("WaitForServiceRPCServer failed (ec = %ld"),
  238. dwRes);
  239. goto ErrorExit;
  240. }
  241. }
  242. }
  243. //
  244. // Here we tries to connect to the Fax service.
  245. //
  246. // We try to connect three times, two times using RPC_C_AUTHN_LEVEL_PKT_PRIVACY Authentication level
  247. // and if we fail we drop to RPC_C_AUTHN_LEVEL_NONE Authentication level.
  248. //
  249. // We try twice with RPC_C_AUTHN_LEVEL_PKT_PRIVACY authentication level, because RPC runtime infrastructure might cache
  250. // the service handle, and if the service was restarted the first RPC call will use the old cached data, and will fail.
  251. // RPC cannot internally retry because we dealling with privacy authentication and thus we do the retry.
  252. //
  253. // If we fail to connect twice we drop the authentication level and retry. This is done to allow .NET clients to connect to
  254. // Fax servers that does not use a secure channel.
  255. // We do not need to retry the connection, beacuse RPC will do that internally.
  256. //
  257. dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
  258. if (dwRes != ERROR_SUCCESS)
  259. {
  260. DebugPrintEx (DEBUG_WRN,
  261. TEXT("fisrt call to ConnectToFaxServer failed with - %lu"),
  262. dwRes);
  263. dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
  264. if (dwRes != ERROR_SUCCESS)
  265. {
  266. //
  267. // We failed twice, Drop authentication level and retry.
  268. //
  269. DebugPrintEx (DEBUG_WRN,
  270. TEXT("second call to ConnectToFaxServer failed with - %lu"),
  271. dwRes);
  272. DebugPrintEx (DEBUG_WRN,
  273. TEXT("Warning!!! not using encryption anymore against remote server %s"),
  274. lpMachineName);
  275. dwRes = RpcBindingSetAuthInfo (
  276. FH_FAX_HANDLE(pHandleEntry), // RPC binding handle
  277. RPC_SERVER_PRINCIPAL_NAME, // Server principal name
  278. RPC_C_AUTHN_LEVEL_NONE, // Authentication level - none
  279. RPC_C_AUTHN_WINNT, // Authentication service (NTLMSSP)
  280. NULL, // Authentication identity - use currently logged on user
  281. 0); // Unused when Authentication service == RPC_C_AUTHN_WINNT
  282. if (ERROR_SUCCESS != dwRes)
  283. {
  284. //
  285. // Couldn't set RPC authentication mode
  286. //
  287. DebugPrintEx(
  288. DEBUG_ERR,
  289. TEXT("RpcBindingSetAuthInfo (RPC_C_AUTHN_LEVEL_NONE) failed. (ec: %lu)"),
  290. dwRes);
  291. goto ErrorExit;
  292. }
  293. dwRes = ConnectToFaxServer(pHandleEntry,pFaxData);
  294. if (ERROR_SUCCESS != dwRes)
  295. {
  296. DebugPrintEx (DEBUG_ERR,
  297. TEXT("third call to ConnectToFaxServer failed with - %lu"),
  298. dwRes);
  299. goto ErrorExit;
  300. }
  301. }
  302. }
  303. if (ERROR_SUCCESS == dwRes)
  304. {
  305. //
  306. // Succeeded to connect
  307. //
  308. pFaxData->dwServerAPIVersion = pFaxData->dwReportedServerAPIVersion;
  309. if (pFaxData->dwReportedServerAPIVersion > CURRENT_FAX_API_VERSION)
  310. {
  311. //
  312. // This is the filtering.
  313. // Assume we're talking to a Windows XP server since we have no knowledge of future servers.
  314. //
  315. pFaxData->dwServerAPIVersion = CURRENT_FAX_API_VERSION;
  316. }
  317. *FaxHandle = (LPHANDLE) pHandleEntry;
  318. return TRUE;
  319. }
  320. ErrorExit:
  321. Assert (ERROR_SUCCESS != dwRes);
  322. if (NULL != pFaxData)
  323. {
  324. if (NULL != pFaxData->FaxHandle)
  325. {
  326. RpcBindingFree(&pFaxData->FaxHandle);
  327. }
  328. }
  329. //
  330. // clean up for CreateNewServiceHandle
  331. //
  332. CloseFaxHandle ( pHandleEntry );
  333. SetLastError(dwRes);
  334. return FALSE;
  335. } // FaxConnectFaxServer
  336. #ifdef UNICODE
  337. BOOL
  338. WINAPI
  339. FaxConnectFaxServerA(
  340. IN LPCSTR lpMachineName OPTIONAL,
  341. OUT LPHANDLE FaxHandle
  342. )
  343. /*++
  344. Routine Description:
  345. Creates a connection to a FAX server. The binding handle that is
  346. returned is used for all subsequent FAX API calls.
  347. Arguments:
  348. MachineName - Machine name, NULL, or "."
  349. FaxHandle - Pointer to a FAX handle
  350. Return Value:
  351. TRUE - Success
  352. FALSE - Failure, call GetLastError() for more error information.
  353. --*/
  354. {
  355. PWCHAR lpwstrMachineName = NULL;
  356. BOOL bRes;
  357. DEBUG_FUNCTION_NAME(TEXT("FaxConnectFaxServerA"));
  358. if (lpMachineName)
  359. {
  360. //
  361. // Create Unicode machine name
  362. //
  363. lpwstrMachineName = AnsiStringToUnicodeString (lpMachineName);
  364. if (!lpwstrMachineName)
  365. {
  366. return FALSE;
  367. }
  368. }
  369. bRes = FaxConnectFaxServerW (lpwstrMachineName, FaxHandle);
  370. MemFree (lpwstrMachineName);
  371. return bRes;
  372. } // FaxConnectFaxServerA
  373. #else
  374. //
  375. // When compiling this code to ANSI we do not want to support the Unicode version.
  376. //
  377. BOOL
  378. WINAPI
  379. FaxConnectFaxServerW(
  380. IN LPCWSTR lpMachineName OPTIONAL,
  381. OUT LPHANDLE FaxHandle
  382. )
  383. {
  384. UNREFERENCED_PARAMETER(lpMachineName);
  385. UNREFERENCED_PARAMETER(FaxHandle);
  386. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  387. return FALSE;
  388. }
  389. #endif
  390. BOOL
  391. WINAPI
  392. FaxGetDeviceStatusW(
  393. IN const HANDLE FaxHandle,
  394. OUT PFAX_DEVICE_STATUSW *DeviceStatus
  395. )
  396. /*++
  397. Routine Description:
  398. Obtains a status report for the FAX devices being
  399. used by the FAX server.
  400. Arguments:
  401. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  402. StatusBuffer - Buffer for the status data
  403. BufferSize - Size of the StatusBuffer
  404. Return Value:
  405. TRUE - Success
  406. FALSE - Failure, call GetLastError() for more error information.
  407. --*/
  408. {
  409. #define FixupString(_s) FixupStringPtrW(DeviceStatus,_s)
  410. error_status_t ec;
  411. DWORD BufferSize = 0;
  412. DEBUG_FUNCTION_NAME(TEXT("FaxGetDeviceStatusW"));
  413. if (!ValidateFaxHandle(FaxHandle, FHT_PORT)) {
  414. SetLastError(ERROR_INVALID_HANDLE);
  415. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  416. return FALSE;
  417. }
  418. if (!DeviceStatus) {
  419. SetLastError(ERROR_INVALID_PARAMETER);
  420. DebugPrintEx(DEBUG_ERR, _T("DeviceStatus is NULL."));
  421. return FALSE;
  422. }
  423. *DeviceStatus = NULL;
  424. __try
  425. {
  426. ec = FAX_GetDeviceStatus(
  427. FH_PORT_HANDLE(FaxHandle),
  428. (LPBYTE*)DeviceStatus,
  429. &BufferSize
  430. );
  431. }
  432. __except (EXCEPTION_EXECUTE_HANDLER)
  433. {
  434. //
  435. // For some reason we crashed.
  436. //
  437. ec = GetExceptionCode();
  438. DebugPrintEx(
  439. DEBUG_ERR,
  440. TEXT("Exception on RPC call to FAX_GetDeviceStatus. (ec: %ld)"),
  441. ec);
  442. }
  443. if (ec)
  444. {
  445. DumpRPCExtendedStatus ();
  446. SetLastError( ec );
  447. return FALSE;
  448. }
  449. FixupString( (*DeviceStatus)->CallerId );
  450. FixupString( (*DeviceStatus)->Csid );
  451. FixupString( (*DeviceStatus)->DeviceName );
  452. FixupString( (*DeviceStatus)->DocumentName );
  453. FixupString( (*DeviceStatus)->PhoneNumber );
  454. FixupString( (*DeviceStatus)->RoutingString );
  455. FixupString( (*DeviceStatus)->SenderName );
  456. FixupString( (*DeviceStatus)->RecipientName );
  457. FixupString( (*DeviceStatus)->StatusString );
  458. FixupString( (*DeviceStatus)->Tsid );
  459. FixupString( (*DeviceStatus)->UserName );
  460. return TRUE;
  461. }
  462. BOOL
  463. WINAPI
  464. FaxGetDeviceStatusA(
  465. IN const HANDLE FaxHandle,
  466. OUT PFAX_DEVICE_STATUSA *DeviceStatus
  467. )
  468. /*++
  469. Routine Description:
  470. Obtains a status report for the FAX devices being
  471. used by the FAX server.
  472. Arguments:
  473. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  474. StatusBuffer - Buffer for the status data
  475. BufferSize - Size of the StatusBuffer
  476. Return Value:
  477. TRUE - Success
  478. FALSE - Failure, call GetLastError() for more error information.
  479. --*/
  480. {
  481. //
  482. // no need to validate parameters, FaxGetDeviceStatusW() will do that
  483. //
  484. DEBUG_FUNCTION_NAME(TEXT("FaxGetDeviceStatusA"));
  485. if (!FaxGetDeviceStatusW( FaxHandle, (PFAX_DEVICE_STATUSW *)DeviceStatus ))
  486. {
  487. return FALSE;
  488. }
  489. if (!ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->CallerId ) ||
  490. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Csid ) ||
  491. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DeviceName ) ||
  492. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DocumentName ) ||
  493. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->PhoneNumber ) ||
  494. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RoutingString ) ||
  495. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->SenderName ) ||
  496. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RecipientName ) ||
  497. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->StatusString ) ||
  498. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Tsid ) ||
  499. !ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->UserName ))
  500. {
  501. DebugPrintEx(DEBUG_ERR, _T("ConvertUnicodeStringInPlace failed, ec = %ld."), GetLastError());
  502. MemFree (*DeviceStatus);
  503. return FALSE;
  504. }
  505. (*DeviceStatus)->SizeOfStruct = sizeof(FAX_DEVICE_STATUSA);
  506. return TRUE;
  507. } // FaxGetDeviceStatusA
  508. BOOL
  509. WINAPI
  510. FaxClose(
  511. IN const HANDLE FaxHandle
  512. )
  513. {
  514. error_status_t ec;
  515. PHANDLE_ENTRY pHandleEntry = (PHANDLE_ENTRY) FaxHandle;
  516. HANDLE TmpFaxPortHandle;
  517. DWORD CanShare;
  518. DEBUG_FUNCTION_NAME(TEXT("FaxClose"));
  519. if (!FaxHandle || IsBadReadPtr ((LPVOID)FaxHandle, sizeof (HANDLE_ENTRY)))
  520. {
  521. SetLastError(ERROR_INVALID_HANDLE);
  522. DebugPrintEx(DEBUG_ERR, _T("!FaxHandle || IsBadReadPtr(FaxHandle)."));
  523. return FALSE;
  524. }
  525. switch (pHandleEntry->Type)
  526. {
  527. case FHT_SERVICE:
  528. __try
  529. {
  530. ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(FaxHandle), &FH_CONTEXT_HANDLE(FaxHandle), 0, &CanShare );
  531. }
  532. __except (EXCEPTION_EXECUTE_HANDLER)
  533. {
  534. //
  535. // For some reason we crashed.
  536. //
  537. ec = GetExceptionCode();
  538. DebugPrintEx(
  539. DEBUG_ERR,
  540. TEXT("Exception on RPC call to FAX_ConnectionRefCount. (ec: %ld)"),
  541. ec);
  542. }
  543. if (ERROR_SUCCESS != ec)
  544. {
  545. DumpRPCExtendedStatus ();
  546. }
  547. __try
  548. {
  549. ec = FaxClientUnbindFromFaxServer( (RPC_BINDING_HANDLE *) pHandleEntry->FaxData->FaxHandle );
  550. }
  551. __except (EXCEPTION_EXECUTE_HANDLER)
  552. {
  553. ec = GetExceptionCode();
  554. }
  555. EnterCriticalSection( &pHandleEntry->FaxData->CsHandleTable );
  556. //
  557. // Zero the binding handle so that no further RPC calls will be made with floating handles
  558. // that still hold the FAX_HANDLE_DATA (e.g. from FaxOpenPort).
  559. //
  560. pHandleEntry->FaxData->FaxHandle = 0;
  561. #if DBG
  562. if (pHandleEntry->FaxData->dwRefCount > 1)
  563. {
  564. //
  565. // The user closed the binding handle (called FaxClose (hFax)) before closing all context
  566. // handles (e.g. FaxClose (hPort)).
  567. // This is not a real problem - the reference count mechanism will take care of it.
  568. //
  569. DebugPrintEx(
  570. DEBUG_WRN,
  571. TEXT("User called FaxClose with a service handle but still has live context handles (port or message enum)"));
  572. }
  573. #endif
  574. LeaveCriticalSection( &pHandleEntry->FaxData->CsHandleTable );
  575. CloseFaxHandle ( pHandleEntry );
  576. return TRUE;
  577. case FHT_PORT:
  578. TmpFaxPortHandle = pHandleEntry->hGeneric;
  579. CloseFaxHandle( pHandleEntry );
  580. __try
  581. {
  582. ec = FAX_ClosePort( &TmpFaxPortHandle );
  583. }
  584. __except (EXCEPTION_EXECUTE_HANDLER)
  585. {
  586. //
  587. // For some reason we crashed.
  588. //
  589. ec = GetExceptionCode();
  590. DebugPrintEx(
  591. DEBUG_ERR,
  592. TEXT("Exception on RPC call to FAX_ClosePort. (ec: %ld)"),
  593. ec);
  594. }
  595. if (ec)
  596. {
  597. DumpRPCExtendedStatus ();
  598. SetLastError( ec );
  599. return FALSE;
  600. }
  601. break;
  602. default:
  603. SetLastError( ERROR_INVALID_HANDLE );
  604. return FALSE;
  605. }
  606. return TRUE;
  607. }
  608. BOOL
  609. WINAPI
  610. FaxGetSecurityEx(
  611. IN HANDLE hFaxHandle,
  612. IN SECURITY_INFORMATION SecurityInformation,
  613. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  614. )
  615. /*++
  616. Routine name : FaxGetSecurityEx
  617. Routine description:
  618. Gets the server's security descriptor
  619. Author:
  620. Eran Yariv (EranY), Nov, 1999
  621. Arguments:
  622. hFaxHandle [in ] - Handle to fax server
  623. SECURITY_INFORMATION [in ] - Defines the desired entries in the security descriptor (Bit wise OR )
  624. ppSecurityDescriptor [out] - Pointer to receive buffer
  625. Return Value:
  626. TRUE - Success
  627. FALSE - Failure, call GetLastError() for more error information.
  628. --*/
  629. {
  630. error_status_t ec;
  631. DWORD BufferSize = 0;
  632. DEBUG_FUNCTION_NAME(TEXT("FaxGetSecurityEx"));
  633. DWORD dwSecInfo = ( OWNER_SECURITY_INFORMATION |
  634. GROUP_SECURITY_INFORMATION |
  635. DACL_SECURITY_INFORMATION |
  636. SACL_SECURITY_INFORMATION );
  637. if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
  638. {
  639. SetLastError(ERROR_INVALID_HANDLE);
  640. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  641. return FALSE;
  642. }
  643. if (0 == (SecurityInformation & dwSecInfo))
  644. {
  645. SetLastError( ERROR_INVALID_PARAMETER );
  646. DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - No valid bit type indicated"));
  647. return FALSE;
  648. }
  649. if (0 != (SecurityInformation & ~dwSecInfo))
  650. {
  651. SetLastError( ERROR_INVALID_PARAMETER );
  652. DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - contains invalid securtiy information bits"));
  653. return FALSE;
  654. }
  655. if (!ppSecurityDescriptor)
  656. {
  657. SetLastError(ERROR_INVALID_PARAMETER);
  658. DebugPrintEx(DEBUG_ERR, _T("ppSecurityDescriptor is NULL."));
  659. return FALSE;
  660. }
  661. if (FAX_API_VERSION_1 > FH_SERVER_VER(hFaxHandle))
  662. {
  663. //
  664. // Servers of API version 0 don't support FAX_GetSecurityEx
  665. //
  666. DebugPrintEx(DEBUG_MSG,
  667. _T("Server version is %ld - doesn't support FAX_GetSecurityEx."),
  668. FH_SERVER_VER(hFaxHandle));
  669. __try
  670. {
  671. ec = FAX_GetSecurity (
  672. FH_FAX_HANDLE(hFaxHandle),
  673. (LPBYTE *)ppSecurityDescriptor,
  674. &BufferSize
  675. );
  676. }
  677. __except (EXCEPTION_EXECUTE_HANDLER)
  678. {
  679. //
  680. // For some reason we got an exception.
  681. //
  682. ec = GetExceptionCode();
  683. DebugPrintEx(
  684. DEBUG_ERR,
  685. TEXT("Exception on RPC call to FAX_GetSecurity. (ec: %ld)"),
  686. ec);
  687. }
  688. }
  689. else
  690. {
  691. __try
  692. {
  693. ec = FAX_GetSecurityEx (
  694. FH_FAX_HANDLE(hFaxHandle),
  695. SecurityInformation,
  696. (LPBYTE *)ppSecurityDescriptor,
  697. &BufferSize
  698. );
  699. }
  700. __except (EXCEPTION_EXECUTE_HANDLER)
  701. {
  702. //
  703. // For some reason we got an exception.
  704. //
  705. ec = GetExceptionCode();
  706. DebugPrintEx(
  707. DEBUG_ERR,
  708. TEXT("Exception on RPC call to FAX_GetSecurityEx. (ec: %ld)"),
  709. ec);
  710. }
  711. }
  712. if (ERROR_SUCCESS != ec)
  713. {
  714. DumpRPCExtendedStatus ();
  715. SetLastError(ec);
  716. return FALSE;
  717. }
  718. return TRUE;
  719. } // FaxGetSecurityEx
  720. BOOL
  721. WINAPI
  722. FaxGetSecurity(
  723. IN HANDLE hFaxHandle,
  724. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  725. )
  726. /*++
  727. Routine name : FaxGetSecurity
  728. Routine description:
  729. Gets the server's security descriptor
  730. Author:
  731. Eran Yariv (EranY), Nov, 1999
  732. Arguments:
  733. hFaxHandle [in ] - Handle to fax server
  734. ppSecurityDescriptor [out] - Pointer to receive buffer
  735. Return Value:
  736. TRUE - Success
  737. FALSE - Failure, call GetLastError() for more error information.
  738. --*/
  739. {
  740. error_status_t ec;
  741. DWORD BufferSize = 0;
  742. DEBUG_FUNCTION_NAME(TEXT("FaxGetSecurity"));
  743. if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
  744. {
  745. SetLastError(ERROR_INVALID_HANDLE);
  746. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  747. return FALSE;
  748. }
  749. if (!ppSecurityDescriptor)
  750. {
  751. SetLastError(ERROR_INVALID_PARAMETER);
  752. DebugPrintEx(DEBUG_ERR, _T("ppSecurityDescriptor is NULL."));
  753. return FALSE;
  754. }
  755. __try
  756. {
  757. ec = FAX_GetSecurity (
  758. FH_FAX_HANDLE(hFaxHandle),
  759. (LPBYTE *)ppSecurityDescriptor,
  760. &BufferSize
  761. );
  762. }
  763. __except (EXCEPTION_EXECUTE_HANDLER)
  764. {
  765. //
  766. // For some reason we got an exception.
  767. //
  768. ec = GetExceptionCode();
  769. DebugPrintEx(
  770. DEBUG_ERR,
  771. TEXT("Exception on RPC call to FAX_GetSecurity. (ec: %ld)"),
  772. ec);
  773. }
  774. if (ERROR_SUCCESS != ec)
  775. {
  776. DumpRPCExtendedStatus ();
  777. SetLastError(ec);
  778. return FALSE;
  779. }
  780. return TRUE;
  781. } // FaxGetSecurity
  782. BOOL
  783. WINAPI
  784. FaxSetSecurity(
  785. IN HANDLE hFaxHandle,
  786. SECURITY_INFORMATION SecurityInformation,
  787. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  788. )
  789. /*++
  790. Routine name : FaxGetSecurity
  791. Routine description:
  792. Sets the server's security descriptor
  793. Author:
  794. Eran Yariv (EranY), Nov, 1999
  795. Arguments:
  796. hFaxHandle [in] - Handle to fax server
  797. SecurityInformation [in] - Defines the valid entries in the security descriptor (Bit wise OR )
  798. pSecurityDescriptor [in] - New security descriptor to set.
  799. Must be self-relative.
  800. Return Value:
  801. TRUE - Success
  802. FALSE - Failure, call GetLastError() for more error information.
  803. --*/
  804. {
  805. error_status_t ec;
  806. DWORD dwBufferSize;
  807. DWORD dwRevision;
  808. SECURITY_DESCRIPTOR_CONTROL sdControl;
  809. DEBUG_FUNCTION_NAME(TEXT("FaxSetSecurity"));
  810. DWORD dwSecInfo = ( OWNER_SECURITY_INFORMATION |
  811. GROUP_SECURITY_INFORMATION |
  812. DACL_SECURITY_INFORMATION |
  813. SACL_SECURITY_INFORMATION );
  814. if (!ValidateFaxHandle(hFaxHandle,FHT_SERVICE))
  815. {
  816. SetLastError(ERROR_INVALID_HANDLE);
  817. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  818. return FALSE;
  819. }
  820. if (!pSecurityDescriptor)
  821. {
  822. SetLastError(ERROR_INVALID_PARAMETER);
  823. DebugPrintEx(DEBUG_ERR, _T("pSecurityDescriptor is NULL."));
  824. return FALSE;
  825. }
  826. if (0 == (SecurityInformation & dwSecInfo))
  827. {
  828. SetLastError( ERROR_INVALID_PARAMETER );
  829. DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - No valid bit type indicated"));
  830. return FALSE;
  831. }
  832. if (0 != (SecurityInformation & ~dwSecInfo))
  833. {
  834. SetLastError( ERROR_INVALID_PARAMETER );
  835. DebugPrintEx(DEBUG_ERR, _T("SecurityInformation is invalid - contains invalid securtiy information bits"));
  836. return FALSE;
  837. }
  838. if (!IsValidSecurityDescriptor(pSecurityDescriptor))
  839. {
  840. SetLastError( ERROR_INVALID_SECURITY_DESCR );
  841. DebugPrintEx(DEBUG_ERR, _T("Got invalid security descriptor"));
  842. return FALSE;
  843. }
  844. if (!GetSecurityDescriptorControl (
  845. pSecurityDescriptor,
  846. &sdControl,
  847. &dwRevision
  848. ))
  849. {
  850. DebugPrintEx(
  851. DEBUG_ERR,
  852. TEXT("Error on GetSecurityDescriptorControl (ec = %ld)"),
  853. GetLastError());
  854. return FALSE;
  855. }
  856. if (!(sdControl & SE_SELF_RELATIVE))
  857. {
  858. //
  859. // Got a non-self-relative security descriptor - bad!!!
  860. //
  861. DebugPrintEx(DEBUG_ERR, _T("Got non-self-relative security descriptor"));
  862. SetLastError( ERROR_INVALID_SECURITY_DESCR );
  863. return FALSE;
  864. }
  865. dwBufferSize = GetSecurityDescriptorLength(pSecurityDescriptor);
  866. __try
  867. {
  868. ec = FAX_SetSecurity(
  869. FH_FAX_HANDLE(hFaxHandle),
  870. SecurityInformation,
  871. (LPBYTE)pSecurityDescriptor,
  872. dwBufferSize
  873. );
  874. }
  875. __except (EXCEPTION_EXECUTE_HANDLER)
  876. {
  877. //
  878. // For some reason we got an exception.
  879. //
  880. ec = GetExceptionCode();
  881. DebugPrintEx(
  882. DEBUG_ERR,
  883. TEXT("Exception on RPC call to FAX_SetSecurity. (ec: %ld)"),
  884. ec);
  885. }
  886. if (ec != ERROR_SUCCESS)
  887. {
  888. DumpRPCExtendedStatus ();
  889. SetLastError(ec);
  890. return FALSE;
  891. }
  892. return TRUE;
  893. } // FaxSetSecurity
  894. BOOL
  895. WINAPI
  896. FaxRelease(
  897. IN const HANDLE FaxHandle
  898. )
  899. /*++
  900. Routine name : FaxRelease
  901. Routine description:
  902. The Fax Service counts all the clients connected to it. When this reference count reaches zero,
  903. the Fax Service can download itself.
  904. There are some connections that do not want to prevent from the service to download,
  905. like Task Bar Monitor.
  906. These clients should call this function.
  907. It adds the indication on the handle that it is "Released" and decrements the total reference count.
  908. Author:
  909. Iv Garber (IvG), Jan, 2001
  910. Arguments:
  911. FaxHandle [in] - the client connection handle that do not want to prevent the service from downloading.
  912. Return Value:
  913. BOOL - TRUE if operation is successfull, otherwise FALSE.
  914. --*/
  915. {
  916. error_status_t ec;
  917. DWORD CanShare;
  918. DEBUG_FUNCTION_NAME(TEXT("FaxRelease"));
  919. if (!ValidateFaxHandle(FaxHandle,FHT_SERVICE))
  920. {
  921. SetLastError(ERROR_INVALID_HANDLE);
  922. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  923. return FALSE;
  924. }
  925. if (FAX_API_VERSION_1 > FH_SERVER_VER(FaxHandle))
  926. {
  927. //
  928. // Servers of API version 0 don't support FAX_ConnectionRefCount(...,2,...)
  929. //
  930. DebugPrintEx(DEBUG_ERR,
  931. _T("Server version is %ld - doesn't support this call"),
  932. FH_SERVER_VER(FaxHandle));
  933. SetLastError(FAX_ERR_VERSION_MISMATCH);
  934. return FALSE;
  935. }
  936. //
  937. // Decrement the Reference Count
  938. //
  939. __try
  940. {
  941. ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(FaxHandle), &FH_CONTEXT_HANDLE(FaxHandle), 2, &CanShare );
  942. }
  943. __except (EXCEPTION_EXECUTE_HANDLER)
  944. {
  945. //
  946. // For some reason we crashed.
  947. //
  948. ec = GetExceptionCode();
  949. DebugPrintEx(DEBUG_ERR, _T("Exception on RPC call to FAX_ConnectionRefCount. (ec: %ld)"), ec);
  950. }
  951. if (ec != ERROR_SUCCESS)
  952. {
  953. DumpRPCExtendedStatus ();
  954. SetLastError(ec);
  955. return FALSE;
  956. }
  957. return TRUE;
  958. }
  959. WINFAXAPI
  960. BOOL
  961. WINAPI
  962. FaxGetReportedServerAPIVersion (
  963. IN HANDLE hFaxHandle,
  964. OUT LPDWORD lpdwReportedServerAPIVersion
  965. )
  966. /*++
  967. Routine name : FaxGetReportedServerAPIVersion
  968. Routine description:
  969. Extracts the reported (non-filtered) fax server API version from an active connection handle
  970. Author:
  971. Eran Yariv (EranY), Mar, 2001
  972. Arguments:
  973. hFaxHandle [in] - Connection handle
  974. lpdwReportedServerAPIVersion [out] - Fax server API version
  975. Return Value:
  976. BOOL - TRUE if operation is successfull, otherwise FALSE.
  977. --*/
  978. {
  979. DEBUG_FUNCTION_NAME(TEXT("FaxGetReportedServerAPIVersion"));
  980. if (!ValidateFaxHandle(hFaxHandle, FHT_SERVICE))
  981. {
  982. SetLastError(ERROR_INVALID_HANDLE);
  983. DebugPrintEx(DEBUG_ERR, _T("ValidateFaxHandle() is failed."));
  984. return FALSE;
  985. }
  986. *lpdwReportedServerAPIVersion = FH_REPORTED_SERVER_VER(hFaxHandle);
  987. return TRUE;
  988. } // FaxGetReportedServerAPIVersion