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.

627 lines
16 KiB

  1. //***************************************************************************
  2. //
  3. // UPDATECFG.H
  4. //
  5. // Module: WMI Framework Instance provider
  6. //
  7. // Purpose: Defines class NlbConfigurationUpdate, used for
  8. // async update of NLB properties associated with a particular NIC.
  9. //
  10. // Copyright (c)2001 Microsoft Corporation, All Rights Reserved
  11. //
  12. // History:
  13. //
  14. // 04/05/01 JosephJ Created
  15. //
  16. //***************************************************************************
  17. //
  18. // The header of a completion header stored as a REG_BINARY value in
  19. // the registry.
  20. //
  21. typedef struct {
  22. UINT Version;
  23. UINT Generation; // Redundant, used for internal consistancy check
  24. UINT CompletionCode;
  25. UINT Reserved;
  26. } NLB_COMPLETION_RECORD, *PNLB_COMPLETION_RECORD;
  27. #define NLB_CURRENT_COMPLETION_RECORD_VERSION 0x3d7376e2
  28. //
  29. // Prefix of the global event name used to control update access to the specifed
  30. // NIC.
  31. // Mutex1 has format: <prefix>
  32. // Mutex2 has format: <prefix><NicGuid>
  33. // Example mutex1 name: NLB_D6901862
  34. // Example mutex2 name: NLB_D6901862{EBE09517-07B4-4E88-AAF1-E06F5540608B}
  35. //
  36. // The value "D6901862" is a random number.
  37. //
  38. #define NLB_CONFIGURATION_EVENT_PREFIX L"NLB_D6901862"
  39. #define NLB_CONFIGURATION_MUTEX_PREFIX L"NLB_D6901863"
  40. //
  41. // Milliseconds to wait before giving up on trying to acquire the
  42. // NLB mutex.
  43. //
  44. #define NLB_MUTEX_TIMEOUT 100
  45. //
  46. // The maximum generation difference between the oldest valid completion
  47. // record and the current one. Records older then the oldest valid record
  48. // are subject to pruning.
  49. //
  50. #define NLB_MAX_GENERATION_GAP 10
  51. // Handle to dll - used in call to LoadString
  52. extern HMODULE ghModule;
  53. //
  54. // Used for maintaining a log on the stack.
  55. // Usage is NOT thread-safe -- each instance must be used
  56. // by a single thread.
  57. // 01/01/02 JosephJ Copied over from NLBMGR.EXE (nlbmgr\exe2)
  58. //
  59. class CLocalLogger
  60. {
  61. public:
  62. CLocalLogger(VOID)
  63. : m_pszLog (NULL), m_LogSize(0), m_CurrentOffset(0)
  64. {
  65. m_Empty[0] = 0; // The empty string.
  66. }
  67. ~CLocalLogger()
  68. {
  69. delete[] m_pszLog;
  70. m_pszLog=NULL;
  71. }
  72. VOID
  73. Log(
  74. IN UINT ResourceID,
  75. ...
  76. );
  77. VOID
  78. ExtractLog(OUT LPCWSTR &pLog, UINT &Size)
  79. //
  80. // pLog -- set to pointer to internal buffer if there is stuff in the
  81. // log, otherwise NULL.
  82. //
  83. // Size -- in chars; includes ending NULL
  84. //
  85. {
  86. if (m_CurrentOffset != 0)
  87. {
  88. pLog = m_pszLog;
  89. Size = m_CurrentOffset+1; // + 1 for ending NULL.
  90. }
  91. else
  92. {
  93. pLog = NULL;
  94. Size = 0;
  95. }
  96. }
  97. LPCWSTR
  98. GetStringSafe(void)
  99. {
  100. LPCWSTR szLog = NULL;
  101. UINT Size;
  102. ExtractLog(REF szLog, REF Size);
  103. if (szLog == NULL)
  104. {
  105. //
  106. // Replace NULL by a pointer to an empty string.
  107. //
  108. szLog = m_Empty;
  109. }
  110. return szLog;
  111. }
  112. private:
  113. WCHAR *m_pszLog;
  114. UINT m_LogSize; // Current size of the log.
  115. UINT m_CurrentOffset; // Characters left in the log.
  116. WCHAR m_Empty[1]; // The empty string.
  117. };
  118. class NlbConfigurationUpdate
  119. {
  120. public:
  121. //
  122. // Static initialization function -- call in process-attach
  123. //
  124. static
  125. VOID
  126. StaticInitialize(
  127. VOID
  128. );
  129. //
  130. // Static deinitialization function -- call in process-detach
  131. //
  132. static
  133. VOID
  134. StaticDeinitialize(
  135. VOID
  136. );
  137. //
  138. // Stop accepting new queries, wait for existing (pending) queries
  139. // to complete.
  140. //
  141. static
  142. VOID
  143. PrepareForDeinitialization(
  144. VOID
  145. );
  146. //
  147. // Return true IFF there is no pending activity. If you return
  148. // TRUE, try not to start new pending activity.
  149. //
  150. static
  151. BOOL
  152. CanUnloadNow(
  153. VOID
  154. );
  155. //
  156. // Returns the current configuration on the specific NIC.
  157. //
  158. static
  159. WBEMSTATUS
  160. GetConfiguration(
  161. IN LPCWSTR szNicGuid,
  162. OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCurrentCfg
  163. );
  164. //
  165. // Called to initiate update to a new cluster state on that NIC. This
  166. // could include moving from a NLB-bound state to the NLB-unbound state.
  167. // *pGeneration is used to reference this particular update request.
  168. //
  169. static
  170. WBEMSTATUS
  171. DoUpdate(
  172. IN LPCWSTR szNicGuid,
  173. IN LPCWSTR szClientDescription,
  174. IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState,
  175. OUT UINT *pGeneration,
  176. OUT WCHAR **ppLog // free using delete operator.
  177. );
  178. /*++
  179. ppLog -- will point to a NULL-terminated string which contains
  180. any messages to be displayed to the user. The string may contain
  181. embedded (WCHAR) '\n' characters to delimit lines.
  182. NOTE: ppLog will be filled out properly EVEN ON FAILURE. If non-null
  183. it must be deleted by the caller.
  184. --*/
  185. //
  186. // Called to get the status of an update request, identified by
  187. // Generation.
  188. //
  189. static
  190. WBEMSTATUS
  191. GetUpdateStatus(
  192. IN LPCWSTR szNicGuid,
  193. IN UINT Generation,
  194. IN BOOL fDelete, // Delete record if it exists
  195. OUT WBEMSTATUS *pCompletionStatus,
  196. OUT WCHAR **ppLog // free using delete operator.
  197. );
  198. static
  199. DWORD
  200. WINAPI
  201. s_AsyncUpdateThreadProc(
  202. LPVOID lpParameter // thread data
  203. );
  204. private:
  205. ///////////////////////////////////////////////////////////////////////////////
  206. //
  207. // S T A T I C S T U F F
  208. //
  209. ///////////////////////////////////////////////////////////////////////////////
  210. //
  211. // A single static lock serialzes all access.
  212. // Use sfn_Lock and sfn_Unlock.
  213. //
  214. static
  215. CRITICAL_SECTION s_Crit;
  216. static
  217. BOOL
  218. s_fStaticInitialized; // set to true once StaticInitialize is called.
  219. static
  220. BOOL
  221. s_fInitialized; // Set to true if we're in the position to
  222. // handle any *new* update requests or even queries.
  223. // Will be set to false if we're in the process
  224. // of de-initializing.
  225. //
  226. // Global list of current updates, one per NIC.
  227. //
  228. static
  229. LIST_ENTRY
  230. s_listCurrentUpdates;
  231. static
  232. VOID
  233. sfn_Lock(
  234. VOID
  235. )
  236. {
  237. EnterCriticalSection(&s_Crit);
  238. }
  239. static
  240. VOID
  241. sfn_Unlock(
  242. VOID
  243. )
  244. {
  245. LeaveCriticalSection(&s_Crit);
  246. }
  247. //
  248. // Looks up the current update for the specific NIC.
  249. // We don't bother to reference count because this object never
  250. // goes away once created -- it's one per unique NIC GUID for as long as
  251. // the DLL is loaded (may want to revisit this).
  252. //
  253. //
  254. static
  255. WBEMSTATUS
  256. sfn_LookupUpdate(
  257. IN LPCWSTR szNic,
  258. IN BOOL fCreate, // Create if required
  259. OUT NlbConfigurationUpdate ** ppUpdate
  260. );
  261. //
  262. // Save the specified completion status to the registry.
  263. //
  264. static
  265. WBEMSTATUS
  266. sfn_RegSetCompletion(
  267. IN LPCWSTR szNicGuid,
  268. IN UINT Generation,
  269. IN WBEMSTATUS CompletionStatus
  270. );
  271. //
  272. // Retrieve the specified completion status from the registry.
  273. //
  274. static
  275. WBEMSTATUS
  276. sfn_RegGetCompletion(
  277. IN LPCWSTR szNicGuid,
  278. IN UINT Generation,
  279. OUT WBEMSTATUS *pCompletionStatus,
  280. OUT WCHAR **ppLog // free using delete operator.
  281. );
  282. //
  283. // Delete the specified completion status from the registry.
  284. //
  285. static
  286. VOID
  287. sfn_RegDeleteCompletion(
  288. IN LPCWSTR szNicGuid,
  289. IN UINT Generation
  290. );
  291. //
  292. // Create the specified subkey key (for r/w access) for the specified
  293. // the specified NIC.
  294. //
  295. static
  296. HKEY
  297. sfn_RegCreateKey(
  298. IN LPCWSTR szNicGuid,
  299. IN LPCWSTR szSubKey,
  300. IN BOOL fVolatile,
  301. OUT BOOL *fExists
  302. );
  303. //
  304. // Open the specified subkey key (for r/w access) for the specified
  305. // the specified NIC.
  306. //
  307. static
  308. HKEY
  309. sfn_RegOpenKey(
  310. IN LPCWSTR szNicGuid,
  311. IN LPCWSTR szSubKey
  312. );
  313. static
  314. VOID
  315. sfn_ReadLog(
  316. IN HKEY hKeyLog,
  317. IN UINT Generation,
  318. OUT LPWSTR *ppLog
  319. );
  320. static
  321. VOID
  322. sfn_WriteLog(
  323. IN HKEY hKeyLog,
  324. IN UINT Generation,
  325. IN LPCWSTR pLog,
  326. IN BOOL fAppend
  327. );
  328. ///////////////////////////////////////////////////////////////////////////////
  329. //
  330. // P E R I N S T A N C E S T U F F
  331. //
  332. ///////////////////////////////////////////////////////////////////////////////
  333. //
  334. // Used in the global one-per-NIC list of updates maintained in
  335. // s_listCurrentUpdates;
  336. //
  337. LIST_ENTRY m_linkUpdates;
  338. #define NLB_GUID_LEN 38
  339. #define NLB_GUID_STRING_SIZE 40 // 38 for the GUID plus trailing NULL + pad
  340. WCHAR m_szNicGuid[NLB_GUID_STRING_SIZE]; // NIC's GUID in text form
  341. LONG m_RefCount;
  342. typedef enum
  343. {
  344. UNINITIALIZED, // IDLE -- no ongoing updates
  345. IDLE, // IDLE -- no ongoing updates
  346. ACTIVE // There is an ongoing update
  347. } MyState;
  348. MyState m_State;
  349. //
  350. // Following mutexes are used to ensure that only a single concurrent
  351. // update can happen per NIC.
  352. //
  353. struct
  354. {
  355. HANDLE hMtx1; // Mutex handle; Obtained 1st
  356. HANDLE hMtx2; // Mutex handle; Obtained 2nd, then hMtx1 is released.
  357. HANDLE hEvt; // Unnamed evt, signaled when hMtx2 is obtained.
  358. } m_mutex;
  359. //
  360. // The following fields are valid only when the state is ACTIVE
  361. //
  362. UINT m_Generation; // Current generation count
  363. #define NLBUPD_MAX_CLIENT_DESCRIPTION_LENGTH 64
  364. WCHAR m_szClientDescription[NLBUPD_MAX_CLIENT_DESCRIPTION_LENGTH+1];
  365. DWORD m_AsyncThreadId; // Thread doing async config update operation.
  366. HANDLE m_hAsyncThread; // ID of above thread.
  367. HKEY m_hCompletionKey; // Key to the registry where
  368. // completions are stored
  369. //
  370. // A snapshot of the cluster configuration state at the start
  371. // of the update BUG -- can this be zeromemoried?
  372. //
  373. NLB_EXTENDED_CLUSTER_CONFIGURATION m_OldClusterConfig;
  374. //
  375. // The requested final state
  376. //
  377. NLB_EXTENDED_CLUSTER_CONFIGURATION m_NewClusterConfig;
  378. //
  379. // Completion status of the current update.
  380. // Could be PENDING.
  381. //
  382. WBEMSTATUS m_CompletionStatus;
  383. //
  384. // END -- of fields that are valid only when the state is ACTIVE
  385. //
  386. //
  387. // Constructor and destructor -- note that these are private
  388. // In fact, the constructor is only called from sfn_LookupUpdate
  389. // and the destructor from mfn_Dereference.
  390. //
  391. NlbConfigurationUpdate(VOID);
  392. ~NlbConfigurationUpdate();
  393. //
  394. // Try to acquire the machine-wide
  395. // NLB configuration update event for this NIC, and create the
  396. // appropriate keys in the registry to track this update.
  397. // NOTE: ppLog will be filled out EVEN ON FAILURE -- it should always
  398. // be deleted by the caller (using the delete operator) if non-NULL.
  399. //
  400. WBEMSTATUS
  401. mfn_StartUpdate(
  402. IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewState,
  403. IN LPCWSTR szClientDescription,
  404. OUT BOOL *pfDoAsync,
  405. OUT WCHAR ** ppLog
  406. );
  407. //
  408. // Increment ref count. Object stays alive as long as refcount is nonzero.
  409. //
  410. VOID
  411. mfn_Reference(
  412. VOID
  413. );
  414. //
  415. // Decrement ref count. Object is deleted when refcount goes to zero.
  416. //
  417. VOID
  418. mfn_Dereference(
  419. VOID
  420. );
  421. //
  422. // Release the machine-wide update event for this NIC, and delete any
  423. // temporary entries in the registry that were used for this update.
  424. // ppLog must be deleted by caller useing the delete operator.
  425. //
  426. VOID
  427. mfn_StopUpdate(
  428. OUT WCHAR ** ppLog
  429. );
  430. //
  431. // Looks up the completion record identified by Generation, for
  432. // specific NIC (identified by *this).
  433. //
  434. //
  435. BOOL
  436. mfn_LookupCompletion(
  437. IN UINT Generation,
  438. OUT PNLB_COMPLETION_RECORD *pCompletionRecord
  439. );
  440. //
  441. // Uses various windows APIs to fill up the current extended cluster
  442. // information for a specific nic (identified by *this).
  443. // It fills out pNewCfg.
  444. // The pNewCfg->field is set to TRUE IFF there were
  445. // no errors trying to fill out the information.
  446. //
  447. //
  448. WBEMSTATUS
  449. mfn_GetCurrentClusterConfiguration(
  450. OUT PNLB_EXTENDED_CLUSTER_CONFIGURATION pCfg
  451. );
  452. //
  453. // Analyzes the nature of the update, mainly to decide whether or not
  454. // we need to do the update asynchronously.
  455. // This also performs parameter validation.
  456. //
  457. WBEMSTATUS
  458. mfn_AnalyzeUpdate(
  459. IN PNLB_EXTENDED_CLUSTER_CONFIGURATION pNewCfg,
  460. IN BOOL *pDoAsync,
  461. IN CLocalLogger &logger
  462. );
  463. //
  464. // Does the update synchronously -- this is where the meat of the update
  465. // logic exists. It can range from a NoOp, through changing the
  466. // fields of a single port rule, through binding NLB, setting up cluster
  467. // parameters and adding the relevant IP addresses in TCPIP.
  468. //
  469. VOID
  470. mfn_ReallyDoUpdate(
  471. VOID
  472. );
  473. VOID
  474. mfn_Log(
  475. UINT Id, // Resource ID of format,
  476. ...
  477. );
  478. VOID
  479. mfn_LogRawText(
  480. LPCWSTR szText
  481. );
  482. //
  483. // Stop the current cluster and take out its vips.
  484. //
  485. VOID
  486. mfn_TakeOutVips(
  487. VOID
  488. );
  489. //
  490. // Acquires the first global mutex, call this first.
  491. //
  492. WBEMSTATUS
  493. mfn_AcquireFirstMutex(
  494. VOID
  495. );
  496. //
  497. // If (fCancel) it releases the first mutex mutex and clears up handles
  498. // to 2nd mutex and evt.
  499. // else it will wait until it receives signal that the 2nd mutex is
  500. // acquired, and then clears up only the 1st mutex handle.
  501. //
  502. WBEMSTATUS
  503. mfn_ReleaseFirstMutex(
  504. BOOL fCancel
  505. );
  506. //
  507. // Acquire the 2nd mutex (could be called from a different thread
  508. // than the one that called mfn_AcquireFirstMutex.
  509. // Also signals an internal event which mfn_ReleaseFirstMutex may
  510. // be waiting on.
  511. //
  512. WBEMSTATUS
  513. mfn_AcquireSecondMutex(
  514. VOID
  515. );
  516. //
  517. // Releases the second mutex.
  518. //
  519. WBEMSTATUS
  520. mfn_ReleaseSecondMutex(
  521. VOID
  522. );
  523. //
  524. // Writes an NT event when the update is stopping
  525. //
  526. VOID
  527. ReportStopEvent(
  528. const WORD wEventType,
  529. WCHAR **ppLog
  530. );
  531. //
  532. // Writes an NT event when the update is starting
  533. //
  534. VOID
  535. ReportStartEvent(
  536. LPCWSTR szClientDescription
  537. );
  538. };
  539. VOID
  540. test_port_rule_string(
  541. VOID
  542. );