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.

529 lines
12 KiB

  1. /*++
  2. Copyright (C) 2001 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. NCmgr.cxx
  6. Abstract:
  7. Implenetation of functions that operate on the name cache.
  8. The initialization and delete functions are declared in NCmgr.hxx.
  9. The rest of the functions are in winsplp.h.
  10. Author:
  11. Felix Maxa (AMaxa) 16 May 2001
  12. Revision History:
  13. --*/
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include <winsock2.h>
  17. #include <iphlpapi.h>
  18. #include "ncmgr.hxx"
  19. #include "NCshared.hxx"
  20. #include "ncnamecache.hxx"
  21. #include "ncsockets.hxx"
  22. TNameResolutionCache *g_pNameCache = NULL;
  23. WCHAR g_szHttpPrefix0[] = L"\\\\http://";
  24. WCHAR g_szHttpPrefix1[] = L"\\\\https://";
  25. /*++
  26. Name:
  27. IsHttpPrinter
  28. Description:
  29. Checks whether a string can be the name of an HTTP printer.
  30. Arguments:
  31. pszPrinter - string. Can be NULL.
  32. Return Value:
  33. TRUE - pszPrinter has the prefix characteristic to HTTP printers
  34. FALSE - pszPrinter does not have the prefix characteristic to HTTP printers
  35. --*/
  36. BOOL
  37. IsHttpPrinter(
  38. IN LPCWSTR pszPrinter
  39. )
  40. {
  41. BOOL bIsHttp = FALSE;
  42. if (pszPrinter && *pszPrinter)
  43. {
  44. bIsHttp = !_wcsnicmp(pszPrinter, g_szHttpPrefix0, COUNTOF(g_szHttpPrefix0) - 1) ||
  45. !_wcsnicmp(pszPrinter, g_szHttpPrefix1, COUNTOF(g_szHttpPrefix1) - 1);
  46. }
  47. return bIsHttp;
  48. }
  49. /*++
  50. Name:
  51. CacheInitNameCache
  52. Description:
  53. Initialize the name cache object and the object that listens for
  54. IP changes for the local machine. This function must be called
  55. before any other thread has a chance of calling the rest of the
  56. cache functions. This is because we do not protect access on
  57. the pointer to the cache object.
  58. Arguments:
  59. None.
  60. Return Value:
  61. S_OK - the cache was initialized successfully
  62. other HRESULT - an error occurred, the cache cannot be used.
  63. --*/
  64. HRESULT
  65. CacheInitNameCache(
  66. VOID
  67. )
  68. {
  69. HRESULT hr = S_OK;
  70. g_pNameCache = new TNameResolutionCache;
  71. hr = g_pNameCache ? S_OK : E_OUTOFMEMORY;
  72. return hr;
  73. }
  74. /*++
  75. Name:
  76. CacheDeleteNameCache
  77. Description:
  78. Clean up the name cache object and the object that listens for
  79. IP changes for the local machine.
  80. Arguments:
  81. None.
  82. Return Value:
  83. None.
  84. --*/
  85. VOID
  86. CacheDeleteNameCache(
  87. VOID
  88. )
  89. {
  90. delete g_pNameCache;
  91. }
  92. /*++
  93. Name:
  94. CacheAddName
  95. Description:
  96. Adds a name to the local cache. The name will be added only if
  97. it refers to the local machine or cluster resources running on
  98. the local machine.
  99. Arguments:
  100. pszName - server name. Must be "\\" prefixed !!!
  101. Return Value:
  102. S_OK - name was added to the cache.
  103. S_FALSE - name does not refer to the local machine
  104. other HRESULT - an error occurred while executing the function
  105. --*/
  106. HRESULT
  107. CacheAddName(
  108. IN LPCWSTR pszName
  109. )
  110. {
  111. HRESULT hr = E_INVALIDARG;
  112. if (pszName &&
  113. *pszName &&
  114. pszName[0] == L'\\' &&
  115. pszName[1] == L'\\' &&
  116. !IsHttpPrinter(pszName))
  117. {
  118. WCHAR *pcMark = wcschr(pszName + 2, L'\\');
  119. if (pcMark)
  120. {
  121. *pcMark = 0;
  122. }
  123. hr = g_pNameCache->AddName(pszName + 2);
  124. if (pcMark)
  125. {
  126. *pcMark = L'\\';
  127. }
  128. }
  129. return hr;
  130. }
  131. /*++
  132. Name:
  133. CacheCreateAndAddNode
  134. Description:
  135. Creates a node supporting the "pszName". The IP addresses
  136. for the node are determined by calling getaddrinfo(pszName).
  137. Arguments:
  138. pszName - server name. Cannnot be "\\" prefixed.
  139. bClusterNode - TRUE if the node is created by a cluster pIniSpooler
  140. Return Value:
  141. S_OK - node was added to the cache. (or existed there already)
  142. other HRESULT - an error occurred while executing the function
  143. --*/
  144. HRESULT
  145. CacheCreateAndAddNode(
  146. IN LPCWSTR pszName,
  147. IN BOOL bClusterNode
  148. )
  149. {
  150. HRESULT hr = g_pNameCache->CreateAndAddNode(pszName, bClusterNode);
  151. return hr;
  152. }
  153. /*++
  154. Name:
  155. CacheCreateAndAddNodeWithIPAddresses
  156. Description:
  157. Creates a node supporting the "pszName". The IP addresses
  158. are passed in a argument by the caller. Thus a certain
  159. node can support IP addresses that don't event resolve to
  160. the pszName itself.
  161. Arguments:
  162. pszName - server name. Cannnot be "\\" prefixed.
  163. bClusterNode - TRUE if the node is created by a cluster pIniSpooler
  164. ppszIPAddresses - array of strings represeting IP addresses
  165. cIPAddresses - number of strings in the array
  166. Return Value:
  167. S_OK - node was added to the cache. (or existed there already)
  168. other HRESULT - an error occurred while executing the function
  169. --*/
  170. HRESULT
  171. CacheCreateAndAddNodeWithIPAddresses(
  172. IN LPCWSTR pszName,
  173. IN BOOL bClusterNode,
  174. IN LPCWSTR *ppszIPAddresses,
  175. IN DWORD cIPAddresses
  176. )
  177. {
  178. HRESULT hr = g_pNameCache->CreateAndAddNodeWithIPAddresses(pszName,
  179. bClusterNode,
  180. ppszIPAddresses,
  181. cIPAddresses);
  182. return hr;
  183. }
  184. /*++
  185. Name:
  186. CacheDeleteNode
  187. Description:
  188. Deletes a node from the cache.
  189. Arguments:
  190. pszName - server name. Cannnot be "\\" prefixed.
  191. Return Value:
  192. S_OK - node was deleted from the cache
  193. S_FALSE - node was not found in cache
  194. other HRESULT - an error occurred while executing the function
  195. --*/
  196. HRESULT
  197. CacheDeleteNode(
  198. IN LPCWSTR pszNode
  199. )
  200. {
  201. return g_pNameCache->DeleteNode(pszNode);
  202. }
  203. /*++
  204. Name:
  205. CacheIsNameInNodeList
  206. Description:
  207. Checks if the node pszNode supports the pszName name in its list.
  208. Arguments:
  209. psznode - node in the cache list
  210. pszName - server name. Cannnot be "\\" prefixed.
  211. Return Value:
  212. S_OK - pszName is in the cache of pszNode
  213. S_FALSE - pszName is NOT in the cache of pszNode
  214. other HRESULT - an error occurred while executing the function
  215. --*/
  216. HRESULT
  217. CacheIsNameInNodeList(
  218. IN LPCWSTR pszNode,
  219. IN LPCWSTR pszName
  220. )
  221. {
  222. return g_pNameCache->IsNameInNodeCache(pszNode, pszName);
  223. }
  224. /*++
  225. Name:
  226. CacheRefresh
  227. Description:
  228. Refershes the list of IP addresses supported by the local machine node.
  229. Should be called when a change of IP PNP event occurrs. The name of
  230. the local node is the short name of the local machine.
  231. Arguments:
  232. None.
  233. Return Value:
  234. S_OK - local machine node was refreshed
  235. other HRESULT - an error occurred while executing the function
  236. --*/
  237. HRESULT
  238. CacheRefresh(
  239. VOID
  240. )
  241. {
  242. HRESULT hr = g_pNameCache->RefreshNode(szMachineName + 2);
  243. return hr;
  244. }
  245. /*++
  246. Name:
  247. PnpIPAddressChangeListener
  248. Description:
  249. This function loops and waits for events that indicate changes in IP address.
  250. Chnages in ip address occurr when you can "ipconfig /release", when the IP
  251. address resource of a cluster comes online or goes offline, etc.
  252. The function takes ownership of the pointer (the meory pointer to by the pointer)
  253. Also, the function takes ownership of the hWaitEvent.
  254. The function does not take ownership of the hTerminateEvent. That event must be
  255. aglobal mutex for the spooler process and can be used to terminate the looping thread.
  256. Arguments:
  257. pVoid - pointer to IPADDRESSCHANGEARGS structure
  258. Return Value:
  259. None.
  260. --*/
  261. VOID
  262. PnpIPAddressChangeListener(
  263. VOID *pVoid
  264. )
  265. {
  266. SIPADDRESSCHANGEARGS *pArgs = reinterpret_cast<SIPADDRESSCHANGEARGS *>(pVoid);
  267. PFNVOID pfnCallBack = pArgs->pfnCallBack;
  268. HANDLE hTerminateEvent = pArgs->hTerminateEvent;
  269. OVERLAPPED InterfaceChange = {0};
  270. BOOL bLoop = TRUE;
  271. InterfaceChange.hEvent = pArgs->hWaitEvent;
  272. while (bLoop)
  273. {
  274. HANDLE hNotify = NULL;
  275. DWORD Error = NotifyAddrChange(&hNotify, &InterfaceChange);
  276. bLoop = FALSE;
  277. if (Error == ERROR_IO_PENDING)
  278. {
  279. HANDLE hHandles[2] = {InterfaceChange.hEvent, hTerminateEvent};
  280. DWORD cHandles = hTerminateEvent ? 2 : 1;
  281. DWORD WaitStatus;
  282. WaitStatus = WaitForMultipleObjects(cHandles, hHandles, FALSE, INFINITE);
  283. switch(WaitStatus)
  284. {
  285. case WAIT_OBJECT_0:
  286. {
  287. bLoop = TRUE;
  288. (*pfnCallBack)();
  289. break;
  290. }
  291. case WAIT_OBJECT_0 + 1:
  292. {
  293. //
  294. // We're done waiting, bLoop is FALSE so the while will terminate
  295. //
  296. break;
  297. }
  298. default:
  299. {
  300. DBGMSG(DBG_ERROR, ("PnpIPAddressChangeListener WaitForMultipleObjects failed\n"));
  301. break;
  302. }
  303. }
  304. }
  305. else
  306. {
  307. DBGMSG(DBG_WARN, ("PnpIPAddressChangeListener NotifyAddrChange failed. Win32 error %u\n", Error));
  308. }
  309. }
  310. CloseHandle(InterfaceChange.hEvent);
  311. delete pArgs;
  312. }
  313. /*++
  314. Name:
  315. InitializePnPIPAddressChangeListener
  316. Description:
  317. Launches a separate thread which waits for IP change events.
  318. Arguments:
  319. pfnCallBack - function to call when a change in IP address occurs
  320. Return Value:
  321. S_OK - the IP change listener was initialized successfully
  322. other HRESULT - an error occurred while executing the function
  323. --*/
  324. HRESULT
  325. InitializePnPIPAddressChangeListener(
  326. IN PFNVOID pfnCallBack
  327. )
  328. {
  329. TStatusH hRetval;
  330. SIPADDRESSCHANGEARGS *pArgs = new SIPADDRESSCHANGEARGS;
  331. hRetval DBGCHK = pfnCallBack ? (pArgs ? S_OK : E_OUTOFMEMORY) : E_INVALIDARG;
  332. if (SUCCEEDED(hRetval))
  333. {
  334. HANDLE hThread;
  335. DWORD ThreadId;
  336. pArgs->pfnCallBack = pfnCallBack;
  337. //
  338. // When the spooler can finally shut down properly, then we can specify
  339. // here an event to terminate the PnpIPAddressChangeListener
  340. //
  341. pArgs->hTerminateEvent = NULL;
  342. //
  343. // Note that PnpIPAddressChangeListener takes ownership of this event
  344. // so PnpIPAddressChangeListener must call CloseHandle on the event
  345. //
  346. pArgs->hWaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  347. hRetval DBGCHK = pArgs->hWaitEvent ? S_OK : GetLastErrorAsHResult();
  348. if (SUCCEEDED(hRetval))
  349. {
  350. if (hThread = CreateThread(NULL,
  351. 0,
  352. (LPTHREAD_START_ROUTINE)PnpIPAddressChangeListener,
  353. pArgs,
  354. 0,
  355. &ThreadId))
  356. {
  357. CloseHandle(hThread);
  358. //
  359. // Note that PnpIPAddressChangeListener takes ownership of pArgs and must free it
  360. //
  361. pArgs = NULL;
  362. }
  363. else
  364. {
  365. hRetval DBGCHK = GetLastErrorAsHResult();
  366. }
  367. }
  368. }
  369. delete pArgs;
  370. return hRetval;
  371. }