Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

722 lines
16 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. BOOL
  18. EnsureFaxServiceIsStarted(
  19. LPCWSTR MachineName
  20. )
  21. {
  22. BOOL Rval = FALSE;
  23. SC_HANDLE hSvcMgr = NULL;
  24. SC_HANDLE hService = NULL;
  25. SERVICE_STATUS Status;
  26. DWORD i = 0;
  27. #if DBG
  28. if (GetEnvironmentVariable( L"DontLookForFaxService", (LPWSTR)&i, sizeof(DWORD) )) {
  29. return TRUE;
  30. }
  31. #endif
  32. hSvcMgr = OpenSCManager(
  33. MachineName,
  34. NULL,
  35. SC_MANAGER_CONNECT
  36. );
  37. if (!hSvcMgr) {
  38. DebugPrint(( L"could not open service manager: error code = %u", GetLastError() ));
  39. goto exit;
  40. }
  41. hService = OpenService(
  42. hSvcMgr,
  43. L"Fax",
  44. SERVICE_START | SERVICE_QUERY_STATUS
  45. );
  46. if (!hService) {
  47. DebugPrint(( L"could not open the FAX service: error code = %u", GetLastError() ));
  48. goto exit;
  49. }
  50. if (!QueryServiceStatus( hService, &Status )) {
  51. DebugPrint(( L"could not query status for the FAX service: error code = %u", GetLastError() ));
  52. goto exit;
  53. }
  54. if (Status.dwCurrentState == SERVICE_RUNNING) {
  55. Rval = TRUE;
  56. goto exit;
  57. }
  58. if (!StartService( hService, 0, NULL )) {
  59. DebugPrint(( L"could not start the FAX service: error code = %u", GetLastError() ));
  60. goto exit;
  61. }
  62. do {
  63. if (!QueryServiceStatus( hService, &Status )) {
  64. DebugPrint(( L"could not query status for the FAX service: error code = %u", GetLastError() ));
  65. goto exit;
  66. }
  67. i += 1;
  68. if (i > 60) {
  69. break;
  70. }
  71. Sleep( 500 );
  72. } while (Status.dwCurrentState != SERVICE_RUNNING);
  73. if (Status.dwCurrentState != SERVICE_RUNNING) {
  74. DebugPrint(( L"could not start the FAX service: error code = %u", GetLastError() ));
  75. goto exit;
  76. }
  77. Rval = TRUE;
  78. exit:
  79. if (hService) {
  80. CloseServiceHandle( hService );
  81. }
  82. if (hSvcMgr) {
  83. CloseServiceHandle( hSvcMgr );
  84. }
  85. return Rval;
  86. }
  87. BOOL
  88. WINAPI
  89. FaxConnectFaxServerW(
  90. IN LPCWSTR lpMachineName OPTIONAL,
  91. OUT LPHANDLE FaxHandle
  92. )
  93. /*++
  94. Routine Description:
  95. Creates a connection to a FAX server. The binding handle that is
  96. returned is used for all subsequent FAX API calls.
  97. Arguments:
  98. MachineName - Machine name, NULL, or "."
  99. FaxHandle - Pointer to a FAX handle
  100. Return Value:
  101. TRUE - Success
  102. FALSE - Failure, call GetLastError() for more error information.
  103. --*/
  104. {
  105. error_status_t ec;
  106. LONG Error;
  107. PFAX_HANDLE_DATA FaxData;
  108. PHANDLE_ENTRY HandleEntry;
  109. DWORD CanShare;
  110. if (!FaxHandle) {
  111. SetLastError(ERROR_INVALID_PARAMETER);
  112. return FALSE;
  113. }
  114. if (!EnsureFaxServiceIsStarted( lpMachineName )) {
  115. return FALSE;
  116. }
  117. FaxData = MemAlloc( sizeof(FAX_HANDLE_DATA) );
  118. if (!FaxData) {
  119. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  120. return FALSE;
  121. }
  122. Error = RpcpBindRpc( lpMachineName, TEXT("FaxSvc"), NULL, &FaxData->FaxHandle );
  123. if (Error) {
  124. MemFree ( FaxData );
  125. SetLastError( Error );
  126. return FALSE;
  127. }
  128. InitializeCriticalSection( &FaxData->CsHandleTable );
  129. InitializeListHead( &FaxData->HandleTableListHead );
  130. HandleEntry = CreateNewServiceHandle( FaxData );
  131. if (!HandleEntry) {
  132. MemFree( FaxData );
  133. return FALSE;
  134. }
  135. if (lpMachineName) {
  136. FaxData->MachineName = StringDup( lpMachineName );
  137. if (!FaxData->MachineName) {
  138. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  139. MemFree( FaxData );
  140. return FALSE;
  141. }
  142. }
  143. *FaxHandle = (LPHANDLE) HandleEntry;
  144. ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(*FaxHandle), &FH_CONTEXT_HANDLE(*FaxHandle), 1, &CanShare );
  145. if (ec) {
  146. FaxClose( *FaxHandle );
  147. SetLastError( ec );
  148. return FALSE;
  149. }
  150. if (IsLocalFaxConnection(*FaxHandle) || CanShare) {
  151. return TRUE;
  152. }
  153. FaxClose( *FaxHandle );
  154. *FaxHandle = NULL;
  155. SetLastError( ERROR_ACCESS_DENIED );
  156. return FALSE;
  157. }
  158. BOOL
  159. WINAPI
  160. FaxConnectFaxServerA(
  161. IN LPCSTR lpMachineName OPTIONAL,
  162. OUT LPHANDLE FaxHandle
  163. )
  164. /*++
  165. Routine Description:
  166. Creates a connection to a FAX server. The binding handle that is
  167. returned is used for all subsequent FAX API calls.
  168. Arguments:
  169. MachineName - Machine name, NULL, or "."
  170. FaxHandle - Pointer to a FAX handle
  171. Return Value:
  172. TRUE - Success
  173. FALSE - Failure, call GetLastError() for more error information.
  174. --*/
  175. {
  176. LONG Error;
  177. PWCHAR MachineName = NULL;
  178. PFAX_HANDLE_DATA FaxData;
  179. PHANDLE_ENTRY HandleEntry;
  180. LPWSTR NetworkOptions;
  181. error_status_t ec;
  182. DWORD CanShare;
  183. if (!FaxHandle) {
  184. SetLastError(ERROR_INVALID_PARAMETER);
  185. return FALSE;
  186. }
  187. if (lpMachineName) {
  188. MachineName = AnsiStringToUnicodeString( lpMachineName );
  189. if (!MachineName) {
  190. SetLastError( ERROR_INVALID_PARAMETER );
  191. return FALSE;
  192. }
  193. }
  194. if (!EnsureFaxServiceIsStarted( MachineName )) {
  195. return FALSE;
  196. }
  197. FaxData = MemAlloc( sizeof(FAX_HANDLE_DATA) );
  198. if (!FaxData) {
  199. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  200. if (MachineName) MemFree( MachineName );
  201. return FALSE;
  202. }
  203. if (OsVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
  204. NetworkOptions = NULL;
  205. } else {
  206. NetworkOptions = L"Security=Impersonation Dynamic False";
  207. }
  208. Error = RpcpBindRpc( MachineName, TEXT("FaxSvc"), NetworkOptions, &FaxData->FaxHandle );
  209. if (Error) {
  210. if (MachineName) MemFree( MachineName );
  211. MemFree( FaxData );
  212. SetLastError( Error );
  213. return FALSE;
  214. }
  215. InitializeCriticalSection( &FaxData->CsHandleTable );
  216. InitializeListHead( &FaxData->HandleTableListHead );
  217. HandleEntry = CreateNewServiceHandle( FaxData );
  218. if (!HandleEntry) {
  219. if (MachineName) MemFree( MachineName );
  220. MemFree( FaxData );
  221. return FALSE;
  222. }
  223. FaxData->MachineName = MachineName;
  224. *FaxHandle = (LPHANDLE) HandleEntry;
  225. ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(*FaxHandle), &FH_CONTEXT_HANDLE(*FaxHandle), 1, &CanShare );
  226. if (ec) {
  227. FaxClose( *FaxHandle );
  228. *FaxHandle = NULL;
  229. SetLastError( ec );
  230. return FALSE;
  231. }
  232. if (IsLocalFaxConnection(*FaxHandle) || CanShare) {
  233. return TRUE;
  234. }
  235. FaxClose( FaxHandle );
  236. *FaxHandle = NULL;
  237. SetLastError( ERROR_ACCESS_DENIED );
  238. return FALSE;
  239. }
  240. BOOL
  241. WINAPI
  242. FaxGetVersion(
  243. IN HANDLE FaxHandle,
  244. OUT LPDWORD Version
  245. )
  246. {
  247. error_status_t ec;
  248. if (!FaxHandle || !Version) {
  249. SetLastError(ERROR_INVALID_PARAMETER);
  250. return FALSE;
  251. }
  252. ec = FAX_GetVersion(
  253. (handle_t) ((PHANDLE_ENTRY)FaxHandle)->FaxData->FaxHandle,
  254. Version
  255. );
  256. if (ec) {
  257. SetLastError( ec );
  258. return FALSE;
  259. }
  260. return TRUE;
  261. }
  262. BOOL
  263. WINAPI
  264. FaxGetDeviceStatusW(
  265. IN const HANDLE FaxHandle,
  266. OUT PFAX_DEVICE_STATUSW *DeviceStatus
  267. )
  268. /*++
  269. Routine Description:
  270. Obtains a status report for the FAX devices being
  271. used by the FAX server.
  272. Arguments:
  273. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  274. StatusBuffer - Buffer for the status data
  275. BufferSize - Size of the StatusBuffer
  276. Return Value:
  277. TRUE - Success
  278. FALSE - Failure, call GetLastError() for more error information.
  279. --*/
  280. {
  281. #define FixupString(_s) FixupStringPtr(DeviceStatus,_s)
  282. error_status_t ec;
  283. DWORD BufferSize = 0;
  284. if (!ValidateFaxHandle(FaxHandle, FHT_PORT)) {
  285. SetLastError(ERROR_INVALID_HANDLE);
  286. return FALSE;
  287. }
  288. if (!DeviceStatus) {
  289. SetLastError(ERROR_INVALID_PARAMETER);
  290. return FALSE;
  291. }
  292. *DeviceStatus = NULL;
  293. ec = FAX_GetDeviceStatus(
  294. FH_PORT_HANDLE(FaxHandle),
  295. (LPBYTE*)DeviceStatus,
  296. &BufferSize
  297. );
  298. if (ec) {
  299. SetLastError( ec );
  300. return FALSE;
  301. }
  302. FixupString( (*DeviceStatus)->CallerId );
  303. FixupString( (*DeviceStatus)->Csid );
  304. FixupString( (*DeviceStatus)->DeviceName );
  305. FixupString( (*DeviceStatus)->DocumentName );
  306. FixupString( (*DeviceStatus)->PhoneNumber );
  307. FixupString( (*DeviceStatus)->RoutingString );
  308. FixupString( (*DeviceStatus)->SenderName );
  309. FixupString( (*DeviceStatus)->RecipientName );
  310. FixupString( (*DeviceStatus)->StatusString );
  311. FixupString( (*DeviceStatus)->Tsid );
  312. FixupString( (*DeviceStatus)->UserName );
  313. return TRUE;
  314. }
  315. BOOL
  316. WINAPI
  317. FaxGetDeviceStatusA(
  318. IN const HANDLE FaxHandle,
  319. OUT PFAX_DEVICE_STATUSA *DeviceStatus
  320. )
  321. /*++
  322. Routine Description:
  323. Obtains a status report for the FAX devices being
  324. used by the FAX server.
  325. Arguments:
  326. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  327. StatusBuffer - Buffer for the status data
  328. BufferSize - Size of the StatusBuffer
  329. Return Value:
  330. TRUE - Success
  331. FALSE - Failure, call GetLastError() for more error information.
  332. --*/
  333. {
  334. if (!FaxGetDeviceStatusW( FaxHandle, (PFAX_DEVICE_STATUSW *)DeviceStatus )) {
  335. return FALSE;
  336. }
  337. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->CallerId );
  338. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Csid );
  339. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DeviceName );
  340. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->DocumentName );
  341. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->PhoneNumber );
  342. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RoutingString );
  343. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->SenderName );
  344. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->RecipientName );
  345. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->StatusString );
  346. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->Tsid );
  347. ConvertUnicodeStringInPlace( (LPWSTR) (*DeviceStatus)->UserName );
  348. return TRUE;
  349. }
  350. BOOL
  351. WINAPI
  352. FaxGetInstallType(
  353. IN HANDLE FaxHandle,
  354. OUT LPDWORD InstallType,
  355. OUT LPDWORD InstalledPlatforms,
  356. OUT LPDWORD ProductType
  357. )
  358. /*++
  359. Routine Description:
  360. Obtains a status report for the FAX devices being
  361. used by the FAX server.
  362. Arguments:
  363. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  364. StatusBuffer - Buffer for the status data
  365. BufferSize - Size of the StatusBuffer
  366. Return Value:
  367. TRUE - Success
  368. FALSE - Failure, call GetLastError() for more error information.
  369. --*/
  370. {
  371. error_status_t ec;
  372. if (!FaxHandle || !InstallType || !InstalledPlatforms || !ProductType) {
  373. SetLastError(ERROR_INVALID_PARAMETER);
  374. return FALSE;
  375. }
  376. ec = FAX_GetInstallType(
  377. FH_FAX_HANDLE(FaxHandle),
  378. InstallType,
  379. InstalledPlatforms,
  380. ProductType
  381. );
  382. if (ec) {
  383. SetLastError( ec );
  384. return FALSE;
  385. }
  386. return TRUE;
  387. }
  388. BOOL
  389. WINAPI
  390. FaxClose(
  391. IN const HANDLE FaxHandle
  392. )
  393. {
  394. error_status_t ec;
  395. PHANDLE_ENTRY HandleEntry = (PHANDLE_ENTRY) FaxHandle;
  396. HANDLE TmpFaxPortHandle;
  397. PFAX_HANDLE_DATA FaxData;
  398. DWORD CanShare;
  399. if (!FaxHandle || !*(LPDWORD)FaxHandle) {
  400. SetLastError(ERROR_INVALID_HANDLE);
  401. return FALSE;
  402. }
  403. switch (HandleEntry->Type) {
  404. case FHT_SERVICE:
  405. ec = FAX_ConnectionRefCount( FH_FAX_HANDLE(FaxHandle), &FH_CONTEXT_HANDLE(FaxHandle), 0, &CanShare );
  406. __try {
  407. ec = RpcpUnbindRpc( (RPC_BINDING_HANDLE *) HandleEntry->FaxData->FaxHandle );
  408. } __except (EXCEPTION_EXECUTE_HANDLER) {
  409. ec = GetExceptionCode();
  410. }
  411. FaxData = HandleEntry->FaxData;
  412. CloseFaxHandle( HandleEntry->FaxData, HandleEntry );
  413. //
  414. // zero out the memory before we return it to the heap
  415. //
  416. ZeroMemory( FaxData, sizeof(FAX_HANDLE_DATA) );
  417. MemFree( FaxData );
  418. return TRUE;
  419. case FHT_PORT:
  420. TmpFaxPortHandle = HandleEntry->FaxPortHandle;
  421. CloseFaxHandle( HandleEntry->FaxData, HandleEntry );
  422. ec = FAX_ClosePort( &TmpFaxPortHandle );
  423. if (ec) {
  424. SetLastError( ec );
  425. return FALSE;
  426. }
  427. break;
  428. default:
  429. SetLastError( ERROR_INVALID_HANDLE );
  430. return FALSE;
  431. }
  432. return TRUE;
  433. }
  434. BOOL
  435. WINAPI
  436. FaxGetSecurityDescriptorCount(
  437. IN HANDLE FaxHandle,
  438. OUT LPDWORD Count
  439. )
  440. {
  441. error_status_t ec;
  442. if (!FaxHandle || !Count) {
  443. SetLastError(ERROR_INVALID_PARAMETER);
  444. return FALSE;
  445. }
  446. ec = FAX_GetSecurityDescriptorCount(
  447. FH_FAX_HANDLE(FaxHandle),
  448. Count
  449. );
  450. if (ec) {
  451. SetLastError(ec);
  452. return FALSE;
  453. }
  454. return TRUE;
  455. }
  456. BOOL
  457. WINAPI
  458. FaxGetSecurityDescriptor(
  459. IN HANDLE FaxHandle,
  460. IN DWORD Id,
  461. OUT PFAX_SECURITY_DESCRIPTOR * FaxSecurityDescriptor
  462. )
  463. {
  464. error_status_t ec;
  465. DWORD BufferSize = 0;
  466. PFAX_SECURITY_DESCRIPTOR SecDesc;
  467. if (!FaxHandle || !FaxSecurityDescriptor) {
  468. SetLastError(ERROR_INVALID_PARAMETER);
  469. return FALSE;
  470. }
  471. ec = FAX_GetSecurityDescriptor(
  472. FH_FAX_HANDLE(FaxHandle),
  473. Id,
  474. (LPBYTE *)FaxSecurityDescriptor,
  475. &BufferSize
  476. );
  477. if (ec) {
  478. SetLastError(ec);
  479. return FALSE;
  480. }
  481. SecDesc = *FaxSecurityDescriptor;
  482. if(SecDesc->FriendlyName){
  483. FixupStringPtr(&SecDesc,SecDesc->FriendlyName);
  484. }
  485. if (SecDesc->SecurityDescriptor) {
  486. FixupStringPtr(&SecDesc,SecDesc->SecurityDescriptor);
  487. }
  488. return TRUE;
  489. }
  490. BOOL
  491. WINAPI
  492. FaxSetSecurityDescriptor(
  493. IN HANDLE FaxHandle,
  494. IN PFAX_SECURITY_DESCRIPTOR FaxSecurityDescriptor
  495. )
  496. {
  497. error_status_t ec;
  498. LPBYTE Buffer;
  499. DWORD BufferSize;
  500. DWORD SecLength;
  501. PFAX_SECURITY_DESCRIPTOR SD;
  502. DWORD Offset = sizeof(FAX_SECURITY_DESCRIPTOR);
  503. if (!FaxHandle || !FaxSecurityDescriptor) {
  504. SetLastError(ERROR_INVALID_PARAMETER);
  505. return FALSE;
  506. }
  507. if (!IsValidSecurityDescriptor( (PSECURITY_DESCRIPTOR) FaxSecurityDescriptor->SecurityDescriptor )){
  508. SetLastError( ERROR_INVALID_DATA );
  509. return FALSE;
  510. }
  511. SecLength = GetSecurityDescriptorLength( (PSECURITY_DESCRIPTOR) FaxSecurityDescriptor->SecurityDescriptor );
  512. BufferSize = sizeof(FAX_SECURITY_DESCRIPTOR) + SecLength;
  513. Buffer = (LPBYTE) MemAlloc( BufferSize );
  514. if (Buffer == NULL) {
  515. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  516. return FALSE;
  517. }
  518. SD = (PFAX_SECURITY_DESCRIPTOR) Buffer;
  519. SD->Id = FaxSecurityDescriptor->Id;
  520. // Can't set the friendly name
  521. SD->FriendlyName = (LPWSTR) Offset;
  522. CopyMemory(
  523. Buffer + Offset,
  524. FaxSecurityDescriptor->SecurityDescriptor,
  525. SecLength
  526. );
  527. SD->SecurityDescriptor = (LPBYTE) Offset;
  528. ec = FAX_SetSecurityDescriptor(
  529. FH_FAX_HANDLE(FaxHandle),
  530. Buffer,
  531. BufferSize
  532. );
  533. MemFree( Buffer );
  534. if (ec != ERROR_SUCCESS) {
  535. SetLastError(ec);
  536. return FALSE;
  537. }
  538. return TRUE;
  539. }