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.

506 lines
10 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. notesrv.c
  5. Abstract:
  6. DNS Resolver Service
  7. Notifications to other services.
  8. Author:
  9. Glenn Curtis (glennc) Feb 1998
  10. Revision History:
  11. Jim Gilroy (jamesg) March 2000 cleanup
  12. Jim Gilroy (jamesg) Nov 2000 created this module
  13. --*/
  14. #include "local.h"
  15. #include <svcs.h>
  16. //
  17. // DCR: eliminate this module
  18. // entirely unclear why we should be notifying remote
  19. // services of PnP -- weird idea
  20. // only actual DNS events should be in our charter
  21. //
  22. //
  23. // Notification list entry
  24. //
  25. typedef struct _SERVICE_NOTIFICATION_
  26. {
  27. struct _SERVICE_NOTIFICATION_ * pNext;
  28. PWSTR pszServiceName;
  29. DWORD dwControl;
  30. }
  31. SERVICE_NOTIFICATION, * PSERVICE_NOTIFICATION;
  32. //
  33. // Service notification list
  34. // Services we should notify if DNS config changes.
  35. //
  36. PSERVICE_NOTIFICATION g_ServiceNotificationList = NULL;
  37. //
  38. // Locking on service control list
  39. // - overload net failure
  40. //
  41. #define LOCK_SERVICE_LIST() LOCK_NET_FAILURE()
  42. #define UNLOCK_SERVICE_LIST() UNLOCK_NET_FAILURE()
  43. //
  44. // Routines
  45. //
  46. DWORD
  47. SendServiceControlCode(
  48. IN LPWSTR pszServiceName,
  49. IN DWORD dwControl
  50. )
  51. {
  52. DWORD status = NO_ERROR;
  53. SC_HANDLE scManagerHandle = NULL;
  54. SC_HANDLE scServiceHandle = NULL;
  55. SERVICE_STATUS serviceStatus;
  56. DNSDBG( TRACE, (
  57. "SendServiceControlCode( %S, %d )\n",
  58. pszServiceName,
  59. dwControl ));
  60. //
  61. // DCR_FIX: identical to routine in dnsapi.dll
  62. // so either expose OR dnslib it
  63. //
  64. //
  65. // DCR_FIX0: service notification probably not working
  66. // i don't believe this is working because no longer
  67. // local system, probably can't open with this access
  68. //
  69. scManagerHandle = OpenSCManagerW( NULL,
  70. NULL,
  71. SC_MANAGER_ALL_ACCESS );
  72. if ( !scManagerHandle )
  73. {
  74. DNSDBG( ANY, (
  75. "OpenSCManagerW( %S ) -- FAILED! %d\n",
  76. pszServiceName,
  77. GetLastError() ));
  78. return GetLastError();
  79. }
  80. scServiceHandle = OpenServiceW( scManagerHandle,
  81. pszServiceName,
  82. SERVICE_ALL_ACCESS );
  83. if ( !scServiceHandle )
  84. {
  85. CloseServiceHandle( scManagerHandle );
  86. return GetLastError();
  87. }
  88. if ( !ControlService( scServiceHandle,
  89. dwControl,
  90. &serviceStatus ) )
  91. {
  92. status = GetLastError();
  93. }
  94. CloseServiceHandle( scServiceHandle );
  95. CloseServiceHandle( scManagerHandle );
  96. return status;
  97. }
  98. VOID
  99. ServiceNotificationCallback(
  100. IN PVOID pContext
  101. )
  102. {
  103. PSERVICE_NOTIFICATION pserviceNot;
  104. UNREFERENCED_PARAMETER( pContext );
  105. DNSLOG_F1( " Inside callback function ServiceNotificationCallback" );
  106. //
  107. // Send PnP to any registered services
  108. //
  109. LOCK_SERVICE_LIST();
  110. for ( pserviceNot = g_ServiceNotificationList;
  111. pserviceNot != NULL;
  112. pserviceNot = pserviceNot->pNext
  113. )
  114. {
  115. DNSLOG_F3( " Sending PnP notification to %S with control %d",
  116. pserviceNot->pszServiceName,
  117. pserviceNot->dwControl );
  118. SendServiceControlCode(
  119. pserviceNot->pszServiceName,
  120. pserviceNot->dwControl );
  121. }
  122. UNLOCK_SERVICE_LIST();
  123. //
  124. // always indicate PnP to DNS server
  125. //
  126. DNSLOG_F2(
  127. " Sending PnP notification to DNS server with control %d",
  128. SERVICE_CONTROL_PARAMCHANGE );
  129. SendServiceControlCode(
  130. L"dns",
  131. SERVICE_CONTROL_PARAMCHANGE );
  132. DNSLOG_F1( " Leaving callback function ServiceNotificationCallback" );
  133. DNSLOG_F1( "" );
  134. }
  135. VOID
  136. SendServiceNotifications(
  137. VOID
  138. )
  139. /*++
  140. Routine Description:
  141. Send service notifications.
  142. Arguments:
  143. None
  144. Return Value:
  145. None
  146. --*/
  147. {
  148. DNSDBG( ANY, ( "SendServiceNotifications()\n" ));
  149. DNSLOG_F1( "Notify any other services of the PnP event" );
  150. //
  151. // DCR: cheesy hack to notify DNS server of paramchange
  152. //
  153. if ( g_IsDnsServer )
  154. {
  155. SendServiceControlCode(
  156. L"Dns",
  157. SERVICE_CONTROL_PARAMCHANGE );
  158. }
  159. //
  160. // notify other services by queuing callback
  161. // - callback function then notifies services
  162. //
  163. RtlQueueWorkItem(
  164. ServiceNotificationCallback, // callback
  165. NULL, // context data
  166. WT_EXECUTEONLYONCE ); // flags
  167. }
  168. VOID
  169. CleanupServiceNotification(
  170. VOID
  171. )
  172. /*++
  173. Routine Description:
  174. Cleanup service notification list.
  175. Arguments:
  176. None
  177. Return Value:
  178. None
  179. --*/
  180. {
  181. PSERVICE_NOTIFICATION pnext;
  182. PSERVICE_NOTIFICATION pfree;
  183. LOCK_SERVICE_LIST();
  184. pnext = g_ServiceNotificationList;
  185. while ( pnext )
  186. {
  187. PSERVICE_NOTIFICATION pfree = pnext;
  188. pnext = pnext->pNext;
  189. GENERAL_HEAP_FREE( pfree );
  190. }
  191. g_ServiceNotificationList = NULL;
  192. UNLOCK_SERVICE_LIST();
  193. }
  194. //
  195. // Remote API for registration\deregistraion
  196. //
  197. BOOL
  198. CRrRegisterParamChange(
  199. IN DNS_RPC_HANDLE Reserved,
  200. IN LPWSTR pszServiceName,
  201. IN DWORD dwControl
  202. )
  203. /*++
  204. Routine Description:
  205. Arguments:
  206. pszServiceName -- name of service to register
  207. dwControl -- control to send
  208. Return Value:
  209. TRUE if success
  210. FALSE on error
  211. --*/
  212. {
  213. PSERVICE_NOTIFICATION pprevService = NULL;
  214. PSERVICE_NOTIFICATION pservice;
  215. DWORD countService = 0;
  216. UNREFERENCED_PARAMETER(Reserved);
  217. DNSLOG_F1( "DNS Caching Resolver Service - CRrRegisterParamChange" );
  218. DNSLOG_F2( "Going to try register service notification entry for %S",
  219. pszServiceName );
  220. DNSLOG_F2( "Control: %d", dwControl );
  221. DNSDBG( RPC, (
  222. "CRrRegisterParamChange( %S, control=%d )\n",
  223. pszServiceName,
  224. dwControl ));
  225. //
  226. // access check
  227. // refuse setting check on resolver service itself
  228. //
  229. if ( ClientThreadNotAllowedAccess() )
  230. {
  231. DNSLOG_F1( "CRrRegisterParamChange - ERROR_ACCESS_DENIED" );
  232. return FALSE;
  233. }
  234. if ( !pszServiceName ||
  235. ! wcsicmp_ThatWorks( DNS_RESOLVER_SERVICE, pszServiceName ) )
  236. {
  237. DNSLOG_F1( "CRrRegisterParamChange - ERROR_INVALID_PARAMETER" );
  238. return FALSE;
  239. }
  240. //
  241. // search service list for service
  242. // - if service exists, bail
  243. // - if too many services, bail
  244. //
  245. LOCK_SERVICE_LIST();
  246. pservice = g_ServiceNotificationList;
  247. while ( pservice )
  248. {
  249. if ( ! wcsicmp_ThatWorks(
  250. pservice->pszServiceName,
  251. pszServiceName ) )
  252. {
  253. pservice->dwControl = dwControl;
  254. UNLOCK_SERVICE_LIST();
  255. DNSLOG_F2(
  256. "Service already registered, resetting control %d\n"
  257. "Returning SUCCESS",
  258. dwControl );
  259. return TRUE;
  260. }
  261. pprevService = pservice;
  262. pservice = pservice->pNext;
  263. countService++;
  264. }
  265. if ( countService > MAX_DNS_NOTIFICATION_LIST_SIZE )
  266. {
  267. UNLOCK_SERVICE_LIST();
  268. DNSLOG_F2(
  269. "Registered service %S, returning error.\n"
  270. "\tThere are too many services alreadyin the notification list!",
  271. pszServiceName );
  272. return FALSE;
  273. }
  274. //
  275. // service not found -- add it
  276. // - alloc single blob
  277. // - name of service will follow structure
  278. //
  279. // DCR: if always doing single blob, why have pointer? duh
  280. //
  281. pservice = GENERAL_HEAP_ALLOC(
  282. sizeof(SERVICE_NOTIFICATION)
  283. + ((wcslen(pszServiceName) + 1) * sizeof(WCHAR)) );
  284. if ( !pservice )
  285. {
  286. UNLOCK_SERVICE_LIST();
  287. DNSLOG_F1( "Could not allocate memory to register service," );
  288. DNSLOG_F1( "returning FAILURE" );
  289. return FALSE;
  290. }
  291. pservice->pNext = NULL;
  292. pservice->dwControl = dwControl;
  293. pservice->pszServiceName = (LPWSTR) ( (LPBYTE) pservice +
  294. sizeof(SERVICE_NOTIFICATION) );
  295. wcscpy(
  296. pservice->pszServiceName,
  297. pszServiceName );
  298. if ( pprevService )
  299. {
  300. pprevService->pNext = pservice;
  301. }
  302. else
  303. {
  304. g_ServiceNotificationList = pservice;
  305. }
  306. UNLOCK_SERVICE_LIST();
  307. DNSLOG_F2(
  308. "Registered service %S, returning SUCCESS",
  309. pszServiceName );
  310. return TRUE;
  311. }
  312. BOOL
  313. CRrDeregisterParamChange(
  314. IN DNS_RPC_HANDLE Reserved,
  315. IN LPWSTR pszServiceName
  316. )
  317. /*++
  318. Routine Description:
  319. Arguments:
  320. Return Value:
  321. --*/
  322. {
  323. PSERVICE_NOTIFICATION pprevService = NULL;
  324. PSERVICE_NOTIFICATION pservice;
  325. UNREFERENCED_PARAMETER(Reserved);
  326. DNSLOG_F1( "DNS Caching Resolver Service - CRrDeregisterParamChange" );
  327. DNSLOG_F2( "Going to try remove service notification entry for %S",
  328. pszServiceName );
  329. DNSDBG( RPC, (
  330. "CRrDeregisterParamChange( %S )\n",
  331. pszServiceName ));
  332. if ( ClientThreadNotAllowedAccess() )
  333. {
  334. DNSLOG_F1( "CRrDeregisterParamChange - ERROR_ACCESS_DENIED" );
  335. return FALSE;
  336. }
  337. //
  338. // search service list for desired service
  339. // - delete entry if found
  340. //
  341. LOCK_SERVICE_LIST();
  342. pservice = g_ServiceNotificationList;
  343. while ( pservice )
  344. {
  345. if ( ! wcsicmp_ThatWorks(
  346. pservice->pszServiceName,
  347. pszServiceName ) )
  348. {
  349. // service found, cut from list
  350. if ( pprevService )
  351. {
  352. pprevService->pNext = pservice->pNext;
  353. }
  354. else
  355. {
  356. g_ServiceNotificationList = pservice->pNext;
  357. }
  358. UNLOCK_SERVICE_LIST();
  359. GENERAL_HEAP_FREE( pservice );
  360. DNSLOG_F1( "Found entry, returning SUCCESS" );
  361. return TRUE;
  362. }
  363. pprevService = pservice;
  364. pservice = pservice->pNext;
  365. }
  366. UNLOCK_SERVICE_LIST();
  367. DNSLOG_F1( "Did not find entry, returning FAILURE" );
  368. return FALSE;
  369. }
  370. //
  371. // End notesrv.c
  372. //