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.

1781 lines
50 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. MPRINIT.CXX
  5. Abstract:
  6. Contains the DLL initialization routine for the Mutiple-Provider
  7. Router. The following are names of functions in this file:
  8. MprDllInit
  9. MprCheckProviders
  10. MprLevel1Init
  11. MprLevel2Init
  12. MprProcessDetach
  13. GetProviderCapabilities
  14. MprFreeGlobalProviderInfo
  15. MprMakeServiceKeyName
  16. MprGetOrderedList
  17. MprGetNumProviders
  18. MprExtractProviderInfo
  19. The router distinguishes between Providers and ActiveProviders. It
  20. maintains global information about GlobalNumProviders and
  21. GlobalNumActiveProviders. The two counts can be distinguished in the
  22. following ways:
  23. GlobalNumProviders - This determines the size of the provider database
  24. that mpr maintains. This count reflects the number of providers for
  25. which we were able to obtain registry information. A provider is
  26. added to the list if we are able to obtain its name and the
  27. name of its dll routine.
  28. GlobalNumActiveProviders - A provider becomes active when we are able
  29. to successfully load the dll, and obtain at least one entry point
  30. for it.
  31. Author:
  32. Dan Lafferty (danl) 6-Oct-1991
  33. Environment:
  34. User Mode - Win32
  35. Notes:
  36. Revision History:
  37. 05-May-1999 jschwart
  38. Make provider addition/removal dynamic
  39. 09-Aug-1996 AnirudhS
  40. Disabled thread library calls, since they cause extra paging and
  41. are 100% useless. Fixed memory leak of error records on DLL unload.
  42. 02-Mar-1995 AnirudhS
  43. Add test for WNNC_ENUM_CONTEXT capability.
  44. 09-Aug-1994 Danl
  45. Only do PROCESS_DETACH cleanup work if the PROCESS_DETACH occurs
  46. because of a FreeLibrary.
  47. 01-Mar-1994 Danl
  48. Created a seperate location for the Credential Managers GetCaps()
  49. function. This way if a provider has both a credential manager
  50. dll and a network dll, we will be able to direct calls to the
  51. correct GetCaps() function.
  52. 08-Apr-1993 Danl
  53. MprLevel1Init: Created a tempOrderedString which will be used
  54. for incrementing through the buffer. This way we can Free
  55. orderedString because it still points to the beginning of the buffer.
  56. 24-Nov-1992 Danl
  57. Modified many things to allow for initialization to occur on
  58. first call rather than at DLL initialization time. Also coded
  59. for the future possibility of Authentication Providers.
  60. 02-Nov-1992 Danl
  61. Allow MPR to continue operation even if there are no providers, or
  62. if the network is not installed and provider info is not available
  63. in the registry. Removed MprHack.
  64. 31-Aug-1992 Danl
  65. Removed use of the list of active providers. Now all providers
  66. in the Provider Order list are loaded at init time.
  67. 06-Oct-1991 Danl
  68. Created
  69. --*/
  70. //
  71. // Includes
  72. //
  73. #include "precomp.hxx"
  74. #include <debugfmt.h> // FORMAT_LPTSTR
  75. #include "mprres.h" // IDS_NETROOT
  76. #include "connify.h" // MprConnectNotifyInit()
  77. //
  78. // Local Function Prototypes
  79. //
  80. BOOL
  81. MprProcessAttach(
  82. HANDLE DllHandle
  83. );
  84. BOOL
  85. MprProcessDetach(
  86. DWORD dwInitLevel
  87. );
  88. BOOL
  89. GetProviderCapabilities(
  90. LPPROVIDER Provider
  91. );
  92. VOID
  93. MprFreeGlobalProviderInfo(VOID);
  94. BOOL
  95. MprGetOrderedList(
  96. HKEY ControlRootKey,
  97. LPTSTR *OrderString
  98. );
  99. DWORD
  100. MprMakeServiceKeyName(
  101. IN OUT LPTSTR *OrderedNamePtr,
  102. OUT LPTSTR *NameBufferPtr,
  103. OUT LPTSTR *NamePtr
  104. );
  105. DWORD
  106. MprGetNumProviders(
  107. LPTSTR OrderedString
  108. );
  109. BOOL
  110. MprExtractProviderInfo(
  111. HKEY ProviderInfoKey,
  112. LPPROVIDER Provider
  113. );
  114. BOOL
  115. MprInitializeProviderGlobals(
  116. VOID
  117. );
  118. BOOL
  119. MprGetLUIDDeviceMapsEnabled(
  120. PBOOL pResult
  121. );
  122. //
  123. // Constants
  124. //
  125. #define TEMP_SIZE 256
  126. //
  127. // Some registry path names
  128. //
  129. #define PROVIDER_KEY_NAME TEXT("control\\NetworkProvider\\active")
  130. #define PROVIDER_ORDER_KEY TEXT("control\\NetworkProvider\\HwOrder")
  131. #define SERVICES_KEY_NAME TEXT("services\\")
  132. #define SYSTEM_CONTROL_ROOT TEXT("system\\CurrentControlSet")
  133. #define PROVIDER_PATH TEXT("\\NetworkProvider")
  134. #define VALUE_PATHNAME TEXT("ProviderPath")
  135. #define AUTHENT_PATHNAME TEXT("AuthentProviderPath")
  136. #define VALUE_CLASS TEXT("Class")
  137. //
  138. // Defines for the DLL's init state
  139. //
  140. #define MPR_PROVIDERLOCK_CREATED 0x00000001
  141. #define MPR_INITCRITSEC_CREATED 0x00000002
  142. #define MPR_ERRORCRITSEC_CREATED 0x00000004
  143. #define MPR_CACHE_CONSTRUCTED 0x00000008
  144. //
  145. // Global Data Structures
  146. //
  147. LPPROVIDER GlobalProviderInfo=NULL; // A pointer to array of PROVIDER Structures
  148. DWORD GlobalNumProviders=0;
  149. DWORD GlobalNumActiveProviders=0;
  150. CRITICAL_SECTION MprInitCritSec;
  151. HMODULE hDLL;
  152. HANDLE g_hProvidersChanged; // Event set on provider addition/deletion
  153. HKEY g_hProviderKey; // Registry key of the provider list
  154. WCHAR g_wszEntireNetwork[40]; // "Entire Network" string for top-level enum
  155. BOOL g_LUIDDeviceMapsEnabled=FALSE; // LUID device map enabled/disabled
  156. //
  157. // GlobalInitLevel is a set of bit flags used to indicate how much
  158. // initialization work has been done.
  159. //
  160. volatile DWORD GlobalInitLevel = 0;
  161. DWORD MprDebugLevel;
  162. extern "C"
  163. BOOL
  164. MprDllInit(
  165. IN HINSTANCE DllHandle,
  166. IN DWORD Reason,
  167. IN PCONTEXT pContext OPTIONAL
  168. )
  169. /*++
  170. Routine Description:
  171. This routine reads the registry to determine what network providers are
  172. available. It then loads and initializes the Network Providers. After
  173. this, a call is made to each of the providers to get a list of
  174. Capabilities (via WNetGetCaps).
  175. Arguments:
  176. DllHandle - A handle for the DLL?
  177. Reason - The reason for which this routine is being called. This might
  178. be one of the following:
  179. DLL_PROCESS_ATTACH
  180. DLL_THREAD_ATTACH
  181. DLL_THREAD_DETACH
  182. DLL_PROCESS_DETACH
  183. pContext - Pointer to a context structure
  184. Return Value:
  185. Note:
  186. --*/
  187. {
  188. //
  189. // We need to keep track of how far initialization went since
  190. // we may get called with DLL_PROCESS_DETACH if init fails and
  191. // don't want to clean up uninitialized data
  192. //
  193. static DWORD s_dwInitLevel;
  194. NTSTATUS Status;
  195. if (Reason == DLL_PROCESS_ATTACH) {
  196. #if DBG == 1
  197. //
  198. // Read the debug message level from the registry
  199. //
  200. HKEY MprKey;
  201. if (MprOpenKey(HKEY_LOCAL_MACHINE,
  202. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Mpr",
  203. &MprKey,
  204. 0))
  205. {
  206. MprDebugLevel = (DWORD) MprGetKeyNumberValue(MprKey, L"DebugLevel", 0);
  207. RegCloseKey(MprKey);
  208. }
  209. #endif
  210. //
  211. // create semaphore used to protect global data (DLL handles and
  212. // function pointers.
  213. //
  214. if ((MprLoadLibSemaphore = CreateSemaphore( NULL,1,1,NULL )) == NULL)
  215. {
  216. MPR_LOG1(ERROR,
  217. "MprDllInit: CreateSemaphore FAILED %d\n",
  218. GetLastError());
  219. return FALSE ;
  220. }
  221. if (!MprInitializeProviderGlobals())
  222. {
  223. return FALSE;
  224. }
  225. s_dwInitLevel |= MPR_PROVIDERLOCK_CREATED;
  226. MPR_LOG2(PS,"Process %#lx (%ws) attached to the DLL\n",
  227. GetCurrentProcessId(), GetCommandLineW());
  228. //
  229. // Save the DLL handle, to be used in LoadString
  230. //
  231. hDLL = DllHandle;
  232. //
  233. // Create the critical section to synchronize access to global
  234. // data when doing init on first call.
  235. //
  236. Status = RtlInitializeCriticalSection(&MprInitCritSec);
  237. if (!NT_SUCCESS(Status))
  238. {
  239. return FALSE;
  240. }
  241. s_dwInitLevel |= MPR_INITCRITSEC_CREATED;
  242. //
  243. // Initialize critical section that protects the Linked list of
  244. // Error Records.
  245. //
  246. //
  247. Status = RtlInitializeCriticalSection(&MprErrorRecCritSec);
  248. if (!NT_SUCCESS(Status))
  249. {
  250. return FALSE;
  251. }
  252. s_dwInitLevel |= MPR_ERRORCRITSEC_CREATED;
  253. CRoutedOperation::ConstructCache();
  254. s_dwInitLevel |= MPR_CACHE_CONSTRUCTED;
  255. DisableThreadLibraryCalls(DllHandle);
  256. }
  257. else if (Reason == DLL_PROCESS_DETACH) {
  258. //
  259. // Only do cleanup if detach was due to a FreeLibrary() call.
  260. // In this case pContext will be NULL. Otherwise, this gets called
  261. // because the process is terminating. We will let the process
  262. // cleanup code clean up everything.
  263. //
  264. if (pContext == NULL) {
  265. //
  266. // close handle for semaphore
  267. //
  268. CloseHandle(MprLoadLibSemaphore) ;
  269. MprLoadLibSemaphore = NULL ;
  270. MPR_LOG(PS,"Process %#lx detached from the DLL\n",GetCurrentProcessId());
  271. MPR_LOG(TRACE,"******************* CLEAN-UP ********************\n",0);
  272. MprProcessDetach(s_dwInitLevel);
  273. if (s_dwInitLevel & MPR_CACHE_CONSTRUCTED)
  274. {
  275. CRoutedOperation::DestroyCache();
  276. }
  277. MPR_LOG(TRACE,"***************** CLEAN_UP END ******************\n",0);
  278. }
  279. }
  280. else if (Reason == DLL_THREAD_ATTACH) {
  281. // This should never happen
  282. MPR_LOG2(PS,"Thread %#lx.%#lx attached to the DLL\n",
  283. GetCurrentProcessId(), GetCurrentThreadId());
  284. }
  285. else if (Reason == DLL_THREAD_DETACH) {
  286. // This should never happen
  287. MPR_LOG2(PS,"Thread %#lx.%#lx detached from the DLL\n",
  288. GetCurrentProcessId(), GetCurrentThreadId());
  289. }
  290. return(TRUE);
  291. }
  292. BOOL
  293. MprInitializeProviderGlobals(
  294. VOID
  295. )
  296. {
  297. g_hProvidersChanged = CreateEvent(NULL, // Default security
  298. TRUE, // Manual reset
  299. FALSE, // Starts out unsignaled
  300. NULL); // No name
  301. if (g_hProvidersChanged == NULL)
  302. {
  303. MPR_LOG1(ERROR,
  304. "MprInitializeProviderGlobals: CreateEvent FAILED %d\n",
  305. GetLastError());
  306. return FALSE;
  307. }
  308. //
  309. // NOTE: Key handle must be global since RegNotifyChangeKeyValue
  310. // fires when the handle is closed (done in MprProcessDetach)
  311. //
  312. if (!MprOpenKey(HKEY_LOCAL_MACHINE,
  313. SYSTEM_CONTROL_ROOT L"\\" PROVIDER_ORDER_KEY,
  314. &g_hProviderKey,
  315. 0))
  316. {
  317. MPR_LOG1(ERROR,
  318. "MprInitializeProviderGlobals: MprOpenKey FAILED %d\n",
  319. GetLastError());
  320. CloseHandle(g_hProvidersChanged);
  321. return FALSE;
  322. }
  323. if (RegNotifyChangeKeyValue(g_hProviderKey, // Key
  324. FALSE, // Don't watch subtree
  325. REG_NOTIFY_CHANGE_LAST_SET, // Watch for value changes
  326. g_hProvidersChanged, // Event to signal
  327. TRUE) // Asynchronous
  328. != ERROR_SUCCESS)
  329. {
  330. //
  331. // If this call fails, we won't notice provider additions/deletions
  332. //
  333. MPR_LOG1(ERROR,
  334. "MprInitializeProviderGlobals: RegNotifyChangeKeyValue FAILED %d\n",
  335. GetLastError());
  336. }
  337. //
  338. // Check if LUID device maps are Enabled
  339. //
  340. MprGetLUIDDeviceMapsEnabled( &g_LUIDDeviceMapsEnabled );
  341. //
  342. // Create the lock that restricts access to the provider array
  343. //
  344. if (!MPRProviderLock.Initialize("P", "Provider"))
  345. {
  346. MPR_LOG0(ERROR,
  347. "MprInitializeProviderGlobals: MPRProviderLock.Initialize FAILED\n");
  348. RegCloseKey(g_hProviderKey);
  349. CloseHandle(g_hProvidersChanged);
  350. return FALSE;
  351. }
  352. return TRUE;
  353. }
  354. VOID
  355. MprCheckProviders(
  356. VOID
  357. )
  358. {
  359. ASSERT(!MPRProviderLock.Have());
  360. if (WaitForSingleObject(g_hProvidersChanged, 0) == WAIT_OBJECT_0)
  361. {
  362. //
  363. // The providers have changed -- grab the exclusive lock and
  364. // check again to avoid a race condition. Note that there
  365. // is no need to acquire the MprInitCritsec since an API must
  366. // always acquire the critsec (via INIT_IF_NECESSARY) AFTER it
  367. // acquires the shared provider lock.
  368. //
  369. CProviderExclusiveLock PLock;
  370. if (WaitForSingleObject(g_hProvidersChanged, 0) == WAIT_OBJECT_0)
  371. {
  372. //
  373. // Still set -- this is the first thread here. Free up the provider
  374. // info and reset the init level so the next INIT_IF_NECESSARY call
  375. // will reinitialize the providers as necessary.
  376. //
  377. MPR_LOG0(TRACE,
  378. "MprCheckProviders: Provider list changed -- reinitializing\n");
  379. MprDeleteIndexArray();
  380. MprFreeGlobalProviderInfo();
  381. GlobalInitLevel = 0;
  382. //
  383. // Flush the provider cache
  384. //
  385. CRoutedOperation::DestroyCache();
  386. CRoutedOperation::ConstructCache();
  387. ResetEvent(g_hProvidersChanged);
  388. if (RegNotifyChangeKeyValue(g_hProviderKey, // Key
  389. FALSE, // Don't watch subtree
  390. REG_NOTIFY_CHANGE_LAST_SET, // Watch for value changes
  391. g_hProvidersChanged, // Event to signal
  392. TRUE) // Asynchronous
  393. != ERROR_SUCCESS)
  394. {
  395. //
  396. // If this call fails we won't notice provider additions/deletions
  397. //
  398. MPR_LOG1(ERROR,
  399. "MprCheckProviders: RegNotifyChangeKeyValue FAILED %d\n",
  400. GetLastError());
  401. }
  402. }
  403. }
  404. }
  405. DWORD
  406. MprLevel1Init(
  407. VOID
  408. )
  409. /*++
  410. Routine Description:
  411. This function looks into the registry to find the names of the providers
  412. and their associated DLLs. A Global table of provider information is
  413. then allocated (GlobalProviderInfo). This table is an array of provider
  414. information structures. The number of elements in the array is stored
  415. in GlobalNumProviders.
  416. If the provider is in the registry ORDERED list, then it is assumed that
  417. complete provider information is stored in the "services" section of
  418. the registry for that provider. This provider information includes such
  419. things as the pathname for the provider dll, and the provider type.
  420. The information is stored in the provider structure for use by the
  421. MprLevel2Init routine.
  422. Arguments:
  423. Return Value:
  424. Note:
  425. --*/
  426. {
  427. DWORD status;
  428. LPPROVIDER provider;
  429. DWORD i;
  430. HKEY controlRootKey;
  431. HKEY providerInfoKey;
  432. LPTSTR orderedString = NULL;
  433. LPTSTR tempOrderedString;
  434. LPTSTR nameBuffer = NULL; // system\LanmanRedirector\NetworkProvider
  435. LPTSTR providerIdString = NULL; // points to provider id in nameBuffer
  436. BOOL oneInitialized = FALSE;
  437. EnterCriticalSection(&MprInitCritSec);
  438. MPR_LOG(TRACE,"******************* LEVEL 1 INIT ********************\n",0);
  439. //
  440. // If this level of initialization is already complete, then return.
  441. //
  442. if (GlobalInitLevel & FIRST_LEVEL) {
  443. LeaveCriticalSection(&MprInitCritSec);
  444. return(WN_SUCCESS);
  445. }
  446. //
  447. // This function had better be called first and only once
  448. //
  449. ASSERT(GlobalInitLevel == 0);
  450. //
  451. // Get a handle to the "current" services part of the registry
  452. //
  453. if(!MprOpenKey(
  454. HKEY_LOCAL_MACHINE, // hKey
  455. SYSTEM_CONTROL_ROOT, // lpSubKey
  456. &controlRootKey, // Newly Opened Key Handle
  457. DA_READ)) { // Desired Access
  458. MPR_LOG(ERROR,"MprLevel1Init: MprOpenKey (System) Error\n",0);
  459. LeaveCriticalSection(&MprInitCritSec);
  460. return(WN_NO_NETWORK);
  461. }
  462. MPR_LOG2(TRACE,"OpenKey %ws,0x%lx\n ",SYSTEM_CONTROL_ROOT,controlRootKey);
  463. //
  464. // Obtain the ordered list information.
  465. // (the orderedString buffer is allocated here)
  466. //
  467. // If this fails, we assume that there are no providers.
  468. //
  469. if (!MprGetOrderedList(controlRootKey, &orderedString)) {
  470. MPR_LOG(ERROR,"Could not get the ordered list of providers\n",0);
  471. RegCloseKey(controlRootKey);
  472. LeaveCriticalSection(&MprInitCritSec);
  473. return(WN_NO_NETWORK);
  474. }
  475. MPR_LOG1(TRACE,"ProviderOrderString = %ws\n",orderedString);
  476. GlobalNumProviders = MprGetNumProviders(orderedString);
  477. //
  478. // Allocate the database in which to store Provider Information.
  479. // This is to be an array of PROVIDER structures. Memory is set
  480. // to zero so that all the provider entry points will be initialized to
  481. // zero.
  482. //
  483. GlobalProviderInfo = (LPPROVIDER) LocalAlloc(
  484. LPTR,
  485. sizeof(PROVIDER) * GlobalNumProviders);
  486. if (GlobalProviderInfo == NULL) {
  487. status = GetLastError();
  488. MPR_LOG(ERROR,"MprLevel1Init: provider array LocalAlloc Failed %d\n",
  489. status);
  490. LocalFree(orderedString);
  491. GlobalNumProviders = 0;
  492. RegCloseKey(controlRootKey);
  493. LeaveCriticalSection(&MprInitCritSec);
  494. return(status);
  495. }
  496. provider = GlobalProviderInfo;
  497. tempOrderedString = orderedString;
  498. for(i=0; i<GlobalNumProviders; i++,provider++) {
  499. //
  500. // Build the Service key name for the next Service/Driver.
  501. // NOTE: This function allocates a nameBuffer.
  502. //
  503. status = MprMakeServiceKeyName(
  504. &tempOrderedString,
  505. &nameBuffer,
  506. &providerIdString );
  507. if (status != WN_SUCCESS) {
  508. goto SkipProvider;
  509. }
  510. //
  511. // Create the path name to the provider information in the
  512. // service's tree.
  513. //
  514. wcscat(nameBuffer, PROVIDER_PATH);
  515. //
  516. // Open the provider portion of that service/driver's
  517. // node in the service tree.
  518. //
  519. if (!MprOpenKey( controlRootKey, nameBuffer, &providerInfoKey, DA_READ)){
  520. LocalFree(nameBuffer);
  521. goto SkipProvider;
  522. }
  523. MPR_LOG1(TRACE,"\n\t----%ws----\n",providerIdString);
  524. MPR_LOG3(TRACE,"\tOpenKey %ws,\n\t%ws\n,\t0x%lx\n",
  525. SYSTEM_CONTROL_ROOT,
  526. nameBuffer,
  527. providerInfoKey);
  528. //
  529. // Free the memory that was allocated for the name buffer.
  530. //
  531. LocalFree (nameBuffer);
  532. //
  533. // Get the data for the provider from the registry at the
  534. // location referenced by providerInfoKey.
  535. //
  536. if (!MprExtractProviderInfo(providerInfoKey, provider)) {
  537. MPR_LOG(TRACE,"CloseKey 0x%lx\n", providerInfoKey);
  538. RegCloseKey(providerInfoKey);
  539. goto SkipProvider;
  540. }
  541. //
  542. // Close the ProviderInfoKey.
  543. //
  544. MPR_LOG(TRACE,"CloseKey 0x%lx\n", providerInfoKey);
  545. RegCloseKey(providerInfoKey);
  546. //
  547. // We have information for at least one provider.
  548. //
  549. oneInitialized = TRUE;
  550. SkipProvider:
  551. ; // The complier needs to find something to go to.
  552. } // End For NumProviders
  553. MPR_LOG(TRACE,"CloseKey 0x%lx\n", controlRootKey);
  554. RegCloseKey(controlRootKey);
  555. if (orderedString != NULL) {
  556. LocalFree(orderedString);
  557. }
  558. GlobalInitLevel = FIRST_LEVEL;
  559. LeaveCriticalSection(&MprInitCritSec);
  560. if (oneInitialized == FALSE) {
  561. return(WN_NO_NETWORK);
  562. }
  563. return(WN_SUCCESS);
  564. }
  565. DWORD
  566. MprLevel2Init(
  567. DWORD InitLevel
  568. )
  569. /*++
  570. Routine Description:
  571. This routine initializes all providers of the class described by
  572. the InitLevel parameter. We loop though all providers that meet
  573. this description, and load the dll and find the dll's function entry
  574. points. If we were successful in getting this information for the
  575. provider, it will be added to our "active" list by having its provider
  576. index placed in the GlobalIndexArray (via MprInitIndexArray).
  577. NOTE:
  578. This routine can potentially be called once for each type of
  579. initialization that is supported. For instance, it may be called for
  580. authentication initialization, and then called later for network
  581. initialization.
  582. Each time this routine is called, a new indexArray is created.
  583. After this array is filled in, it is merged with any existing
  584. indexArray left over from previous calls. The merge is performed
  585. by MprInitIndexArray. Locks on this array must be held in order to
  586. update it.
  587. Arguments:
  588. InitLevel - This indicates the level of initialization. This can be
  589. a NETWORK_LEVEL or CREDENTIAL_LEVEL initialization, or both.
  590. Return Value:
  591. WN_SUCCESS - This is returned if we are able to obtain some entry point
  592. information for at least one provider.
  593. Otherwise, an appropriate error is returned.
  594. --*/
  595. {
  596. DWORD status = WN_SUCCESS;
  597. LPPROVIDER provider;
  598. DWORD i;
  599. LPDWORD indexArray = NULL;
  600. DWORD numActive = 0;
  601. DWORD InitClass = 0;
  602. //
  603. // Before we can do a level2 initialization, we must first check to
  604. // see if level 1 has been completed.
  605. //
  606. if (!(GlobalInitLevel & FIRST_LEVEL)) {
  607. status = MprLevel1Init();
  608. if (status != WN_SUCCESS) {
  609. return(status);
  610. }
  611. }
  612. EnterCriticalSection(&MprInitCritSec);
  613. MPR_LOG(TRACE,"******************* LEVEL 2 INIT ********************\n",0);
  614. //
  615. // If this level of initialization is already complete, then return.
  616. //
  617. if (GlobalInitLevel & InitLevel) {
  618. LeaveCriticalSection(&MprInitCritSec);
  619. return(WN_SUCCESS);
  620. }
  621. //
  622. // Translate InitLevel into an InitClass so it can be compared with the
  623. // provider class.
  624. //
  625. if (InitLevel & NETWORK_LEVEL)
  626. {
  627. InitClass |= NETWORK_TYPE;
  628. //
  629. // Load the "Entire Network" string (used by WNetEnumResource
  630. // for RESOURCE_CONNECTED). Note that WNetEnumResource requires
  631. // only NETWORK_LEVEL initialization, so it's OK to load it
  632. // here and only here.
  633. //
  634. if (g_wszEntireNetwork[0] == L'\0')
  635. {
  636. int cch = LoadString(hDLL,
  637. IDS_NETROOT,
  638. g_wszEntireNetwork,
  639. LENGTH(g_wszEntireNetwork));
  640. ASSERT(cch > 0 && cch < LENGTH(g_wszEntireNetwork));
  641. }
  642. }
  643. if (InitLevel & CREDENTIAL_LEVEL)
  644. {
  645. InitClass |= CREDENTIAL_TYPE;
  646. }
  647. if (InitLevel & NOTIFIEE_LEVEL)
  648. {
  649. status = MprConnectNotifyInit();
  650. GlobalInitLevel |= InitLevel;
  651. LeaveCriticalSection(&MprInitCritSec);
  652. return(status);
  653. }
  654. provider = GlobalProviderInfo;
  655. //
  656. // Allocate storage for the ordered list of indices. This storage is
  657. // freed by MprInitIndexArray.
  658. //
  659. indexArray = (LPDWORD) LocalAlloc(LPTR, sizeof(DWORD) * GlobalNumProviders);
  660. if (indexArray == NULL) {
  661. MPR_LOG(ERROR,"MprProcessAttach: indexArray LocalAlloc Failed %d\n",
  662. GetLastError());
  663. LeaveCriticalSection(&MprInitCritSec);
  664. return(GetLastError());
  665. }
  666. for(i=0; i<GlobalNumProviders; i++,provider++) {
  667. //
  668. // If this provider matches the init type for which we are
  669. // initializing, then load the library and get the entry points.
  670. // Then add the provider array index to the index array.
  671. //
  672. if (provider->InitClass & InitClass) {
  673. //
  674. // Load the DLL and free the memory for its name.
  675. //
  676. if (provider->AuthentDllName != NULL) {
  677. MPR_LOG1(TRACE,"MprLevel2Init: Loading %ws\n",provider->AuthentDllName);
  678. provider->AuthentHandle = LoadLibraryEx(
  679. provider->AuthentDllName,
  680. NULL,
  681. LOAD_WITH_ALTERED_SEARCH_PATH);
  682. if (provider->AuthentHandle == NULL) {
  683. MPR_LOG(ERROR,"MprLevel2Init: LoadLibraryEx Failed %d\n",
  684. GetLastError());
  685. }
  686. LocalFree(provider->AuthentDllName);
  687. provider->AuthentDllName = NULL;
  688. }
  689. if (provider->DllName != NULL) {
  690. MPR_LOG1(TRACE,"MprLevel2Init: Loading %ws\n",provider->DllName);
  691. provider->Handle = LoadLibraryEx(
  692. provider->DllName,
  693. NULL,
  694. LOAD_WITH_ALTERED_SEARCH_PATH);
  695. if (provider->Handle == NULL) {
  696. MPR_LOG(ERROR,"MprLevel2Init: LoadLibraryEx Failed %d\n",
  697. GetLastError());
  698. }
  699. //
  700. // Keep around the DLL name since we need to do another
  701. // LoadLibraryEx to refcount the DLL in WNetOpenEnum
  702. //
  703. }
  704. if ((provider->Handle != NULL) || (provider->AuthentHandle != NULL)) {
  705. MPR_LOG0(TRACE,"MprLevel2Init: LoadLibraryEx success\n");
  706. //
  707. // Obtain the various entry points for the library.
  708. // This is done based on the capabilities that are listed for the
  709. // provider.
  710. //
  711. if (GetProviderCapabilities(provider)) {
  712. //
  713. // Only providers for which we are able to successfully
  714. // get the entry points are added to the active array.
  715. //
  716. // Since this provider information is now initialized, the
  717. // provider is considered ACTIVE. Put the index to the
  718. // provider in the index array.
  719. //
  720. MPR_LOG1(TRACE,"MprLevel2Init: Successfully got "
  721. "capabilities for %ws\n",provider->Resource.lpProvider);
  722. indexArray[numActive] = i;
  723. numActive++;
  724. }
  725. }
  726. } // End If InitLevel match
  727. } // End For NumProviders
  728. //
  729. // Store the information in this indexArray in the GlobalIndexArray.
  730. //
  731. MprInitIndexArray(indexArray, numActive);
  732. GlobalInitLevel |= InitLevel;
  733. LeaveCriticalSection(&MprInitCritSec);
  734. MPR_LOG(TRACE,"******************* END LEVEL 2 INIT ********************\n",0);
  735. return(WN_SUCCESS);
  736. }
  737. BOOL
  738. MprProcessDetach(
  739. DWORD dwInitLevel
  740. )
  741. /*++
  742. Routine Description:
  743. This function cleans up resources for a process when it detaches
  744. from the dll.
  745. Arguments:
  746. none
  747. Return Value:
  748. none
  749. Note:
  750. --*/
  751. {
  752. MprDeleteIndexArray();
  753. MprFreeGlobalProviderInfo();
  754. GlobalNumProviders = 0;
  755. GlobalProviderInfo = NULL;
  756. if (dwInitLevel & MPR_INITCRITSEC_CREATED)
  757. {
  758. DeleteCriticalSection(&MprInitCritSec);
  759. }
  760. if (dwInitLevel & MPR_PROVIDERLOCK_CREATED)
  761. {
  762. RegCloseKey(g_hProviderKey);
  763. CloseHandle(g_hProvidersChanged);
  764. MPRProviderLock.Delete();
  765. }
  766. if (dwInitLevel & MPR_ERRORCRITSEC_CREATED)
  767. {
  768. MprFreeAllErrorRecords();
  769. DeleteCriticalSection(&MprErrorRecCritSec);
  770. }
  771. return(TRUE);
  772. }
  773. BOOL
  774. GetProviderCapabilities(
  775. LPPROVIDER Provider
  776. )
  777. /*++
  778. Routine Description:
  779. This function obtains the provider's capabilities and then gets the
  780. procedure entry point for all supported API.
  781. Arguments:
  782. Provider - A pointer to a PROVIDER structure which will contain all
  783. information that must be maintained for a given provider.
  784. Return Value:
  785. TRUE - If at least one capability is found for this provider.
  786. FALSE - If no capabilities are found for the provider.
  787. History:
  788. Johnl 17-Jan-1992 Added Property dialog support
  789. --*/
  790. //
  791. // The following macro is designed to work within the function
  792. // GetProviderCapabilities().
  793. //
  794. #define GET_ADDRESS(apiName) Provider-> ## apiName = (PF_NP ## apiName) GetProcAddress( \
  795. Provider->Handle, \
  796. "NP"#apiName); \
  797. if (Provider-> ## apiName == NULL) { \
  798. MPR_LOG(ERROR, \
  799. "GetProviderCapabilities: Can't get NP"#apiName " Address %d\n",\
  800. GetLastError()); \
  801. } \
  802. else { \
  803. status = TRUE; \
  804. }
  805. #define GET_AUTH_ADDRESS(apiName) Provider-> ## apiName = (PF_NP ## apiName) GetProcAddress( \
  806. Provider->AuthentHandle, \
  807. "NP"#apiName); \
  808. if (Provider-> ## apiName == NULL) { \
  809. MPR_LOG(ERROR, \
  810. "GetProviderCapabilities: Can't get NP"#apiName " Address %d\n",\
  811. GetLastError()); \
  812. } \
  813. else { \
  814. status = TRUE; \
  815. }
  816. {
  817. DWORD bitMask;
  818. BOOLEAN status=FALSE;
  819. GET_ADDRESS(GetCaps);
  820. if (status) {
  821. //
  822. // Get the Network Type
  823. //
  824. // CODEWORK: Read the type from the registry when possible -- this
  825. // will allow us to avoid doing a Level 2 init in all the cases where
  826. // only the provider type is needed (e.g., MprFindProviderByType).
  827. //
  828. Provider->Type = Provider->GetCaps(WNNC_NET_TYPE);
  829. //
  830. // Reject providers that don't supply their type
  831. //
  832. if (Provider->Type == 0)
  833. {
  834. MPR_LOG(ERROR, "%ws provider reported a net type of 0\n",
  835. Provider->Resource.lpProvider);
  836. ASSERT(!"Network provider didn't report its network type");
  837. return FALSE;
  838. }
  839. //
  840. // Does it support WNetGetUser?
  841. //
  842. bitMask = Provider->GetCaps(WNNC_USER);
  843. if (bitMask & WNNC_USR_GETUSER) {
  844. GET_ADDRESS(GetUser);
  845. }
  846. //
  847. // Connection Api Supported
  848. //
  849. bitMask = Provider->GetCaps(WNNC_CONNECTION);
  850. Provider->ConnectCaps = bitMask;
  851. if (bitMask & WNNC_CON_ADDCONNECTION) {
  852. GET_ADDRESS(AddConnection);
  853. }
  854. if (bitMask & WNNC_CON_ADDCONNECTION3) {
  855. DWORD bitMask2;
  856. GET_ADDRESS(AddConnection3);
  857. GET_ADDRESS(GetReconnectFlags); // optional entry point
  858. //
  859. // Connection Api flags Supported
  860. //
  861. bitMask2 = Provider->GetCaps(WNNC_CONNECTION_FLAGS);
  862. if (bitMask2 == 0) {
  863. bitMask2 = WNNC_CF_DEFAULT;
  864. }
  865. bitMask2 &= WNNC_CF_MAXIMUM;
  866. Provider->ConnectFlagCaps = bitMask2;
  867. }
  868. if (bitMask & WNNC_CON_CANCELCONNECTION) {
  869. GET_ADDRESS(CancelConnection);
  870. }
  871. if (bitMask & WNNC_CON_GETCONNECTIONS) {
  872. GET_ADDRESS(GetConnection);
  873. GET_ADDRESS(GetConnection3);
  874. GET_ADDRESS(GetUniversalName);
  875. }
  876. if (bitMask & WNNC_CON_GETPERFORMANCE) {
  877. GET_ADDRESS(GetConnectionPerformance);
  878. }
  879. //
  880. // Enumeration Api Supported
  881. //
  882. bitMask = Provider->GetCaps(WNNC_ENUMERATION);
  883. if ((bitMask & WNNC_ENUM_GLOBAL) ||
  884. (bitMask & WNNC_ENUM_LOCAL) ||
  885. (bitMask & WNNC_ENUM_CONTEXT)) {
  886. GET_ADDRESS(OpenEnum);
  887. GET_ADDRESS(EnumResource);
  888. GET_ADDRESS(CloseEnum);
  889. }
  890. //
  891. // Admin Api Supported
  892. //
  893. bitMask = Provider->GetCaps(WNNC_ADMIN);
  894. if (bitMask & WNNC_ADM_GETDIRECTORYTYPE) {
  895. GET_ADDRESS(GetDirectoryType);
  896. }
  897. if (bitMask & WNNC_ADM_DIRECTORYNOTIFY) {
  898. GET_ADDRESS(DirectoryNotify);
  899. }
  900. //
  901. // Dialog API Support
  902. //
  903. bitMask = Provider->GetCaps(WNNC_DIALOG);
  904. if (bitMask & WNNC_DLG_PROPERTYDIALOG) {
  905. GET_ADDRESS(GetPropertyText);
  906. GET_ADDRESS(PropertyDialog);
  907. }
  908. if (bitMask & WNNC_DLG_SEARCHDIALOG) {
  909. GET_ADDRESS(SearchDialog);
  910. }
  911. if (bitMask & WNNC_DLG_FORMATNETWORKNAME) {
  912. GET_ADDRESS(FormatNetworkName);
  913. }
  914. if (bitMask & WNNC_DLG_PERMISSIONEDITOR) {
  915. GET_ADDRESS(FMXGetPermCaps);
  916. GET_ADDRESS(FMXEditPerm);
  917. GET_ADDRESS(FMXGetPermHelp);
  918. }
  919. if (bitMask & WNNC_DLG_GETRESOURCEPARENT) {
  920. GET_ADDRESS(GetResourceParent);
  921. }
  922. if (bitMask & WNNC_DLG_GETRESOURCEINFORMATION) {
  923. GET_ADDRESS(GetResourceInformation);
  924. }
  925. }
  926. else {
  927. if (Provider->GetAuthentCaps == NULL) {
  928. Provider->GetAuthentCaps = (PF_NPGetCaps)GetProcAddress(
  929. Provider->AuthentHandle,
  930. "NPGetCaps");
  931. if (Provider->GetAuthentCaps == NULL) {
  932. MPR_LOG(ERROR,
  933. "GetProviderCapabilities: Can't get NPGetCaps %d\n",
  934. GetLastError());
  935. }
  936. else {
  937. status = TRUE;
  938. }
  939. }
  940. //
  941. // If we couldn't get an address for GetCaps from either the
  942. // network provider dll or the authentication provider dll, then
  943. // we should return an error. The rule is, this must be supported
  944. // by one of the providers.
  945. //
  946. if (status == FALSE) {
  947. return(FALSE);
  948. }
  949. }
  950. //
  951. // Get Authentication Provider entry points
  952. //
  953. if (Provider->InitClass & CREDENTIAL_TYPE) {
  954. if (Provider->AuthentHandle == NULL) {
  955. MPR_LOG0(TRACE,"GetProvCaps: CM provider in same DLL\n");
  956. GET_ADDRESS(LogonNotify);
  957. GET_ADDRESS(PasswordChangeNotify);
  958. }
  959. else {
  960. MPR_LOG0(TRACE,"GetProvCaps: CM provider in seperate DLL\n");
  961. GET_AUTH_ADDRESS(LogonNotify);
  962. GET_AUTH_ADDRESS(PasswordChangeNotify);
  963. if (Provider->GetAuthentCaps == NULL) {
  964. Provider->GetAuthentCaps = (PF_NPGetCaps)GetProcAddress(
  965. Provider->AuthentHandle,
  966. "NPGetCaps");
  967. if (Provider->GetAuthentCaps == NULL) {
  968. MPR_LOG(ERROR,
  969. "GetProviderCapabilities: Can't get NPGetCaps %d\n",
  970. GetLastError());
  971. }
  972. else {
  973. status = TRUE;
  974. }
  975. }
  976. }
  977. }
  978. return(status);
  979. }
  980. VOID
  981. MprFreeGlobalProviderInfo(
  982. VOID
  983. )
  984. /*++
  985. Routine Description:
  986. This function walks through the array of provider structures, and
  987. frees up all the valid pointers to the provider name. Then if frees
  988. the GlobalProviderInfo array.
  989. Arguments:
  990. none.
  991. Return Value:
  992. none.
  993. --*/
  994. {
  995. LPPROVIDER provider;
  996. DWORD i;
  997. if (GlobalProviderInfo == NULL)
  998. {
  999. return;
  1000. }
  1001. provider = GlobalProviderInfo;
  1002. //
  1003. // Free all the valid pointers to the provider's name.
  1004. //
  1005. for(i = 0; i < GlobalNumProviders; i++, provider++)
  1006. {
  1007. MPR_LOG(TRACE, "Freeing Name for provider %d\n",i);
  1008. if (provider->Handle != NULL)
  1009. {
  1010. MPR_LOG1(TRACE,
  1011. "Freeing Library for "FORMAT_LPTSTR" \n",
  1012. provider->Resource.lpProvider);
  1013. FreeLibrary(provider->Handle);
  1014. }
  1015. LocalFree(provider->DllName);
  1016. if (provider->AuthentHandle != NULL)
  1017. {
  1018. MPR_LOG1(TRACE,
  1019. "Freeing authentication library for "FORMAT_LPTSTR" \n",
  1020. provider->Resource.lpProvider);
  1021. FreeLibrary(provider->AuthentHandle);
  1022. }
  1023. //
  1024. // Should have been freed when the DLL was loaded
  1025. //
  1026. ASSERT(provider->AuthentDllName == NULL);
  1027. LocalFree(provider->Resource.lpRemoteName);
  1028. }
  1029. //
  1030. // Free the top level data structure and reinit the globals
  1031. //
  1032. MPR_LOG(TRACE, "Freeing GlobalProviderInfo\n",0);
  1033. LocalFree(GlobalProviderInfo);
  1034. GlobalProviderInfo = NULL;
  1035. GlobalNumProviders = 0;
  1036. GlobalNumActiveProviders = 0;
  1037. }
  1038. DWORD
  1039. MprMakeServiceKeyName(
  1040. IN OUT LPTSTR *OrderedNamePtr,
  1041. OUT LPTSTR *NameBufferPtr,
  1042. OUT LPTSTR *NamePtr
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. This function gets the name of the provider device driver key within
  1047. the registry tree. A buffer is allocated that is large enough for
  1048. that name as well as the name of the key where the provider information
  1049. is stored.
  1050. For example, the following buffer is allocated and filled with
  1051. only the path prefix followed by the LanmanRedirector name.
  1052. NameBuffer = [services\LanmanRedirector ]
  1053. The buffer is sized so that it can be filled in later with the
  1054. following information.
  1055. NameBuffer = [services\LanmanRedirector\NetworkProvider]
  1056. The Driver name is needed for comparison with the ordered list names.
  1057. Arguments:
  1058. OrderedNamePtr - On entry this points to a location where there is a
  1059. pointer to the the next name in the ordered list of providers.
  1060. These names are seperated by commas. The last entry is followed by
  1061. a trailing NUL.
  1062. On exit a pointer to the next name in the list is stored here. If
  1063. it is the last name, the pointer is NULL.
  1064. NameBufferPtr - This is a pointer to a location where the pointer to the
  1065. name buffer is to be placed.
  1066. NamePtr - This is a a location where the pointer to the provider
  1067. name is placed. In the above example, this pointer would point
  1068. to the beginnning of the LanmanRedirector portion of the string.
  1069. Return Value:
  1070. TRUE - We successfully obtained the driver name.
  1071. FALSE - We were unsuccessful in obtaining the driver name.
  1072. Note:
  1073. --*/
  1074. {
  1075. LPTSTR pNext;
  1076. DWORD bufferSize; // number of BYTES in buffer
  1077. DWORD nameLength; // number of CHARACTERS in string
  1078. //
  1079. // The OrderedNamePtr should always be valid. If not there is a software
  1080. // error in this code.
  1081. //
  1082. if (*OrderedNamePtr == NULL) {
  1083. MPR_LOG(ERROR,"GetDriverName: The ordered Name Ptr was NULL.\n",0);
  1084. return(WN_NO_NETWORK);
  1085. }
  1086. pNext = *OrderedNamePtr;
  1087. //
  1088. // Find the next NULL or COMMA.
  1089. //
  1090. while ( (*pNext != TEXT('\0')) &&
  1091. (*pNext != TEXT(',')) ){
  1092. pNext++;
  1093. }
  1094. //
  1095. // Allocate a buffer for the name to be stored in
  1096. //
  1097. bufferSize = (DWORD)((LPBYTE)pNext - (LPBYTE)(*OrderedNamePtr));
  1098. nameLength = bufferSize / sizeof(TCHAR);
  1099. bufferSize = bufferSize + sizeof(PROVIDER_PATH) + sizeof(SERVICES_KEY_NAME);
  1100. *NameBufferPtr = (LPTSTR) LocalAlloc(LPTR, bufferSize);
  1101. if (*NameBufferPtr == NULL) {
  1102. MPR_LOG(ERROR,"MprMakeServiceKeyName:LocalAllocFailed %d\n",GetLastError());
  1103. return(GetLastError());
  1104. }
  1105. //
  1106. // Copy the path prefix "services\\" followed by the name
  1107. // into the buffer and terminate with a NULL character.
  1108. //
  1109. wcscpy(*NameBufferPtr, SERVICES_KEY_NAME);
  1110. *NamePtr = (LPTSTR)(*NameBufferPtr + (wcslen(*NameBufferPtr)));
  1111. wcsncat(*NameBufferPtr, *OrderedNamePtr, nameLength);
  1112. *((*NamePtr) + nameLength) = TEXT('\0');
  1113. if (*pNext == TEXT('\0')) {
  1114. *OrderedNamePtr = NULL;
  1115. }
  1116. else {
  1117. *OrderedNamePtr = pNext + 1;
  1118. }
  1119. return (WN_SUCCESS);
  1120. }
  1121. BOOL
  1122. MprGetOrderedList(
  1123. HKEY ControlRootKey,
  1124. LPTSTR *OrderString
  1125. )
  1126. /*++
  1127. Routine Description:
  1128. This function returns a pointer to a string that contains the
  1129. ordered list of providers. This ordered list is to be used when
  1130. we go through the list of providers with a trial-and-error method
  1131. when servicing a WINNET API call.
  1132. ALLOCATES STORAGE: This function allocates the buffer for the
  1133. OrderString.
  1134. Arguments:
  1135. OrderString - This is a pointer to a location where the pointer to
  1136. the order string is to be placed.
  1137. Return Value:
  1138. TRUE - The ordered list was found, and the string was returned.
  1139. FALSE - A failure occured when attempting to find the ordered list.
  1140. --*/
  1141. {
  1142. HKEY orderKey;
  1143. *OrderString = NULL;
  1144. //
  1145. // Get a handle to the key for the ordered provider information.
  1146. //
  1147. if(!MprOpenKey(
  1148. ControlRootKey, // hKey
  1149. PROVIDER_ORDER_KEY, // lpSubKey
  1150. &orderKey, // Newly Opened Key Handle
  1151. DA_READ)) { // Desired Access
  1152. MPR_LOG(ERROR,"MprGetOrderedList: MprOpenKey (ActiveProviders) Error\n",0);
  1153. return(FALSE);
  1154. }
  1155. //
  1156. // Get the provider order string from the registry.
  1157. //
  1158. if (!MprGetKeyValue(orderKey, TEXT("ProviderOrder"), OrderString)) {
  1159. MPR_LOG(ERROR,"MprGetOrderedList: MprGetKeyValue Error.\n", 0);
  1160. RegCloseKey(orderKey);
  1161. return(FALSE);
  1162. }
  1163. RegCloseKey(orderKey);
  1164. return(TRUE);
  1165. }
  1166. DWORD
  1167. MprGetNumProviders(
  1168. LPTSTR OrderedString
  1169. )
  1170. /*++
  1171. Routine Description:
  1172. This routine finds the number of provider names in the string of
  1173. ordered provider names.
  1174. Arguments:
  1175. OrderedString - This is a pointer to a NUL terminated string of
  1176. ordered provider names. Names are seperated by commas.
  1177. Return Value:
  1178. --*/
  1179. {
  1180. DWORD count = 0;
  1181. LPTSTR pBegin;
  1182. pBegin = OrderedString;
  1183. while (*OrderedString != TEXT('\0')) {
  1184. //
  1185. // If a seperator has been found, and if there are characters
  1186. // between it and the last seperator (or the beginning), then
  1187. // increment the count.
  1188. //
  1189. if (*OrderedString == TEXT(',')) {
  1190. if((OrderedString - pBegin) > 0) {
  1191. count++;
  1192. }
  1193. pBegin = OrderedString + 1;
  1194. }
  1195. OrderedString++;
  1196. }
  1197. //
  1198. // The last name is expected to be followed by a NUL rather than a
  1199. // comma.
  1200. //
  1201. if ((OrderedString - pBegin) > 0) {
  1202. count++;
  1203. }
  1204. return(count);
  1205. }
  1206. BOOL
  1207. MprExtractProviderInfo(
  1208. HKEY ProviderInfoKey,
  1209. LPPROVIDER Provider
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. This function extracts information from the ProviderInfoKey location
  1214. in the registry and stores it in the Provider data structure.
  1215. Arguments:
  1216. ProviderInfoKey - This is a registry key handle for the location in
  1217. the registry where we expect to obtain all the necessary
  1218. information about a provider.
  1219. Provider - This is a pointer to a provider structure that is to be
  1220. filled in with the information from the registry.
  1221. Return Value:
  1222. TRUE - The operation was completely successful.
  1223. FALSE - The operation failed.
  1224. Note:
  1225. --*/
  1226. {
  1227. LPTSTR providerName = NULL;
  1228. LPTSTR fileName = NULL;
  1229. DWORD ValueType;
  1230. DWORD Class;
  1231. DWORD classSize = sizeof(DWORD);
  1232. DWORD status;
  1233. MPR_LOG(TRACE,"In MprExtractProviderInfo....\n",0);
  1234. //
  1235. // Get Provider Name
  1236. //
  1237. if(!MprGetKeyValue(ProviderInfoKey, TEXT("name"), &providerName) ||
  1238. providerName[0] == L'\0') {
  1239. MPR_LOG0(ERROR,"MprExtractProviderInfo: Couldn't get provider name\n");
  1240. return(FALSE);
  1241. }
  1242. //
  1243. // Initialize all the fields in the resource structure.
  1244. // NOTE: The reserved field in dwUsage is set to indicate this is
  1245. // a top level structure.
  1246. //
  1247. Provider->Resource.lpProvider = providerName;
  1248. Provider->Resource.lpRemoteName = providerName;
  1249. Provider->Resource.dwScope = RESOURCE_GLOBALNET;
  1250. Provider->Resource.dwType = 0;
  1251. Provider->Resource.dwDisplayType= RESOURCEDISPLAYTYPE_NETWORK;
  1252. Provider->Resource.dwUsage = RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_RESERVED;
  1253. Provider->Resource.lpComment = NULL;
  1254. //
  1255. // Get the Provider Class. If there isn't a Class value in the
  1256. // registry, assume it is a NetworkClass only.
  1257. //
  1258. status = RegQueryValueEx(
  1259. ProviderInfoKey, // hKey
  1260. VALUE_CLASS, // lpValueName
  1261. NULL, // lpTitleIndex
  1262. &ValueType, // lpType
  1263. (LPBYTE)&Class, // lpData
  1264. &classSize); // lpcbData
  1265. if (status != NO_ERROR) {
  1266. //
  1267. // If we get an error we assume it is because there is no key - thus
  1268. // indicating that this provider is a network provider only.
  1269. //
  1270. MPR_LOG0(TRACE,"Couldn't find Authenticator Class value "
  1271. "- assume it is Network-type only\n");
  1272. Class = WN_NETWORK_CLASS;
  1273. }
  1274. Provider->InitClass = Class;
  1275. MPR_LOG1(TRACE,"MprExtractProviderInfo: Provider InitClass = %d\n",Class);
  1276. //
  1277. // Get the name of the provider's DLL routine
  1278. //
  1279. if(!MprGetKeyValue(ProviderInfoKey,VALUE_PATHNAME,&fileName)){
  1280. MPR_LOG(ERROR,
  1281. "MprExtractProviderInfo: Failed to get the Dll path from registry\n",0);
  1282. //
  1283. // If this is a network class provider, it MUST have a provider
  1284. // dll. Otherwise, we return a failure.
  1285. //
  1286. if (Class & WN_NETWORK_CLASS) {
  1287. return(FALSE);
  1288. }
  1289. else {
  1290. fileName = NULL;
  1291. }
  1292. }
  1293. Provider->DllName = fileName;
  1294. //
  1295. // If this is a CREDENTIAL_CLASS or PRIMARY_AUTHENT_CLASS provider
  1296. // then try to get the dll name for the authentication provider.
  1297. //
  1298. if (Class & (WN_CREDENTIAL_CLASS | WN_PRIMARY_AUTHENT_CLASS)) {
  1299. //
  1300. // Get the name of the provider's Credential Management DLL routine
  1301. //
  1302. if(!MprGetKeyValue(ProviderInfoKey,AUTHENT_PATHNAME,&fileName)){
  1303. //
  1304. // If we can't get a name for the Authentication Provider's DLL,
  1305. // then we will assume the network provider dll exports the
  1306. // Credential Management functions.
  1307. //
  1308. MPR_LOG0(ERROR,
  1309. "MprExtractProviderInfo: Failed to get the Authenticator "
  1310. "Dll path from registry\n");
  1311. //
  1312. // If we don't have a provider dll name, or an authent provider
  1313. // dll name, then this is an error condition.
  1314. //
  1315. if (Provider->DllName == NULL) {
  1316. return(FALSE);
  1317. }
  1318. }
  1319. else {
  1320. Provider->AuthentDllName = fileName;
  1321. }
  1322. }
  1323. return(TRUE);
  1324. }
  1325. BOOL
  1326. MprGetLUIDDeviceMapsEnabled(
  1327. PBOOL pResult
  1328. )
  1329. /*++
  1330. Routine Description:
  1331. This function calls NtQueryInformationProcess() to determine if
  1332. LUID device maps are enabled
  1333. Arguments:
  1334. pResult - returns the result of "Is LUID device maps are enabled?"
  1335. TRUE - LUID device maps are enabled
  1336. FALSE - LUID device maps are disabled
  1337. Return Value:
  1338. TRUE - This is returned if we are able to determine if LUID device
  1339. maps are enabled/disabled.
  1340. FALSE - Encountered an error
  1341. --*/
  1342. {
  1343. NTSTATUS Status;
  1344. ULONG LUIDDeviceMapsEnabled;
  1345. BOOL Result;
  1346. if( pResult == NULL ) {
  1347. return (FALSE);
  1348. }
  1349. Status = NtQueryInformationProcess( NtCurrentProcess(),
  1350. ProcessLUIDDeviceMapsEnabled,
  1351. &LUIDDeviceMapsEnabled,
  1352. sizeof(LUIDDeviceMapsEnabled),
  1353. NULL
  1354. );
  1355. if( !NT_SUCCESS(Status) ) {
  1356. MPR_LOG(ERROR,"MprGetLUIDDeviceMapsEnabled: NtQueryInformationProcess (g_LUIDDeviceMapsEnabled) Error\n",0);
  1357. return( FALSE );
  1358. }
  1359. else{
  1360. Result = (LUIDDeviceMapsEnabled != 0);
  1361. }
  1362. *pResult = Result;
  1363. return( TRUE );
  1364. }
  1365. extern "C" int __cdecl
  1366. _purecall(
  1367. VOID
  1368. )
  1369. {
  1370. // Make it build... (the compiler will initialize all pure virtual
  1371. // function pointers to point to this... If we hit this function,
  1372. // there's a really big problem.)
  1373. RtlRaiseStatus(STATUS_NOT_IMPLEMENTED);
  1374. return 0;
  1375. }