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.

1408 lines
34 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. smbrdr.c
  5. Abstract:
  6. This module implements the functios to load and unload the
  7. smb monolithic minirdr. Also explicit start/stop control is
  8. provided
  9. This module also populates the registry entries for the
  10. driver, and the network provider.
  11. --*/
  12. //#ifndef UNICODE
  13. //#define UNICODE
  14. //#endif
  15. #include <windows.h>
  16. #include <devioctl.h>
  17. #include <stdlib.h>
  18. #include "srfunc.h"
  19. #ifdef DBG
  20. #define DbgP(_x_) DbgPrint _x_
  21. #else
  22. #define DbgP(_x_)
  23. #endif
  24. ULONG _cdecl DbgPrint( LPTSTR Format, ... );
  25. #define TRACE_TAG L"SMBRDR: "
  26. TCHAR* SmbMrxDriverName = TEXT("SmbMRx");
  27. // load action states
  28. ULONG_PTR LoadActionStates[] =
  29. {
  30. RDR_NULL_STATE,
  31. RDR_LOADING,
  32. RDR_NULL_STATE,
  33. RDR_NULL_STATE,
  34. RDR_NULL_STATE,
  35. RDR_NULL_STATE,
  36. RDR_NULL_STATE,
  37. RDR_NULL_STATE,
  38. RDR_NULL_STATE
  39. };
  40. // unload action states
  41. ULONG_PTR UnloadActionStates[] =
  42. {
  43. RDR_NULL_STATE,
  44. RDR_NULL_STATE,
  45. RDR_NULL_STATE,
  46. RDR_NULL_STATE,
  47. RDR_UNLOADING,
  48. RDR_UNLOADING,
  49. RDR_NULL_STATE,
  50. RDR_NULL_STATE,
  51. RDR_NULL_STATE
  52. };
  53. // Start action states
  54. ULONG_PTR StartActionStates[] =
  55. {
  56. RDR_NULL_STATE,
  57. RDR_NULL_STATE,
  58. RDR_NULL_STATE,
  59. RDR_NULL_STATE,
  60. RDR_STARTING,
  61. RDR_STARTING,
  62. RDR_NULL_STATE,
  63. RDR_NULL_STATE,
  64. RDR_NULL_STATE
  65. };
  66. // Stop action states
  67. ULONG_PTR StopActionStates[] =
  68. {
  69. RDR_NULL_STATE,
  70. RDR_NULL_STATE,
  71. RDR_NULL_STATE,
  72. RDR_NULL_STATE,
  73. RDR_NULL_STATE,
  74. RDR_NULL_STATE,
  75. RDR_NULL_STATE,
  76. RDR_NULL_STATE,
  77. RDR_STOPPING
  78. };
  79. ULONG_PTR TransitionActionStates[] =
  80. {
  81. RDR_NULL_STATE,
  82. RDR_NULL_STATE,
  83. RDR_UNLOADED,
  84. RDR_LOADED,
  85. RDR_NULL_STATE,
  86. RDR_NULL_STATE,
  87. RDR_STOPPED,
  88. RDR_STARTED,
  89. RDR_NULL_STATE
  90. };
  91. ULONG_PTR ErrorActionStates[] =
  92. {
  93. RDR_NULL_STATE,
  94. RDR_NULL_STATE,
  95. RDR_LOADED,
  96. RDR_UNLOADED,
  97. RDR_NULL_STATE,
  98. RDR_NULL_STATE,
  99. RDR_STARTED,
  100. RDR_STOPPED,
  101. RDR_NULL_STATE
  102. };
  103. ULONG_PTR NoneActionStates[] =
  104. {
  105. RDR_NULL_STATE,
  106. RDR_UNLOADED,
  107. RDR_UNLOADING,
  108. RDR_LOADING,
  109. RDR_LOADED,
  110. RDR_STOPPED,
  111. RDR_STOPPING,
  112. RDR_STARTING,
  113. RDR_STARTED
  114. };
  115. ULONG_PTR *ActionsStatesArray[] =
  116. {
  117. LoadActionStates,
  118. UnloadActionStates,
  119. StartActionStates,
  120. StopActionStates,
  121. TransitionActionStates,
  122. ErrorActionStates,
  123. NoneActionStates
  124. };
  125. ACTIONVECTOR ActionProcs[] =
  126. {
  127. RdrLoad,
  128. RdrUnload,
  129. RdrStart,
  130. RdrStop,
  131. RdrDoNothing,
  132. RdrDoNothing,
  133. RdrDoNothing
  134. };
  135. typedef enum _INSTALLCHECKS
  136. {
  137. installcheck_start,
  138. installcheck_driverfile,
  139. installcheck_providerfile,
  140. installcheck_serviceentry,
  141. installcheck_providerorder,
  142. installcheck_stop,
  143. installcheck_done
  144. };
  145. ULONG_PTR RdrInstallCheck( void )
  146. {
  147. TCHAR tszTestPath[_MAX_PATH];
  148. ULONG_PTR teststep;
  149. ULONG len = 0;
  150. ULONG_PTR tc = SETUP_COMPLETE;
  151. HANDLE th;
  152. for ( teststep = installcheck_start; teststep < installcheck_done; teststep++ )
  153. {
  154. switch ( teststep )
  155. {
  156. case installcheck_start:
  157. {
  158. len = GetWindowsDirectory( tszTestPath, _MAX_PATH );
  159. }
  160. break;
  161. case installcheck_driverfile:
  162. {
  163. lstrcpyn( &tszTestPath[len], DRIVER_FILE_PATH, _MAX_PATH - len );
  164. th = CreateFile( tszTestPath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
  165. if ( th == INVALID_HANDLE_VALUE )
  166. {
  167. tc = SETUP_MISSING_FILE;
  168. teststep = installcheck_stop;
  169. }
  170. else
  171. {
  172. CloseHandle( th );
  173. }
  174. }
  175. break;
  176. case installcheck_providerfile:
  177. {
  178. lstrcpyn( &tszTestPath[len], PROVIDER_FILE_PATH, _MAX_PATH - len );
  179. th = CreateFile( tszTestPath, 0, 0, NULL, OPEN_EXISTING, 0, NULL );
  180. if ( th == INVALID_HANDLE_VALUE )
  181. {
  182. tc = SETUP_MISSING_FILE;
  183. teststep = installcheck_stop;
  184. }
  185. else
  186. {
  187. CloseHandle( th );
  188. }
  189. }
  190. break;
  191. case installcheck_serviceentry:
  192. {
  193. HKEY hTestKey;
  194. if ( OpenKey( RDRSERVICE_KEY, &hTestKey ) )
  195. {
  196. RegCloseKey( hTestKey );
  197. }
  198. else
  199. {
  200. tc = SETUP_INCOMPLETE;
  201. teststep = installcheck_stop;
  202. }
  203. }
  204. break;
  205. case installcheck_providerorder:
  206. {
  207. LPTSTR pOrder;
  208. RdrGetProviderOrderString( &pOrder );
  209. if ( pOrder )
  210. {
  211. if ( !RdrFindProviderInOrder( pOrder, PROVIDER_NAME ) )
  212. {
  213. tc = SETUP_INCOMPLETE;
  214. teststep = installcheck_stop;
  215. }
  216. free( pOrder );
  217. }
  218. }
  219. break;
  220. case installcheck_stop:
  221. break;
  222. }
  223. }
  224. return tc;
  225. }
  226. BOOL RdrCompleteSetup( void )
  227. {
  228. return RdrSetupServiceEntry( ) && RdrSetupProviderOrder( );
  229. }
  230. // These handles are retained
  231. HANDLE hSharedMemory;
  232. HANDLE hMutex;
  233. BOOL RdrStart(void)
  234. /*++
  235. Routine Description:
  236. This routine starts the SMB sample mini redirector.
  237. Notes:
  238. The start is distinguished from Load. During this phase the appropriate FSCTL
  239. is issued and the shared memory/mutex data structures required for the Network
  240. provider DLL are initialized.
  241. --*/
  242. {
  243. HANDLE DeviceHandle; // The mini rdr device handle
  244. DWORD BytesRet;
  245. BOOL started = FALSE;
  246. // Grab a handle to the redirector device object
  247. DbgP((TEXT("Opening Rdr Device Object for Start Ioctl\n")));
  248. DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
  249. GENERIC_READ | GENERIC_WRITE,
  250. FILE_SHARE_READ | FILE_SHARE_WRITE,
  251. NULL,
  252. OPEN_EXISTING,
  253. 0,
  254. NULL );
  255. DbgP((TEXT("returned from rdr device open\n")));
  256. if ( DeviceHandle != INVALID_HANDLE_VALUE )
  257. {
  258. DbgP(( TEXT("Issueing Rdr Start Ioctl\n") ));
  259. started = DeviceIoControl( DeviceHandle,
  260. IOCTL_SMBMRX_START,
  261. NULL,
  262. 0,
  263. NULL,
  264. 0,
  265. &BytesRet,
  266. NULL );
  267. // Create a section of shared memory to serve as the connection database
  268. if ( started )
  269. {
  270. DWORD Status;
  271. hSharedMemory = CreateFileMapping( INVALID_HANDLE_VALUE,
  272. NULL,
  273. PAGE_READWRITE,
  274. 0,
  275. sizeof(SMBMRXNP_SHARED_MEMORY),
  276. SMBMRXNP_SHARED_MEMORY_NAME);
  277. if (hSharedMemory == NULL)
  278. {
  279. Status = GetLastError();
  280. DbgP((TEXT("SMB MRx Net Provider shared memory Creation status %lx\n"),Status));
  281. }
  282. else
  283. {
  284. PSMBMRXNP_SHARED_MEMORY pSharedMemory;
  285. pSharedMemory = MapViewOfFile(hSharedMemory, FILE_MAP_WRITE, 0, 0, 0);
  286. if (pSharedMemory != NULL)
  287. {
  288. pSharedMemory->HighestIndexInUse = -1;
  289. pSharedMemory->NumberOfResourcesInUse = 0;
  290. }
  291. UnmapViewOfFile(pSharedMemory);
  292. }
  293. hMutex = CreateMutex( NULL,
  294. FALSE,
  295. SMBMRXNP_MUTEX_NAME);
  296. if (hMutex == NULL)
  297. {
  298. Status = GetLastError();
  299. DbgP(( TEXT("SMB MRx Net Provider Mutex Creation status %lx\n"), Status));
  300. }
  301. }
  302. else
  303. {
  304. DbgP(( TEXT("The DeviceIoctl for Starting Redirector returned %lx\n"), GetLastError() ));
  305. }
  306. }
  307. else
  308. {
  309. DbgP(( TEXT("The CreateFile for opening device failed with error 0x%lx\n"), GetLastError() ));
  310. DbgP(( TEXT("Device is %s\n"),DD_SMBMRX_USERMODE_DEV_NAME ));
  311. }
  312. //DbgP((TEXT("SMB MRx sample mini redirector start status %lx\n"),ntstatus));
  313. CloseHandle(DeviceHandle);
  314. return started;
  315. }
  316. BOOL RdrStop( void )
  317. /*++
  318. Routine Description:
  319. This routine stops the SMB sample mini redirector.
  320. Notes:
  321. The stop is distinguished from unload. During this phase the appropriate FSCTL
  322. is issued and the shared memory/mutex data structures required for the Network
  323. provider DLL are torn down.
  324. --*/
  325. {
  326. HANDLE DeviceHandle; // The mini rdr device handle
  327. DWORD BytesRet;
  328. BOOL stopped = FALSE;
  329. // Grab a handle to the redirector device object
  330. DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
  331. GENERIC_READ | GENERIC_WRITE,
  332. FILE_SHARE_READ | FILE_SHARE_WRITE,
  333. NULL,
  334. OPEN_EXISTING,
  335. 0,
  336. NULL );
  337. DbgP((TEXT("Doing Stop DeviceIoControl\n")));
  338. if ( DeviceHandle != INVALID_HANDLE_VALUE )
  339. {
  340. stopped = DeviceIoControl( DeviceHandle,
  341. IOCTL_SMBMRX_STOP,
  342. NULL,
  343. 0,
  344. NULL,
  345. 0,
  346. &BytesRet,
  347. NULL );
  348. CloseHandle( DeviceHandle );
  349. }
  350. else
  351. {
  352. DbgP(( TEXT("The CreateFile for opening device failed\n") ));
  353. }
  354. CloseHandle(hMutex);
  355. CloseHandle(hSharedMemory);
  356. // DbgP(( TEXT("SMB MRx sample mini redirector start status %lx\n"),ntstatus ));
  357. return stopped;
  358. }
  359. BOOL RdrLoad( void )
  360. {
  361. SC_HANDLE sch, service;
  362. BOOL loaded = FALSE;
  363. DbgP((TEXT("Loading SMB sample minirdr.......\n")));
  364. sch = OpenSCManager( NULL, NULL, GENERIC_EXECUTE );
  365. if ( sch )
  366. {
  367. service = OpenService( sch, RDRSERVICE, GENERIC_EXECUTE );
  368. if ( service )
  369. {
  370. loaded = StartService( service, 0, NULL );
  371. CloseServiceHandle( service );
  372. }
  373. CloseServiceHandle( sch );
  374. }
  375. return loaded;
  376. }
  377. BOOL RdrUnload( void )
  378. {
  379. SC_HANDLE sch, service;
  380. BOOL unloaded = FALSE;
  381. DbgP((TEXT("Unloading SMB sample minirdr.......\n")));
  382. sch = OpenSCManager( NULL, NULL, GENERIC_EXECUTE );
  383. if ( sch )
  384. {
  385. service = OpenService( sch, RDRSERVICE, GENERIC_EXECUTE );
  386. if ( service )
  387. {
  388. SERVICE_STATUS ss;
  389. unloaded = ControlService( service, SERVICE_CONTROL_STOP, &ss );
  390. CloseServiceHandle( service );
  391. }
  392. CloseServiceHandle( sch );
  393. }
  394. return unloaded;
  395. }
  396. BOOL RdrDoNothing( void )
  397. {
  398. return TRUE;
  399. }
  400. BOOL RdrDoAction( ULONG_PTR action )
  401. {
  402. return (*ActionProcs[action])( );
  403. }
  404. ULONG_PTR RdrGetInitialState(void)
  405. {
  406. ULONG_PTR state = RDR_UNLOADED;
  407. SC_HANDLE sch, service;
  408. sch = OpenSCManager( NULL, NULL, GENERIC_READ );
  409. if ( sch )
  410. {
  411. service = OpenService( sch, RDRSERVICE, GENERIC_READ );
  412. if ( service )
  413. {
  414. SERVICE_STATUS ss;
  415. if ( QueryServiceStatus( service, &ss ) )
  416. {
  417. switch ( ss.dwCurrentState )
  418. {
  419. case SERVICE_STOPPED:
  420. state = RDR_UNLOADED;
  421. break;
  422. case SERVICE_START_PENDING:
  423. state = RDR_LOADING;
  424. break;
  425. case SERVICE_STOP_PENDING:
  426. state = RDR_UNLOADING;
  427. break;
  428. case SERVICE_RUNNING:
  429. state = RDR_LOADED;
  430. break;
  431. case SERVICE_CONTINUE_PENDING:
  432. case SERVICE_PAUSE_PENDING:
  433. case SERVICE_PAUSED:
  434. default:
  435. state = RDR_UNLOADED;
  436. break;
  437. }
  438. #if 0 //just check for load/unload state for now
  439. // go check the start/stop state
  440. if ( state == RDR_LOADED )
  441. {
  442. BOOL IsOk;
  443. HANDLE DeviceHandle;
  444. DWORD BytesRet;
  445. ULONG_PTR RdrStateValue;
  446. DeviceHandle = CreateFile( DD_SMBMRX_USERMODE_DEV_NAME,
  447. GENERIC_READ | GENERIC_WRITE,
  448. FILE_SHARE_READ | FILE_SHARE_WRITE,
  449. NULL,
  450. OPEN_EXISTING,
  451. 0,
  452. NULL );
  453. if ( DeviceHandle != INVALID_HANDLE_VALUE )
  454. {
  455. DbgP((TEXT("Doing Get State DeviceIoControl\n")));
  456. IsOk = DeviceIoControl( DeviceHandle,
  457. IOCTL_SMBMRX_GETSTATE,
  458. NULL,
  459. 0,
  460. &RdrStateValue,
  461. sizeof(ULONG),
  462. &BytesRet,
  463. NULL );
  464. CloseHandle( DeviceHandle );
  465. }
  466. if ( IsOk )
  467. {
  468. state = RdrStateValue;
  469. }
  470. }
  471. #endif
  472. }
  473. CloseServiceHandle( service );
  474. }
  475. CloseServiceHandle( sch );
  476. }
  477. return state;
  478. }
  479. ULONG_PTR RdrGetNextState( ULONG_PTR Action, ULONG_PTR CurrentState )
  480. {
  481. return ActionsStatesArray[Action][CurrentState];
  482. }
  483. REGENTRY LinkageKeyValues[] =
  484. {
  485. { TEXT("Bind"), REG_MULTI_SZ, 0, 0 },
  486. { TEXT("Export"), REG_MULTI_SZ, 0, 0 },
  487. { TEXT("Route"), REG_MULTI_SZ, 0, 0 }
  488. };
  489. REGENTRY LinkageDisabledKeyValues[] =
  490. {
  491. { TEXT("Bind"), REG_MULTI_SZ, 0, 0 },
  492. { TEXT("Export"), REG_MULTI_SZ, 0, 0 },
  493. { TEXT("Route"), REG_MULTI_SZ, 0, 0 }
  494. };
  495. REGENTRY NetworkProviderKeyValues[] =
  496. {
  497. {
  498. TEXT("Devicename"),
  499. REG_SZ,
  500. sizeof(SMBMRX_DEVICE_NAME),
  501. SMBMRX_DEVICE_NAME
  502. },
  503. {
  504. TEXT("ProviderPath"),
  505. REG_EXPAND_SZ,
  506. sizeof(PROVIDER_PATH),
  507. PROVIDER_PATH
  508. },
  509. {
  510. TEXT("Name"),
  511. REG_SZ,
  512. sizeof(SMBMRX_PROVIDER_NAME),
  513. SMBMRX_PROVIDER_NAME
  514. }
  515. };
  516. REGENTRY ProviderOrderKeyValues[] =
  517. {
  518. { TEXT("ProviderOrder"), REG_SZ, 0, 0 }
  519. };
  520. BOOL RdrSetupServiceEntry( void )
  521. /*++
  522. Routine Description:
  523. This routine initializes the registry entries for the smbmrx
  524. minirdr. This only needs to be done once.
  525. Arguments:
  526. None
  527. Return Value:
  528. None
  529. --*/
  530. {
  531. HKEY hCurrentKey;
  532. SC_HANDLE sch, service;
  533. BOOL success = TRUE;
  534. DbgP(( TEXT( "Setting up ") RDRSERVICE TEXT(" registry Entries\n" ) ));
  535. sch = OpenSCManager( NULL, NULL, GENERIC_WRITE );
  536. if ( sch )
  537. {
  538. service = CreateService( sch,
  539. RDRSERVICE,
  540. RDRSERVICE,
  541. SERVICE_ALL_ACCESS,
  542. SERVICE_FILE_SYSTEM_DRIVER,
  543. SERVICE_DEMAND_START,
  544. SERVICE_ERROR_NORMAL,
  545. TEXT("System32\\DRIVERS\\") RDRSERVICE TEXT(".sys"),
  546. TEXT("Network"),
  547. NULL,
  548. NULL,
  549. NULL,
  550. NULL );
  551. if ( service )
  552. {
  553. CloseServiceHandle( service );
  554. }
  555. else if ( GetLastError( ) != ERROR_SERVICE_EXISTS )
  556. {
  557. success = FALSE;
  558. }
  559. CloseServiceHandle( sch );
  560. }
  561. else
  562. {
  563. success = FALSE;
  564. }
  565. // Read the linkage values associated with the Lanman workstation service.
  566. // This contains all the transports and the order in which they need to be used
  567. if ( success && OpenKey( WKSSERVICE_KEY TEXT("\\Linkage"), &hCurrentKey ) )
  568. {
  569. ULONG i;
  570. ReadRegistryKeyValues( hCurrentKey,
  571. sizeof(LinkageKeyValues) / sizeof(REGENTRY),
  572. LinkageKeyValues);
  573. RegCloseKey(hCurrentKey);
  574. // Update the SMB MRx linkage values
  575. if ( CreateKey( RDRSERVICE_KEY TEXT("\\Linkage"), &hCurrentKey ) )
  576. {
  577. WriteRegistryKeyValues( hCurrentKey,
  578. sizeof(LinkageKeyValues) / sizeof(REGENTRY),
  579. LinkageKeyValues);
  580. RegCloseKey(hCurrentKey);
  581. }
  582. else
  583. {
  584. success = FALSE;
  585. }
  586. for ( i = 0; i < ( sizeof(LinkageKeyValues) / sizeof(REGENTRY) ); i++ )
  587. {
  588. if ( LinkageKeyValues[i].pvValue )
  589. {
  590. free( LinkageKeyValues[i].pvValue );
  591. LinkageKeyValues[i].pvValue = NULL;
  592. }
  593. }
  594. }
  595. else
  596. {
  597. success = FALSE;
  598. }
  599. //if ( OpenKey( WKSSERVICE_KEY TEXT("\\Linkage\\Disabled",&hCurrentKey))
  600. //{
  601. // ReadRegistryKeyValues( hCurrentKey,
  602. // sizeof(LinkageDisabledKeyValues) / sizeof(REGENTRY),
  603. // LinkageDisabledKeyValues);
  604. // RegCloseKey(hCurrentKey);
  605. //}
  606. //else
  607. //{
  608. // DbgP(( TEXT("Error Opening Key %s Status %d\n"),WKSSERVICE_KEY TEXT("\\Linkage\\Disabled"),GetLastError() ));
  609. // return;
  610. //}
  611. // Update the SMB MRx linkage disabled values
  612. //if ( CreateKey( RDRSERVICE_KEY TEXT("\\Linkage\\Disabled") ,&hCurrentKey))
  613. //{
  614. // WriteRegistryKeyValues( hCurrentKey,
  615. // sizeof(LinkageDisabledKeyValues)/sizeof(REGENTRY),
  616. // LinkageDisabledKeyValues );
  617. // RegCloseKey(hCurrentKey);
  618. //}
  619. //else
  620. //{
  621. // DbgP(( TEXT("Error Creating Key %s Status %d\n"),RDRSERVICE_KEY TEXT("\\linkage\\disabled",GetLastError() ));
  622. // return;
  623. //}
  624. // Update the SMBmrx network provider section
  625. if ( success && CreateKey( RDRSERVICE_KEY TEXT("\\NetworkProvider"), &hCurrentKey ) )
  626. {
  627. WriteRegistryKeyValues( hCurrentKey,
  628. sizeof(NetworkProviderKeyValues)/sizeof(REGENTRY),
  629. NetworkProviderKeyValues);
  630. RegCloseKey(hCurrentKey);
  631. }
  632. else
  633. {
  634. success = FALSE;
  635. }
  636. if ( success && CreateKey( RDRSERVICE_KEY TEXT("\\Parameters"), &hCurrentKey ) )
  637. {
  638. RegCloseKey( hCurrentKey );
  639. }
  640. else
  641. {
  642. success = FALSE;
  643. }
  644. return success;
  645. }
  646. BOOL RdrSetupProviderOrder( void )
  647. {
  648. LPTSTR pOrderString = NULL;
  649. ULONG_PTR len;
  650. BOOL success = TRUE;
  651. len = RdrGetProviderOrderString( &pOrderString ) * sizeof(TCHAR);
  652. if ( len > 0 && pOrderString )
  653. {
  654. if ( !RdrFindProviderInOrder( pOrderString, PROVIDER_NAME ) )
  655. {
  656. LPTSTR pNewOrderString;
  657. len += sizeof( PROVIDER_NAME ) + (2 * sizeof(TCHAR)); // add 2 for comma delimeter and null
  658. pNewOrderString = malloc( len );
  659. if ( pNewOrderString )
  660. {
  661. lstrcpy( pNewOrderString, pOrderString );
  662. lstrcat( pNewOrderString, TEXT(",") );
  663. lstrcat( pNewOrderString, PROVIDER_NAME );
  664. success = RdrSetProviderOrderString( pNewOrderString );
  665. free( pNewOrderString );
  666. }
  667. }
  668. }
  669. else
  670. {
  671. success = RdrSetProviderOrderString( PROVIDER_NAME );
  672. }
  673. if ( pOrderString )
  674. {
  675. free( pOrderString );
  676. }
  677. return success;
  678. }
  679. ULONG_PTR RdrGetProviderOrderString( LPTSTR *OrderString )
  680. {
  681. HKEY hOrderKey;
  682. ULONG_PTR len = 0;
  683. if ( OpenKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
  684. {
  685. ReadRegistryKeyValues( hOrderKey,
  686. sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
  687. ProviderOrderKeyValues);
  688. RegCloseKey(hOrderKey);
  689. len = ProviderOrderKeyValues[0].dwLength / sizeof( TCHAR ) - 1;
  690. *OrderString = (LPTSTR) ProviderOrderKeyValues[0].pvValue;
  691. }
  692. return len;
  693. }
  694. BOOL RdrSetProviderOrderString( LPTSTR OrderString )
  695. {
  696. HKEY hOrderKey;
  697. ULONG len = 0;
  698. BOOL rc = FALSE;
  699. if ( CreateKey( PROVIDER_ORDER_KEY, &hOrderKey ) )
  700. {
  701. ProviderOrderKeyValues[0].dwLength = ( lstrlen( OrderString ) + 1 ) * sizeof( TCHAR );
  702. ProviderOrderKeyValues[0].pvValue = OrderString;
  703. WriteRegistryKeyValues( hOrderKey,
  704. sizeof(ProviderOrderKeyValues) / sizeof(REGENTRY),
  705. ProviderOrderKeyValues);
  706. RegCloseKey(hOrderKey);
  707. rc = TRUE;
  708. }
  709. return rc;
  710. }
  711. BOOL RdrFindProviderInOrder( LPTSTR OrderString, LPTSTR Provider )
  712. {
  713. LPTSTR pCompare;
  714. BOOL match = FALSE;
  715. if ( OrderString && Provider && *Provider )
  716. {
  717. pCompare = Provider;
  718. while ( *OrderString )
  719. {
  720. if ( toupper(*OrderString++) != toupper(*pCompare++) )
  721. {
  722. pCompare = Provider;
  723. }
  724. if ( *pCompare == TEXT('\0') )
  725. {
  726. if ( ( *OrderString == TEXT(',') ) || ( *OrderString == TEXT('\0') ) )
  727. {
  728. match = TRUE;
  729. break;
  730. }
  731. else // hmm, it's a substring of another provider name
  732. {
  733. while ( ( *OrderString != TEXT(',') ) && ( *OrderString != TEXT('\0') ) )
  734. {
  735. OrderString++;
  736. }
  737. pCompare = Provider;
  738. }
  739. }
  740. }
  741. }
  742. return match;
  743. }
  744. void
  745. ReadRegistryKeyValues(
  746. HKEY hCurrentKey,
  747. DWORD NumberOfValues,
  748. PREGENTRY pValues)
  749. /*++
  750. Routine Description:
  751. This routine reads a bunch of values associated with a given key.
  752. Arguments:
  753. hCurrentKey - the key
  754. NumberOfValues - the number of values
  755. pValues - the array of values
  756. Return Value:
  757. None
  758. --*/
  759. {
  760. //
  761. // Iterate through table reading the values along the way
  762. //
  763. DWORD i;
  764. for (i = 0; i < NumberOfValues; i++)
  765. {
  766. DWORD dwType;
  767. LPTSTR pszKey;
  768. dwType = pValues[i].dwType;
  769. pszKey = pValues[i].pszKey;
  770. switch (dwType)
  771. {
  772. case REG_SZ:
  773. GetRegsz(hCurrentKey, pszKey, &pValues[i].pvValue,
  774. &pValues[i].dwLength);
  775. break;
  776. case REG_DWORD:
  777. GetRegdw(hCurrentKey, pszKey, &pValues[i].pvValue,
  778. &pValues[i].dwLength);
  779. break;
  780. case REG_EXPAND_SZ:
  781. GetRegesz(hCurrentKey, pszKey, &pValues[i].pvValue,
  782. &pValues[i].dwLength);
  783. break;
  784. case REG_MULTI_SZ:
  785. GetRegmsz(hCurrentKey, pszKey, &pValues[i].pvValue,
  786. &pValues[i].dwLength);
  787. break;
  788. case REG_BINARY:
  789. DbgP(( TEXT("%s is a REG_BINARY and won't be duplicated\n"), pszKey ));
  790. break;
  791. default:
  792. DbgP(( TEXT("%s is an unknown type; %d (decimal)\n"), pszKey, dwType ));
  793. break;
  794. }
  795. }
  796. }
  797. //
  798. // Get a REG_SZ value and stick it in the table entry, along with the
  799. // length
  800. //
  801. BOOL GetRegsz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD *pdwLength)
  802. {
  803. BYTE achValue[1024];
  804. DWORD dwLength;
  805. LONG Status;
  806. DWORD dwType = REG_SZ;
  807. PBYTE pszValue = NULL;
  808. if ( (NULL == pszKey) || (NULL == ppvValue) ||
  809. (NULL == hKey) || (NULL == pdwLength))
  810. {
  811. return FALSE;
  812. }
  813. #ifdef _DEBUG
  814. FillMemory(achValue, sizeof(achValue), 0xcd);
  815. #endif
  816. dwLength = sizeof(achValue);
  817. Status = RegQueryValueEx( hKey,
  818. pszKey,
  819. NULL,
  820. &dwType,
  821. (PUCHAR) &achValue[0],
  822. &dwLength);
  823. if ((ERROR_SUCCESS != Status) || (REG_SZ != dwType) )
  824. {
  825. return FALSE;
  826. }
  827. pszValue = malloc(dwLength);
  828. if (NULL == pszValue)
  829. {
  830. return FALSE;
  831. }
  832. CopyMemory(pszValue, achValue, dwLength);
  833. *ppvValue = pszValue;
  834. *pdwLength = dwLength;
  835. return TRUE;
  836. }
  837. //
  838. // Get the value of a REG_EXPAND_SZ and its length
  839. //
  840. BOOL GetRegesz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
  841. {
  842. BYTE achValue[1024];
  843. DWORD dwLength;
  844. LONG Status;
  845. DWORD dwType = REG_EXPAND_SZ;
  846. PBYTE pszValue = NULL;
  847. if ( (NULL == pszKey) || (NULL == ppvValue) ||
  848. (NULL == hKey) || (NULL == pdwLength))
  849. {
  850. return FALSE;
  851. }
  852. #ifdef _DEBUG
  853. FillMemory(achValue, sizeof(achValue), 0xcd);
  854. #endif
  855. dwLength = sizeof(achValue);
  856. Status = RegQueryValueEx( hKey,
  857. pszKey,
  858. NULL,
  859. &dwType,
  860. (PUCHAR) &achValue[0],
  861. &dwLength);
  862. if ((ERROR_SUCCESS != Status) || (REG_EXPAND_SZ != dwType))
  863. {
  864. return FALSE;
  865. }
  866. pszValue = malloc(dwLength);
  867. if (NULL == pszValue)
  868. {
  869. return FALSE;
  870. }
  871. CopyMemory(pszValue, achValue, dwLength);
  872. *ppvValue = pszValue;
  873. *pdwLength = dwLength;
  874. return TRUE;
  875. }
  876. //
  877. // Get value and length of REG_MULTI_SZ
  878. //
  879. BOOL GetRegmsz(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
  880. {
  881. //BYTE achValue[1024];
  882. BYTE achValue[2048]; // careful, some of these strings are quite long
  883. DWORD dwLength;
  884. LONG Status;
  885. DWORD dwType = REG_MULTI_SZ;
  886. PBYTE pszValue = NULL;
  887. if ( (NULL == pszKey) || (NULL == ppvValue) ||
  888. (NULL == hKey) || (NULL == pdwLength))
  889. {
  890. return FALSE;
  891. }
  892. #ifdef _DEBUG
  893. FillMemory(achValue, sizeof(achValue), 0xcd);
  894. #endif
  895. dwLength = sizeof(achValue);
  896. Status = RegQueryValueEx( hKey,
  897. pszKey,
  898. NULL,
  899. &dwType,
  900. (PUCHAR) &achValue[0],
  901. &dwLength);
  902. if ((ERROR_SUCCESS != Status) || (REG_MULTI_SZ != dwType))
  903. {
  904. return FALSE;
  905. }
  906. pszValue = malloc(dwLength);
  907. if (NULL == pszValue)
  908. {
  909. return FALSE;
  910. }
  911. CopyMemory(pszValue, achValue, dwLength);
  912. *ppvValue = pszValue;
  913. *pdwLength = dwLength;
  914. return TRUE;
  915. }
  916. //
  917. // Get value and length of REG_DWORD
  918. //
  919. BOOL GetRegdw(HKEY hKey, LPTSTR pszKey, PVOID * ppvValue, DWORD * pdwLength)
  920. {
  921. DWORD dwValue = 0;
  922. DWORD dwLength;
  923. LONG Status;
  924. DWORD dwType = REG_DWORD;
  925. if ( (NULL == pszKey) || (NULL == ppvValue) ||
  926. (NULL == hKey) || (NULL == pdwLength) )
  927. {
  928. return FALSE;
  929. }
  930. dwLength = sizeof(dwValue);
  931. Status = RegQueryValueEx( hKey,
  932. pszKey,
  933. NULL,
  934. &dwType,
  935. (PUCHAR) &dwValue,
  936. &dwLength);
  937. if ((ERROR_SUCCESS != Status) || (REG_DWORD != dwType))
  938. {
  939. return FALSE;
  940. }
  941. *ppvValue = (PVOID) (ULONG_PTR) dwValue;
  942. *pdwLength = dwLength;
  943. return TRUE;
  944. }
  945. void
  946. WriteRegistryKeyValues(
  947. HKEY hCurrentKey,
  948. DWORD NumberOfValues,
  949. PREGENTRY pValues)
  950. /*++
  951. Routine Description:
  952. This routine reads a bunch of values associated with a given key.
  953. Arguments:
  954. hCurrentKey - the key
  955. NumberOfValues - the number of values
  956. pValues - the array of values
  957. Return Value:
  958. None
  959. --*/
  960. {
  961. DWORD i;
  962. for (i = 0; i < NumberOfValues; i++)
  963. {
  964. DWORD dwType;
  965. PVOID pvValue;
  966. DWORD dwLength;
  967. LPTSTR pszKey;
  968. pszKey = pValues[i].pszKey;
  969. dwType = pValues[i].dwType;
  970. dwLength = pValues[i].dwLength;
  971. pvValue = pValues[i].pvValue;
  972. switch (dwType)
  973. {
  974. case REG_SZ:
  975. AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
  976. break;
  977. case REG_DWORD:
  978. AddValue(hCurrentKey, pszKey, dwType, dwLength, &pvValue);
  979. break;
  980. case REG_EXPAND_SZ:
  981. AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
  982. break;
  983. case REG_MULTI_SZ:
  984. AddValue(hCurrentKey, pszKey, dwType, dwLength, pvValue);
  985. break;
  986. case REG_BINARY:
  987. //
  988. // There are no binary values we need to copy. If we did, we'd
  989. // put something here
  990. //
  991. break;
  992. default:
  993. DbgP(( TEXT("%s is an unknown type; %d (decimal)\n"), pszKey, dwType ));
  994. break;
  995. }
  996. }
  997. }
  998. //
  999. // Open a key so we can read the values
  1000. //
  1001. BOOL OpenKey(
  1002. LPTSTR pszKey,
  1003. PHKEY phKey)
  1004. /*++
  1005. Routine Description:
  1006. This routine opens a registry key.
  1007. Arguments:
  1008. pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
  1009. phKey - the key handlle
  1010. Return Value:
  1011. TRUE if successful, otherwise FALSE
  1012. --*/
  1013. {
  1014. HKEY hNewKey = 0;
  1015. DWORD Status;
  1016. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1017. pszKey,
  1018. 0,
  1019. KEY_QUERY_VALUE,
  1020. &hNewKey);
  1021. if (ERROR_SUCCESS != Status)
  1022. {
  1023. *phKey = NULL;
  1024. return FALSE;
  1025. }
  1026. else
  1027. {
  1028. *phKey = hNewKey;
  1029. return TRUE;
  1030. }
  1031. }
  1032. BOOL CreateKey(LPTSTR pszKey, PHKEY phKey)
  1033. /*++
  1034. Routine Description:
  1035. This routine creates a registry key.
  1036. Arguments:
  1037. pszKey - the name of the key relative to HKEY_LOCAL_MACHINE
  1038. phKey - the key handlle
  1039. Return Value:
  1040. TRUE if successful, otherwise FALSE
  1041. --*/
  1042. {
  1043. LONG Status;
  1044. DWORD Disposition;
  1045. Status = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  1046. pszKey,
  1047. 0,
  1048. REG_NONE,
  1049. REG_OPTION_NON_VOLATILE,
  1050. KEY_ALL_ACCESS,
  1051. NULL,
  1052. phKey,
  1053. &Disposition);
  1054. if ( ERROR_SUCCESS == Status)
  1055. {
  1056. return TRUE;
  1057. }
  1058. else
  1059. {
  1060. DbgP(( TEXT("error creating key %s Status %d\n"), pszKey, Status ));
  1061. return FALSE;
  1062. }
  1063. }
  1064. //
  1065. // Add a value to the registry
  1066. //
  1067. BOOL AddValue(HKEY hKey, LPTSTR pszKey, DWORD dwType, DWORD dwLength, PVOID pvValue)
  1068. {
  1069. BOOL fSuccess = TRUE;
  1070. LONG Status = ERROR_SUCCESS;
  1071. HANDLE th;
  1072. Status = RegSetValueEx( hKey,
  1073. pszKey,
  1074. 0,
  1075. dwType,
  1076. pvValue,
  1077. dwLength);
  1078. if (Status != ERROR_SUCCESS)
  1079. {
  1080. fSuccess = FALSE;
  1081. //RegCloseKey(hKey);
  1082. }
  1083. return fSuccess;
  1084. }
  1085. int _cdecl _vsnwprintf( wchar_t *buffer, size_t count, wchar_t *format, va_list arg_ptr);
  1086. // Format and write debug information to OutputDebugString
  1087. ULONG
  1088. _cdecl
  1089. DbgPrint(
  1090. LPTSTR Format,
  1091. ...
  1092. )
  1093. {
  1094. ULONG rc = 0;
  1095. TCHAR szbuffer[256];
  1096. va_list marker;
  1097. va_start( marker, Format );
  1098. {
  1099. rc = _vsnwprintf( szbuffer, 254, Format, marker );
  1100. szbuffer[255] = (TCHAR)0;
  1101. OutputDebugString( TRACE_TAG );
  1102. OutputDebugString( szbuffer );
  1103. }
  1104. return rc;
  1105. }