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.

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