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.

388 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. clirpc.c
  5. Abstract:
  6. This module contains the client side RPC
  7. functions. These functions are used when the
  8. WINFAX client runs as an RPC server too. These
  9. functions are the ones available for the RPC
  10. clients to call. Currently the only client
  11. of these functions is the fax service.
  12. Author:
  13. Wesley Witt (wesw) 29-Nov-1996
  14. Revision History:
  15. --*/
  16. #include "faxapi.h"
  17. #pragma hdrstop
  18. BOOL RpcServerStarted;
  19. VOID
  20. WINAPI
  21. FaxFreeBuffer(
  22. LPVOID Buffer
  23. )
  24. {
  25. MemFree( Buffer );
  26. }
  27. void *
  28. MIDL_user_allocate(
  29. IN size_t NumBytes
  30. )
  31. {
  32. return MemAlloc( NumBytes );
  33. }
  34. void
  35. MIDL_user_free(
  36. IN void *MemPointer
  37. )
  38. {
  39. MemFree( MemPointer );
  40. }
  41. DWORD
  42. FaxServerThread(
  43. LPVOID UnUsed
  44. )
  45. /*++
  46. Routine Description:
  47. Thread to process RPC messages from the various fax servers.
  48. Arguments:
  49. AsyncInfo - Packet of data necessary for processing this thread
  50. Return Value:
  51. Always zero.
  52. --*/
  53. {
  54. error_status_t ec;
  55. ec = RpcMgmtWaitServerListen();
  56. if (ec != 0) {
  57. return ec;
  58. }
  59. return 0;
  60. }
  61. BOOL
  62. WINAPI
  63. FaxInitializeEventQueue(
  64. IN HANDLE FaxHandle,
  65. IN HANDLE CompletionPort,
  66. IN ULONG_PTR CompletionKey,
  67. IN HWND hWnd,
  68. IN UINT MessageStart
  69. )
  70. /*++
  71. Routine Description:
  72. Initializes the client side event queue. There can be one event
  73. queue initialized for each fax server that the client app is
  74. connected to.
  75. Arguments:
  76. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  77. CompletionPort - Handle of an existing completion port opened using CreateIoCompletionPort.
  78. CompletionKey - A value that will be returned through the lpCompletionKey parameter of GetQueuedCompletionStatus.
  79. hWnd - Window handle to post events to
  80. MessageStart - Starting message number, message range used is MessageStart + FEI_NEVENTS
  81. Return Value:
  82. TRUE - Success
  83. FALSE - Failure, call GetLastError() for more error information.
  84. --*/
  85. {
  86. DWORD ThreadId;
  87. HANDLE hThread;
  88. PASYNC_EVENT_INFO AsyncInfo;
  89. DWORD Size;
  90. error_status_t ec;
  91. TCHAR ComputerName[64];
  92. TCHAR ClientName[64];
  93. DWORD FaxSvcProcessId;
  94. if (CompletionPort && hWnd) {
  95. SetLastError( ERROR_INVALID_PARAMETER );
  96. return FALSE;
  97. }
  98. if (!ValidateFaxHandle(FaxHandle, FHT_SERVICE)) {
  99. SetLastError(ERROR_INVALID_HANDLE);
  100. return FALSE;
  101. }
  102. if (hWnd && !IsLocalFaxConnection(FaxHandle)) {
  103. SetLastError( ERROR_INVALID_PARAMETER );
  104. return FALSE;
  105. }
  106. if (hWnd) {
  107. if (MessageStart < WM_USER) {
  108. SetLastError( ERROR_INVALID_PARAMETER );
  109. return FALSE;
  110. }
  111. if (CompletionKey == (ULONG_PTR)-1) {
  112. //
  113. // this means that we want the fax service to close it's token so we can logoff
  114. //
  115. ec = FAX_RegisterEventWindow( FH_FAX_HANDLE(FaxHandle), (ULONG64)hWnd, 0, NULL , NULL , &FaxSvcProcessId );
  116. } else {
  117. //
  118. // normal registration of event window
  119. //
  120. HWINSTA hWinStation;
  121. HDESK hDesktop;
  122. WCHAR StationName[100];
  123. WCHAR DesktopName[100];
  124. DWORD dwNeeded;
  125. if (!IsWindow(hWnd)) {
  126. SetLastError( ERROR_INVALID_PARAMETER );
  127. return FALSE;
  128. }
  129. hWinStation = GetProcessWindowStation();
  130. if (!GetUserObjectInformation(hWinStation,
  131. UOI_NAME,
  132. StationName,
  133. sizeof(StationName),
  134. &dwNeeded) ) {
  135. return FALSE;
  136. }
  137. hDesktop = GetThreadDesktop( GetCurrentThreadId() );
  138. if (! GetUserObjectInformation(hDesktop,
  139. UOI_NAME,
  140. DesktopName,
  141. sizeof(DesktopName),
  142. &dwNeeded) ) {
  143. return FALSE;
  144. }
  145. ec = FAX_RegisterEventWindow( FH_FAX_HANDLE(FaxHandle),
  146. (ULONG64)hWnd,
  147. MessageStart,
  148. StationName,
  149. DesktopName,
  150. &FaxSvcProcessId );
  151. }
  152. if (ec) {
  153. SetLastError( ec );
  154. return FALSE;
  155. }
  156. return FaxSvcProcessId;
  157. } else if (!CompletionPort) {
  158. SetLastError(ERROR_INVALID_PARAMETER);
  159. return FALSE;
  160. }
  161. AsyncInfo = (PASYNC_EVENT_INFO) MemAlloc( sizeof(ASYNC_EVENT_INFO) );
  162. if (!AsyncInfo) {
  163. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  164. return FALSE;
  165. }
  166. AsyncInfo->FaxData = FH_DATA(FaxHandle);
  167. AsyncInfo->CompletionPort = CompletionPort;
  168. AsyncInfo->CompletionKey = CompletionKey;
  169. Size = sizeof(ComputerName) / sizeof(TCHAR);
  170. if (!GetComputerName( ComputerName, &Size )) {
  171. goto error_exit;
  172. }
  173. _stprintf( ClientName, TEXT("FaxClient$%d"), GetCurrentProcessId() );
  174. //
  175. // timing: get the server thread up and running before
  176. // registering with the fax service (our client)
  177. //
  178. ec = RpcpStartRpcServer( ClientName, faxclient_ServerIfHandle );
  179. if (ec != 0) {
  180. SetLastError( ec );
  181. goto error_exit;
  182. }
  183. FH_DATA(FaxHandle)->EventInit = TRUE;
  184. if (!RpcServerStarted) {
  185. hThread = CreateThread(
  186. NULL,
  187. 1024*100,
  188. FaxServerThread,
  189. NULL,
  190. 0,
  191. &ThreadId
  192. );
  193. if (!hThread) {
  194. goto error_exit;
  195. } else {
  196. RpcServerStarted = TRUE;
  197. CloseHandle(hThread);
  198. }
  199. }
  200. ec = FAX_StartClientServer( FH_FAX_HANDLE(FaxHandle), ComputerName, ClientName, (ULONG64) AsyncInfo );
  201. if (ec) {
  202. SetLastError( ec );
  203. goto error_exit;
  204. }
  205. return TRUE;
  206. error_exit:
  207. if (AsyncInfo) {
  208. MemFree(AsyncInfo);
  209. }
  210. if (RpcServerStarted) {
  211. FH_DATA(FaxHandle)->EventInit = FALSE;
  212. // this should also terminate FaxServerThread
  213. RpcpStopRpcServer( faxclient_ServerIfHandle );
  214. RpcServerStarted = FALSE;
  215. }
  216. return FALSE;
  217. }
  218. error_status_t
  219. FAX_OpenConnection(
  220. IN handle_t hBinding,
  221. IN ULONG64 Context,
  222. OUT LPHANDLE FaxHandle
  223. )
  224. {
  225. *FaxHandle = (HANDLE) Context;
  226. return 0;
  227. }
  228. error_status_t
  229. FAX_CloseConnection(
  230. OUT LPHANDLE FaxHandle
  231. )
  232. {
  233. *FaxHandle = NULL;
  234. return 0;
  235. }
  236. error_status_t
  237. FAX_ClientEventQueue(
  238. IN HANDLE FaxHandle,
  239. IN FAX_EVENT FaxEvent
  240. )
  241. /*++
  242. Routine Description:
  243. This function is called when the a fax server wants
  244. to deliver a fax event to this client.
  245. Arguments:
  246. FaxHandle - FAX handle obtained from FaxConnectFaxServer.
  247. FaxEvent - FAX event structure.
  248. Context - Context token, really a ASYNC_EVENT_INFO structure pointer
  249. Return Value:
  250. TRUE - Success
  251. FALSE - Failure, call GetLastError() for more error information.
  252. --*/
  253. {
  254. PASYNC_EVENT_INFO AsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
  255. PFAX_EVENT FaxEventPost = NULL;
  256. FaxEventPost = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
  257. if (!FaxEventPost) {
  258. return ERROR_NOT_ENOUGH_MEMORY;
  259. }
  260. CopyMemory( FaxEventPost, &FaxEvent, sizeof(FAX_EVENT) );
  261. PostQueuedCompletionStatus(
  262. AsyncInfo->CompletionPort,
  263. sizeof(FAX_EVENT),
  264. AsyncInfo->CompletionKey,
  265. (LPOVERLAPPED) FaxEventPost
  266. );
  267. return ERROR_SUCCESS;
  268. }
  269. VOID
  270. RPC_FAX_HANDLE_rundown(
  271. IN HANDLE FaxHandle
  272. )
  273. {
  274. PASYNC_EVENT_INFO AsyncInfo = (PASYNC_EVENT_INFO) FaxHandle;
  275. PFAX_EVENT FaxEvent;
  276. FaxEvent = (PFAX_EVENT) LocalAlloc( LMEM_FIXED, sizeof(FAX_EVENT) );
  277. if (!FaxEvent) {
  278. goto exit;
  279. }
  280. FaxEvent->SizeOfStruct = sizeof(ASYNC_EVENT_INFO);
  281. GetSystemTimeAsFileTime( &FaxEvent->TimeStamp );
  282. FaxEvent->DeviceId = 0;
  283. FaxEvent->EventId = FEI_FAXSVC_ENDED;
  284. FaxEvent->JobId = 0;
  285. PostQueuedCompletionStatus(
  286. AsyncInfo->CompletionPort,
  287. sizeof(FAX_EVENT),
  288. AsyncInfo->CompletionKey,
  289. (LPOVERLAPPED) FaxEvent
  290. );
  291. exit:
  292. RpcpStopRpcServer( faxclient_ServerIfHandle );
  293. return;
  294. }