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.

764 lines
18 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. rpcsvr.c
  5. Abstract:
  6. RPC server routines
  7. Author:
  8. Vlad Sadovsky (vlads) 10-Jan-1997
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 26-Jan-1997 VladS created
  13. --*/
  14. #include "precomp.h"
  15. #include "stiexe.h"
  16. #include "device.h"
  17. #include "conn.h"
  18. #include "wiapriv.h"
  19. #include "lockmgr.h"
  20. #include <apiutil.h>
  21. #include <stiapi.h>
  22. #include <stirpc.h>
  23. //
  24. // Context number used for WIA runtime event clients
  25. //
  26. LONG_PTR g_lContextNum = 0;
  27. //
  28. // External prototypes
  29. //
  30. DWORD
  31. WINAPI
  32. StiApiAccessCheck(
  33. IN ACCESS_MASK DesiredAccess
  34. );
  35. DWORD
  36. WINAPI
  37. R_StiApiGetVersion(
  38. LPCWSTR pszServer,
  39. DWORD dwReserved,
  40. DWORD *pdwVersion
  41. )
  42. {
  43. DWORD dwErr;
  44. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  45. if (NOERROR != dwErr ) {
  46. return dwErr;
  47. }
  48. if (!pdwVersion) {
  49. return ERROR_INVALID_PARAMETER;
  50. }
  51. STIMONWPRINTF(TEXT("RPC SUPP: ApiGetVersion called"));
  52. *pdwVersion = STI_VERSION;
  53. return NOERROR;
  54. }
  55. DWORD
  56. WINAPI
  57. R_StiApiOpenDevice(
  58. LPCWSTR pszServer,
  59. LPCWSTR pszDeviceName,
  60. DWORD dwMode,
  61. DWORD dwAccessRequired,
  62. DWORD dwProcessId,
  63. STI_DEVICE_HANDLE *pHandle
  64. )
  65. {
  66. USES_CONVERSION;
  67. BOOL fRet;
  68. DWORD dwErr;
  69. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  70. if (NOERROR != dwErr ) {
  71. return dwErr;
  72. }
  73. if (!pHandle || !pszDeviceName) {
  74. return ERROR_INVALID_PARAMETER;
  75. }
  76. // STIMONWPRINTF(TEXT("RPC SUPP: Open device called"));
  77. //
  78. // Create connection object and get it's handle
  79. //
  80. fRet = CreateDeviceConnection(W2CT(pszDeviceName),
  81. dwMode,
  82. dwProcessId,
  83. pHandle
  84. );
  85. if (fRet && *pHandle) {
  86. return NOERROR;
  87. }
  88. *pHandle = INVALID_HANDLE_VALUE;
  89. return ::GetLastError();
  90. }
  91. DWORD
  92. WINAPI
  93. R_StiApiCloseDevice(
  94. LPCWSTR pszServer,
  95. STI_DEVICE_HANDLE hDevice
  96. )
  97. {
  98. STIMONWPRINTF(TEXT("RPC SUPP: Close device called"));
  99. DWORD dwErr;
  100. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  101. if (NOERROR != dwErr ) {
  102. return dwErr;
  103. }
  104. #ifdef DEBUG
  105. DebugDumpScheduleList(TEXT("RPC CLose enter"));
  106. #endif
  107. if (DestroyDeviceConnection(hDevice,FALSE) ) {
  108. #ifdef DEBUG
  109. DebugDumpScheduleList(TEXT("RPC CLose exit"));
  110. #endif
  111. return NOERROR;
  112. }
  113. #ifdef DEBUG
  114. DebugDumpScheduleList(TEXT("RPC CLose exit"));
  115. #endif
  116. return GetLastError();
  117. }
  118. VOID
  119. STI_DEVICE_HANDLE_rundown(
  120. STI_DEVICE_HANDLE hDevice
  121. )
  122. {
  123. STIMONWPRINTF(TEXT("RPC SUPP: rundown device called"));
  124. if (DestroyDeviceConnection(hDevice,TRUE) ) {
  125. return;
  126. }
  127. return ;
  128. }
  129. DWORD
  130. WINAPI
  131. R_StiApiSubscribe(
  132. STI_DEVICE_HANDLE Handle,
  133. LOCAL_SUBSCRIBE_CONTAINER *lpSubscribe
  134. )
  135. {
  136. STI_CONN *pConnectionObject;
  137. BOOL fRet;
  138. DWORD dwErr;
  139. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  140. if (NOERROR != dwErr ) {
  141. return dwErr;
  142. }
  143. //
  144. // Validate contents of subscribe request
  145. //
  146. // For this call we need to impersonate , because we will need
  147. // access to client process handle
  148. //
  149. dwErr = ::RpcImpersonateClient( NULL ) ;
  150. if( dwErr == NOERROR ) {
  151. //
  152. // Invoke add subscription method on connection object
  153. //
  154. if (!LookupConnectionByHandle(Handle,&pConnectionObject)) {
  155. dwErr = ERROR_INVALID_HANDLE;
  156. }
  157. else
  158. {
  159. fRet = pConnectionObject->SetSubscribeInfo(lpSubscribe);
  160. if (fRet)
  161. {
  162. dwErr = NOERROR;
  163. }
  164. else
  165. {
  166. dwErr = ERROR_INVALID_PARAMETER;
  167. }
  168. pConnectionObject->Release();
  169. }
  170. // Go back. RpcRevertToSelf will always succeed in this case (including low mem conditions etc.)
  171. // because it is called on the same thread that RpcImpersonateClient was called on. Therefore, the
  172. // return code is never looked at.
  173. RPC_STATUS rpcStatus = ::RpcRevertToSelf();
  174. }
  175. else {
  176. // Failed to impersonate
  177. }
  178. return dwErr;
  179. }
  180. DWORD
  181. WINAPI
  182. R_StiApiGetLastNotificationData(
  183. STI_DEVICE_HANDLE Handle,
  184. LPBYTE pData,
  185. DWORD nSize,
  186. LPDWORD pcbNeeded
  187. )
  188. {
  189. //
  190. // Find connection object and if we are subscribed , retreive
  191. // first waiting message
  192. //
  193. STI_CONN *pConnectionObject;
  194. DWORD cbNeeded = nSize;
  195. DWORD dwErr;
  196. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  197. if (NOERROR != dwErr ) {
  198. return dwErr;
  199. }
  200. //
  201. // Validate contents of subscribe request
  202. //
  203. if (!LookupConnectionByHandle(Handle,&pConnectionObject)) {
  204. return ERROR_INVALID_HANDLE;
  205. }
  206. dwErr = pConnectionObject->GetNotification(pData,&cbNeeded);
  207. pConnectionObject->Release();
  208. if (pcbNeeded) {
  209. *pcbNeeded = cbNeeded;
  210. }
  211. return dwErr;
  212. }
  213. DWORD
  214. WINAPI
  215. R_StiApiUnSubscribe(
  216. STI_DEVICE_HANDLE Handle
  217. )
  218. {
  219. STI_CONN *pConnectionObject;
  220. BOOL fRet;
  221. DWORD dwErr;
  222. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  223. if (NOERROR != dwErr ) {
  224. return( dwErr );
  225. }
  226. //
  227. // Validate contents of subscribe request
  228. //
  229. // For this call we need to impersonate , because we will need
  230. // access to client process handle
  231. //
  232. dwErr = ::RpcImpersonateClient( NULL ) ;
  233. if( dwErr == NOERROR ) {
  234. //
  235. // Invoke add subscription method on connection object
  236. //
  237. if (!LookupConnectionByHandle(Handle,&pConnectionObject)) {
  238. dwErr = ERROR_INVALID_HANDLE;
  239. }
  240. else
  241. {
  242. fRet = pConnectionObject->SetSubscribeInfo(NULL);
  243. if (fRet)
  244. {
  245. dwErr = NOERROR;
  246. }
  247. else
  248. {
  249. dwErr = ERROR_INVALID_PARAMETER;
  250. }
  251. pConnectionObject->Release();
  252. }
  253. // Go back. RpcRevertToSelf will always succeed in this case (including low mem conditions etc.)
  254. // because it is called on the same thread that RpcImpersonateClient was called on. Therefore, the
  255. // return code is never looked at.
  256. RPC_STATUS rpcStatus = ::RpcRevertToSelf();
  257. }
  258. else {
  259. // Failed to impersonate
  260. }
  261. return dwErr;
  262. }
  263. DWORD
  264. WINAPI
  265. R_StiApiEnableHwNotifications(
  266. LPCWSTR pszServer,
  267. LPCWSTR pszDeviceName,
  268. BOOL bNewState
  269. )
  270. {
  271. USES_CONVERSION;
  272. ACTIVE_DEVICE *pOpenedDevice;
  273. BOOL fRet;
  274. DWORD dwErr;
  275. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  276. if (NOERROR != dwErr ) {
  277. return dwErr;
  278. }
  279. //
  280. // Locate device incrementing it's ref count
  281. //
  282. pOpenedDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, pszDeviceName);
  283. if(!pOpenedDevice) {
  284. // Failed to connect to the device
  285. return ERROR_DEV_NOT_EXIST ;
  286. }
  287. {
  288. TAKE_ACTIVE_DEVICE t(pOpenedDevice);
  289. if (bNewState) {
  290. pOpenedDevice->EnableDeviceNotifications();
  291. }
  292. else {
  293. pOpenedDevice->DisableDeviceNotifications();
  294. }
  295. }
  296. pOpenedDevice->Release();
  297. return NOERROR;
  298. }
  299. DWORD
  300. R_StiApiGetHwNotificationState(
  301. LPCWSTR pszServer,
  302. LPCWSTR pszDeviceName,
  303. LPDWORD pState
  304. )
  305. {
  306. USES_CONVERSION;
  307. ACTIVE_DEVICE *pOpenedDevice;
  308. BOOL fRet;
  309. DWORD dwErr;
  310. dwErr = StiApiAccessCheck(STI_GENERIC_READ);
  311. if (NOERROR != dwErr ) {
  312. return dwErr;
  313. }
  314. //
  315. // Locate device incrementing it's ref count
  316. //
  317. pOpenedDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, pszDeviceName);
  318. if(!pOpenedDevice) {
  319. // Failed to connect to the device
  320. return ERROR_DEV_NOT_EXIST ;
  321. }
  322. if (pOpenedDevice->QueryFlags() & STIMON_AD_FLAG_NOTIFY_ENABLED) {
  323. *pState = TRUE;
  324. }
  325. else {
  326. *pState = FALSE;
  327. }
  328. pOpenedDevice->Release();
  329. return NOERROR;
  330. }
  331. DWORD
  332. WINAPI
  333. R_StiApiLaunchApplication(
  334. LPCWSTR pszServer,
  335. LPCWSTR pszDeviceName,
  336. LPCWSTR pAppName,
  337. LPSTINOTIFY pStiNotify
  338. )
  339. {
  340. USES_CONVERSION;
  341. ACTIVE_DEVICE *pOpenedDevice;
  342. BOOL fRet;
  343. DWORD dwError;
  344. DWORD dwErr;
  345. dwErr = StiApiAccessCheck(STI_GENERIC_READ | STI_GENERIC_EXECUTE);
  346. if (NOERROR != dwErr ) {
  347. return dwErr;
  348. }
  349. //
  350. // Locate device incrementing it's ref count
  351. //
  352. pOpenedDevice = g_pDevMan->IsInList(DEV_MAN_IN_LIST_DEV_ID, pszDeviceName);
  353. if(!pOpenedDevice) {
  354. // Failed to connect to the device
  355. return ERROR_DEV_NOT_EXIST ;
  356. }
  357. //
  358. // Attempt to launch registered application
  359. //
  360. {
  361. TAKE_ACTIVE_DEVICE t(pOpenedDevice);
  362. fRet = pOpenedDevice->ProcessEvent(pStiNotify,TRUE,W2CT(pAppName));
  363. dwError = fRet ? NOERROR : pOpenedDevice->QueryError();
  364. }
  365. pOpenedDevice->Release();
  366. return dwError;
  367. }
  368. DWORD
  369. WINAPI
  370. R_StiApiLockDevice(
  371. LPCWSTR pszServer,
  372. LPCWSTR pszDeviceName,
  373. DWORD dwWait,
  374. BOOL bInServerProcess,
  375. DWORD dwClientThreadId
  376. )
  377. {
  378. BSTR bstrDevName = SysAllocString(pszDeviceName);
  379. DWORD dwError = 0;
  380. if (bstrDevName) {
  381. dwError = (DWORD) g_pStiLockMgr->RequestLock(bstrDevName,
  382. (ULONG) dwWait,
  383. bInServerProcess,
  384. dwClientThreadId);
  385. SysFreeString(bstrDevName);
  386. } else {
  387. dwError = (DWORD) E_OUTOFMEMORY;
  388. }
  389. return dwError;
  390. }
  391. DWORD
  392. WINAPI
  393. R_StiApiUnlockDevice(
  394. LPCWSTR pszServer,
  395. LPCWSTR pszDeviceName,
  396. BOOL bInServerProcess,
  397. DWORD dwClientThreadId
  398. )
  399. {
  400. BSTR bstrDevName = SysAllocString(pszDeviceName);
  401. DWORD dwError = 0;
  402. if (bstrDevName) {
  403. dwError = (DWORD) g_pStiLockMgr->RequestUnlock(bstrDevName,
  404. bInServerProcess,
  405. dwClientThreadId);
  406. SysFreeString(bstrDevName);
  407. } else {
  408. dwError = (DWORD) E_OUTOFMEMORY;
  409. }
  410. return dwError;
  411. }
  412. void
  413. R_WiaGetEventDataAsync(IN PRPC_ASYNC_STATE pAsync,
  414. RPC_BINDING_HANDLE hBinding,
  415. WIA_ASYNC_EVENT_NOTIFY_DATA *pEvent
  416. )
  417. {
  418. RPC_STATUS status;
  419. EnterCriticalSection(&g_RpcEvent.cs);
  420. if(g_RpcEvent.pAsync) {
  421. status = RpcAsyncAbortCall(g_RpcEvent.pAsync, RPC_S_CALL_CANCELLED);
  422. }
  423. g_RpcEvent.pAsync = pAsync;
  424. g_RpcEvent.pEvent = pEvent;
  425. LeaveCriticalSection(&g_RpcEvent.cs);
  426. }
  427. void WiaGetRuntimetEventDataAsync(
  428. IN PRPC_ASYNC_STATE pAsync,
  429. RPC_BINDING_HANDLE hBinding,
  430. STI_CLIENT_CONTEXT ClientContext,
  431. WIA_ASYNC_EVENT_NOTIFY_DATA *pWIA_ASYNC_EVENT_NOTIFY_DATA)
  432. {
  433. DWORD dwStatus = RPC_S_OK;
  434. //
  435. // Do Validation.
  436. //
  437. if (!pAsync)
  438. {
  439. DBG_ERR(("StiRpc Error: Client specified NULL Async State structure!!"));
  440. dwStatus = RPC_S_INVALID_ARG;
  441. }
  442. if (!pWIA_ASYNC_EVENT_NOTIFY_DATA)
  443. {
  444. DBG_ERR(("StiRpc Error: Client specified NULL WIA_ASYNC_EVENT_NOTIFY_DATA structure!!"));
  445. dwStatus = RPC_S_INVALID_ARG;
  446. }
  447. if (dwStatus == RPC_S_OK)
  448. {
  449. if (g_pWiaEventNotifier)
  450. {
  451. //
  452. // Find the client
  453. //
  454. AsyncRPCEventClient *pWiaEventClient = (AsyncRPCEventClient*)g_pWiaEventNotifier->GetClientFromContext(ClientContext);
  455. if (pWiaEventClient)
  456. {
  457. HRESULT hr = pWiaEventClient->saveAsyncParams(pAsync, pWIA_ASYNC_EVENT_NOTIFY_DATA);
  458. //
  459. // Release pWiaEventClient now that we're done
  460. //
  461. pWiaEventClient->Release();
  462. dwStatus = RPC_S_OK;
  463. }
  464. else
  465. {
  466. DBG_ERR(("StiRpc Error: Client %p was not found, cannot update reg info", ClientContext));
  467. dwStatus = RPC_S_INVALID_ARG;
  468. }
  469. }
  470. else
  471. {
  472. DBG_ERR(("StiRpc Error: The WiaEventNotifier is NULL"));
  473. dwStatus = RPC_S_INVALID_ARG;
  474. }
  475. }
  476. else
  477. {
  478. dwStatus = RPC_S_INVALID_ARG;
  479. }
  480. //
  481. // Abort the call if we could not save the async parameters
  482. //
  483. if (dwStatus != RPC_S_OK)
  484. {
  485. RPC_STATUS rpcStatus = RpcAsyncAbortCall(pAsync, dwStatus);
  486. }
  487. }
  488. DWORD OpenClientConnection(
  489. handle_t hBinding,
  490. STI_CLIENT_CONTEXT *pSyncClientContext,
  491. STI_CLIENT_CONTEXT *pAsyncClientContext)
  492. {
  493. DWORD dwStatus = RPC_S_OK;
  494. if (pSyncClientContext && pAsyncClientContext)
  495. {
  496. *pSyncClientContext = (STI_CLIENT_CONTEXT)NativeInterlockedIncrement(&g_lContextNum);
  497. *pAsyncClientContext = *pSyncClientContext;
  498. DBG_TRC(("Opened client connection for %p", *pAsyncClientContext));
  499. if (g_pWiaEventNotifier)
  500. {
  501. WiaEventClient *pWiaEventClient = new AsyncRPCEventClient(*pSyncClientContext);
  502. if (pWiaEventClient)
  503. {
  504. //
  505. // Add the client
  506. //
  507. dwStatus = g_pWiaEventNotifier->AddClient(pWiaEventClient);
  508. if (SUCCEEDED(dwStatus))
  509. {
  510. dwStatus = RPC_S_OK;
  511. }
  512. //
  513. // We can release the client object here. If the WiaEventNotifier successfully
  514. // added it to its list of clients, it would have AddRef'd it. If it wasn't successful,
  515. // we want to destory it here anyway.
  516. //
  517. pWiaEventClient->Release();
  518. }
  519. else
  520. {
  521. dwStatus = RPC_S_OUT_OF_MEMORY;
  522. }
  523. }
  524. }
  525. else
  526. {
  527. dwStatus = RPC_S_INVALID_ARG;
  528. }
  529. return dwStatus;
  530. }
  531. VOID STI_CLIENT_CONTEXT_rundown(
  532. STI_CLIENT_CONTEXT ClientContext)
  533. {
  534. DBG_TRC(("Rundown called for %p", ClientContext));
  535. //
  536. // TBD: Check if client exists, then remove it if the connection hasn't been
  537. // closed correctly.
  538. //
  539. if (g_pWiaEventNotifier)
  540. {
  541. g_pWiaEventNotifier->MarkClientForRemoval(ClientContext);
  542. }
  543. return;
  544. }
  545. DWORD CloseClientConnection(
  546. handle_t hBinding,
  547. STI_CLIENT_CONTEXT ClientContext)
  548. {
  549. //
  550. // TBD: Remove objects used to keep track of client
  551. //
  552. DBG_TRC(("Closed connection for %p", ClientContext));
  553. STI_CLIENT_CONTEXT_rundown(ClientContext);
  554. return RPC_S_OK;
  555. }
  556. DWORD RegisterUnregisterForEventNotification(
  557. handle_t hBinding,
  558. STI_CLIENT_CONTEXT ClientContext,
  559. WIA_ASYNC_EVENT_REG_DATA *pWIA_ASYNC_EVENT_REG_DATA)
  560. {
  561. DWORD dwStatus = RPC_S_OK;
  562. if (g_pWiaEventNotifier)
  563. {
  564. if (pWIA_ASYNC_EVENT_REG_DATA)
  565. {
  566. //
  567. // Find the client
  568. //
  569. WiaEventClient *pWiaEventClient = g_pWiaEventNotifier->GetClientFromContext(ClientContext);
  570. if (pWiaEventClient)
  571. {
  572. EventRegistrationInfo *pEventRegistrationInfo = new EventRegistrationInfo(pWIA_ASYNC_EVENT_REG_DATA->dwFlags,
  573. pWIA_ASYNC_EVENT_REG_DATA->guidEvent,
  574. pWIA_ASYNC_EVENT_REG_DATA->bstrDeviceID,
  575. pWIA_ASYNC_EVENT_REG_DATA->ulCallback);
  576. if (pEventRegistrationInfo)
  577. {
  578. //
  579. // Update its event registration info
  580. //
  581. dwStatus = pWiaEventClient->RegisterUnregisterForEventNotification(pEventRegistrationInfo);
  582. pEventRegistrationInfo->Release();
  583. }
  584. else
  585. {
  586. DBG_ERR(("StiRpc Error: Cannot update reg info - we appear to be out of memory"));
  587. dwStatus = RPC_S_OUT_OF_MEMORY;
  588. }
  589. //
  590. // Release pWiaEventClient now that we're done
  591. //
  592. pWiaEventClient->Release();
  593. }
  594. else
  595. {
  596. DBG_ERR(("StiRpc Error: Client %p was not found, cannot update reg info", ClientContext));
  597. dwStatus = RPC_S_INVALID_ARG;
  598. }
  599. }
  600. else
  601. {
  602. DBG_ERR(("StiRpc Error: Received NULL event reg data from RPC"));
  603. dwStatus = RPC_S_INVALID_ARG;
  604. }
  605. }
  606. else
  607. {
  608. DBG_ERR(("StiRpc Error: WiaEventNotifier is NULL"));
  609. dwStatus = RPC_S_INVALID_ARG;
  610. }
  611. return dwStatus;
  612. }