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.

1250 lines
36 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // File: SETUPSVC.CXX
  4. //
  5. // Contents:
  6. //
  7. // Synoposis:
  8. //
  9. // Classes: CService
  10. //
  11. // Functions:
  12. //
  13. // History: May 19, 1993 AlokS Created
  14. //
  15. //-------------------------------------------------------------------
  16. #include <windows.h>
  17. #include <ole2.h>
  18. #include <registry.hxx>
  19. #include <setupsvc.hxx>
  20. #include <dfsstr.h>
  21. #include "messages.h"
  22. VOID
  23. MyFormatMessage(
  24. IN HRESULT dwMsgId,
  25. IN PWSTR pszBuffer,
  26. IN DWORD dwBufferSize,
  27. ...
  28. );
  29. //+------------------------------------------------------------------
  30. //
  31. // Class: CService
  32. //
  33. // Purpose: Helper class for dealing with Service Controller
  34. //
  35. // Interface: CService::CService() = Constructor
  36. // CService::~CService() = Destructor
  37. // CService::Init() = Initializes the class
  38. // CService::_CreateService() = Install a Win32 Service
  39. // CService::_OpenService() = Open an existing service
  40. // CService::_QueryServiceStatus() = Query servcie status.
  41. // CService::_CloseService() = Close all resources associated with
  42. // the service
  43. // CService::_DeleteService() = Remove a Win32 Service
  44. // CService::_DisableService() = Disables a Win32 Service
  45. // CService::_StartService() = Start an existing service
  46. // CService::_StopService() = Stop an existing, running service
  47. // CService::_ConfigService() = Combo operation. Create if
  48. // not present else reconfigure it
  49. //
  50. // History: May 20, 1993 AlokS Created
  51. //
  52. // Notes: This is a smart wrapper class for Service APIs. But it is not
  53. // multi-thread safe.
  54. //
  55. //-------------------------------------------------------------------
  56. //+------------------------------------------------------------------
  57. //
  58. // Member: CService::CService
  59. //
  60. // Synopsis: Create an instance
  61. //
  62. // Effects: Instantiates the class
  63. //
  64. // Arguments: -none-
  65. //
  66. // Returns : None.
  67. //
  68. // History: May 20, 1993 AlokS Created
  69. //
  70. // Notes: The class allows only one handle to service per instance of this
  71. // class. Plus, it is not written to close handles before opening
  72. // new service. However, it does guarantee to close handles
  73. // (SC database and one Service handle) at destruction time.
  74. //
  75. //-------------------------------------------------------------------
  76. CService::CService():
  77. _schSCManager(NULL),
  78. _scHandle(NULL)
  79. {
  80. ;
  81. }
  82. //+------------------------------------------------------------------
  83. //
  84. // Member: CService::Init
  85. //
  86. // Synopsis: Open handle to Service Controller
  87. //
  88. // Effects: -do-
  89. //
  90. // Arguments: -none-
  91. //
  92. // Returns : 0 on success else error from opening SC.
  93. //
  94. // History: Nov 4, 1993 AlokS Created
  95. //
  96. // Notes: The class allows only one handle to service per instance of this
  97. // class. Plus, it is not written to close handles before opening
  98. // new service. However, it does guarantee to close handles
  99. // (SC database and one Service handle) at destruction time.
  100. //
  101. //-------------------------------------------------------------------
  102. DWORD CService::Init()
  103. {
  104. DWORD dwStatus = 0;
  105. // Open the local SC database
  106. _schSCManager = OpenSCManager(NULL, // Machine Name
  107. NULL, // Database Name
  108. SC_MANAGER_CREATE_SERVICE|
  109. SC_MANAGER_LOCK
  110. );
  111. if (_schSCManager == NULL)
  112. {
  113. dwStatus = GetLastError();
  114. DSSCDebugOut(( DEB_IERROR, "Error: %lx in opening SCManager", dwStatus));
  115. }
  116. return(dwStatus);
  117. }
  118. //+------------------------------------------------------------------
  119. //
  120. // Member: CService::~CService
  121. //
  122. // Synopsis: Release all resources
  123. //
  124. // Effects: Closes SC database handle as well as any service handle
  125. //
  126. // Arguments: none
  127. //
  128. // History: May 20, 1993 AlokS Created
  129. //
  130. // Notes: Remember that we have only 1 service handle per instance.
  131. //
  132. //-------------------------------------------------------------------
  133. CService::~CService()
  134. {
  135. if (_schSCManager != NULL)
  136. CloseServiceHandle (_schSCManager);
  137. if (_scHandle != NULL)
  138. CloseServiceHandle (_scHandle);
  139. }
  140. //+------------------------------------------------------------------
  141. //
  142. // Member: CService::_CreateService
  143. //
  144. // Synopsis: This method is used to install a new Win32 Service or driver
  145. //
  146. // Effects: Creates a service.
  147. //
  148. // Arguments: all [in] parameters. See CreateService() API documentation
  149. //
  150. // Returns: 0 on success
  151. //
  152. // History: May 20, 1993 AlokS Created
  153. //
  154. // Notes: The handle of newly created service is remembered and closed by
  155. // destructor
  156. //
  157. //-------------------------------------------------------------------
  158. DWORD CService::_CreateService(const LPWSTR lpwszServiceName,
  159. const LPWSTR lpwszDisplayName,
  160. DWORD fdwDesiredAccess,
  161. DWORD fdwServiceType,
  162. DWORD fdwStartType,
  163. DWORD fdwErrorControl,
  164. const LPWSTR lpwszBinaryPathName,
  165. const LPWSTR lpwszLoadOrderGroup,
  166. const LPDWORD lpdwTagID,
  167. const LPWSTR lpwszDependencies,
  168. const LPWSTR lpwszServiceStartName,
  169. const LPWSTR lpwszPassword)
  170. {
  171. if (_schSCManager==NULL)
  172. {
  173. return(ERROR_INVALID_HANDLE);
  174. }
  175. DWORD dwStatus =0;
  176. _scHandle = CreateService(_schSCManager,
  177. lpwszServiceName,
  178. lpwszDisplayName,
  179. fdwDesiredAccess,
  180. fdwServiceType,
  181. fdwStartType,
  182. fdwErrorControl,
  183. lpwszBinaryPathName,
  184. lpwszLoadOrderGroup,
  185. lpdwTagID,
  186. lpwszDependencies,
  187. lpwszServiceStartName,
  188. lpwszPassword
  189. );
  190. if (_scHandle==NULL)
  191. {
  192. dwStatus = GetLastError();
  193. DSSCDebugOut(( DEB_IERROR,
  194. "Error: %lx in CreateService: %ws\n",
  195. dwStatus,
  196. lpwszServiceName));
  197. }
  198. return dwStatus;
  199. }
  200. //+------------------------------------------------------------------
  201. //
  202. // Member: CService::_OpenService
  203. //
  204. // Synopsis: Opens the service if caller has specified proper access
  205. //
  206. // Effects: Opens a service, if one exists
  207. //
  208. // Arguments: [in] lpwszServiceName = Name of the service
  209. // [in] fdwDesiredAccess = Open Access mode bits
  210. //
  211. // Returns: 0 on success
  212. //
  213. // History: May 20, 1993 AlokS Created
  214. //
  215. // Notes: The handle of opened service is remembered and closed by
  216. // destructor
  217. //
  218. //-------------------------------------------------------------------
  219. DWORD CService::_OpenService( const LPWSTR lpwszServiceName,
  220. DWORD fdwDesiredAccess
  221. )
  222. {
  223. if (_schSCManager==NULL)
  224. {
  225. return(ERROR_INVALID_HANDLE);
  226. }
  227. DWORD dwStatus =0;
  228. _scHandle = OpenService ( _schSCManager,
  229. lpwszServiceName,
  230. fdwDesiredAccess
  231. );
  232. if (_scHandle==NULL)
  233. {
  234. dwStatus = GetLastError();
  235. DSSCDebugOut(( DEB_IERROR,
  236. "Error: %lx in OpeningService: %ws\n",
  237. dwStatus,
  238. lpwszServiceName
  239. ));
  240. }
  241. return dwStatus;
  242. }
  243. //+------------------------------------------------------------------
  244. //
  245. // Member: CService::_StartService
  246. //
  247. // Synopsis: Start the named service
  248. //
  249. // Effects: Opens a service, if one exists
  250. //
  251. // Arguments: [in] lpwszServiceName = Name of the service to start
  252. //
  253. // Returns: 0 on success
  254. //
  255. // History: May 20, 1993 AlokS Created
  256. //
  257. // Notes: The handle of opened service is remembered and closed by
  258. // destructor
  259. //
  260. //-------------------------------------------------------------------
  261. DWORD CService::_StartService( const LPWSTR lpwszServiceName
  262. )
  263. {
  264. if (_schSCManager==NULL)
  265. {
  266. return(ERROR_INVALID_HANDLE);
  267. }
  268. DWORD dwStatus =0;
  269. if (_scHandle)
  270. _CloseService();
  271. _scHandle = OpenService ( _schSCManager,
  272. lpwszServiceName,
  273. SERVICE_START|SERVICE_QUERY_STATUS
  274. );
  275. if (_scHandle==NULL)
  276. {
  277. dwStatus = GetLastError();
  278. DSSCDebugOut(( DEB_IERROR,
  279. "Error: %lx in Opening Service: %ws\n",
  280. dwStatus,
  281. lpwszServiceName
  282. ));
  283. }
  284. else if (!StartService(_scHandle, NULL, NULL))
  285. {
  286. dwStatus = GetLastError();
  287. DSSCDebugOut(( DEB_IERROR,
  288. "Error: %lx in Starting Service: %ws\n",
  289. dwStatus,
  290. lpwszServiceName
  291. ));
  292. }
  293. return dwStatus;
  294. }
  295. //+------------------------------------------------------------------
  296. //
  297. // Member: CService::_StopService
  298. //
  299. // Synopsis: Stop the named service
  300. //
  301. // Effects: Opens a service, if one exists
  302. //
  303. // Arguments: [in] lpwszServiceName = Name of the service to stop
  304. //
  305. // Returns: 0 on success
  306. //
  307. // History: May 9, 1994 DaveStr Created
  308. //
  309. // Notes: The handle of opened service is remembered and closed by
  310. // destructor
  311. //
  312. //-------------------------------------------------------------------
  313. DWORD CService::_StopService( const LPWSTR lpwszServiceName
  314. )
  315. {
  316. SERVICE_STATUS ss;
  317. if (_schSCManager==NULL)
  318. {
  319. return(ERROR_INVALID_HANDLE);
  320. }
  321. DWORD dwStatus =0;
  322. if (_scHandle)
  323. _CloseService();
  324. _scHandle = OpenService ( _schSCManager,
  325. lpwszServiceName,
  326. SERVICE_STOP|SERVICE_QUERY_STATUS
  327. );
  328. if (_scHandle==NULL)
  329. {
  330. dwStatus = GetLastError();
  331. DSSCDebugOut(( DEB_IERROR,
  332. "Error: %lx in Opening Service: %ws\n",
  333. dwStatus,
  334. lpwszServiceName
  335. ));
  336. }
  337. else if (!ControlService(_scHandle, SERVICE_CONTROL_STOP, &ss))
  338. {
  339. dwStatus = GetLastError();
  340. DSSCDebugOut(( DEB_IERROR,
  341. "Error: %lx in Controlling (stopping) Service: %ws\n",
  342. dwStatus,
  343. lpwszServiceName
  344. ));
  345. }
  346. return dwStatus;
  347. }
  348. //+------------------------------------------------------------------
  349. //
  350. // Member: CService::_DeleteService
  351. //
  352. // Synopsis: Remove the named service
  353. //
  354. // Effects: Deletes a service, if one exists
  355. //
  356. // Arguments: [in] lpwszServiceName = Name of the service to remove
  357. //
  358. // Returns: 0 on success
  359. //
  360. // History: May 20, 1993 AlokS Created
  361. //
  362. // Notes:
  363. //
  364. //
  365. //-------------------------------------------------------------------
  366. DWORD CService::_DeleteService( const LPWSTR lpwszServiceName )
  367. {
  368. DWORD dwStatus;
  369. // Open the service
  370. dwStatus = _OpenService(lpwszServiceName,
  371. SERVICE_CHANGE_CONFIG|
  372. DELETE
  373. );
  374. if (!dwStatus)
  375. {
  376. // We have a handle to the existing service. So, delete it.
  377. if (!DeleteService ( _scHandle))
  378. {
  379. dwStatus = GetLastError();
  380. DSSCDebugOut(( DEB_IERROR,
  381. "Error: %lx in DeleteService: %ws\n",
  382. dwStatus,
  383. lpwszServiceName
  384. ));
  385. _CloseService();
  386. }
  387. }
  388. return dwStatus;
  389. }
  390. //+------------------------------------------------------------------
  391. //
  392. // Member: CService::_DisableService
  393. //
  394. // Synopsis: Disable the named service
  395. //
  396. // Effects: Disables a service, if one exists
  397. //
  398. // Arguments: [in] lpwszServiceName = Name of the service to disable
  399. //
  400. // Returns: 0 on success
  401. //
  402. // History: Dec 8, 1993 AlokS Created
  403. //
  404. // Notes:
  405. //
  406. //
  407. //-------------------------------------------------------------------
  408. DWORD CService::_DisableService( const LPWSTR lpwszServiceName )
  409. {
  410. DWORD dwStatus;
  411. // Open the service
  412. dwStatus = _OpenService(lpwszServiceName,
  413. SERVICE_CHANGE_CONFIG
  414. );
  415. if (!dwStatus)
  416. {
  417. // We have a handle to the existing service. So, delete it.
  418. if (!ChangeServiceConfig ( _scHandle, // Handle
  419. SERVICE_NO_CHANGE, // Type
  420. SERVICE_DISABLED, // Start
  421. SERVICE_NO_CHANGE, // Error
  422. NULL, // Path
  423. NULL, // Load order
  424. NULL, // Tag
  425. NULL, // Depend
  426. NULL, // Start name
  427. NULL, // Password
  428. NULL // Display Name
  429. ))
  430. {
  431. dwStatus = GetLastError();
  432. DSSCDebugOut(( DEB_IERROR,
  433. "Error: %lx in ChangeService: %ws\n",
  434. dwStatus,
  435. lpwszServiceName
  436. ));
  437. _CloseService();
  438. }
  439. }
  440. return dwStatus;
  441. }
  442. //+------------------------------------------------------------------
  443. //
  444. // Member: CService::_CloseService
  445. //
  446. // Synopsis: Close a service for which we have an open handle
  447. //
  448. // Effects: Close service handle, if opened previously
  449. //
  450. // Arguments: -none-
  451. //
  452. // Returns: 0 on success
  453. //
  454. // History: May 20, 1993 AlokS Created
  455. //
  456. // Notes:
  457. //
  458. //
  459. //-------------------------------------------------------------------
  460. void CService::_CloseService( )
  461. {
  462. if (_scHandle != NULL)
  463. CloseServiceHandle ( _scHandle);
  464. _scHandle = NULL;
  465. }
  466. //+------------------------------------------------------------------
  467. //
  468. // Member: CService::_QueryServiceStatus
  469. //
  470. // Synopsis: query current service status
  471. //
  472. // Effects: none
  473. //
  474. // Arguments: service_status - service status structure.
  475. //
  476. // Returns: 0 on success
  477. //
  478. // History: May 20, 1993 AlokS Created
  479. //
  480. // Notes:
  481. //
  482. //
  483. //-------------------------------------------------------------------
  484. DWORD CService::_QueryServiceStatus(LPSERVICE_STATUS ss)
  485. {
  486. if (_scHandle != NULL) {
  487. if (!QueryServiceStatus(_scHandle, ss))
  488. return(GetLastError());
  489. return(0);
  490. }
  491. return(ERROR_INVALID_HANDLE);
  492. }
  493. //+------------------------------------------------------------------
  494. //
  495. // Member: CService::ConfigService
  496. //
  497. // Synopsis: Create else Open/Change the named Service
  498. //
  499. // Effects: It first tries to create a service. If one exists already,
  500. // it changes the configuration to new configuration.
  501. //
  502. // Arguments: Lots of them. See documentation on CreateService() API.
  503. //
  504. // Returns: 0 on success
  505. //
  506. // History: May 20, 1993 AlokS Created
  507. //
  508. // Notes: Most people should use this method only for setting up services
  509. //
  510. // MAJOR NOTE: It is essential that all the keys being asked to change
  511. // be actually present before they can be changed
  512. //
  513. //
  514. //
  515. //-------------------------------------------------------------------
  516. WCHAR MsgBuf[0x1000];
  517. DWORD CService::_ConfigService( DWORD fdwServiceType,
  518. DWORD fdwStartType,
  519. DWORD fdwErrorControl,
  520. const LPWSTR lpwszBinaryPathName,
  521. const LPWSTR lpwszLoadOrderGroup,
  522. const LPWSTR lpwszDependencies,
  523. const LPWSTR lpwszServiceStartName,
  524. const LPWSTR lpwszPassword,
  525. const LPWSTR lpwszDisplayName,
  526. const LPWSTR lpwszServiceName
  527. )
  528. {
  529. if (_schSCManager==NULL)
  530. {
  531. return(ERROR_INVALID_HANDLE);
  532. }
  533. DWORD dwStatus = ERROR_SERVICE_DATABASE_LOCKED;
  534. SC_LOCK scLock;
  535. //
  536. // Let us lock the database. There could be a problem here
  537. // because the service controller also locks the database when
  538. // starting a service so it reads the startup parameters properly.
  539. // If this is the case, and the database is locked, we just try
  540. // up to 5 times to lock it ourselves before we fail.
  541. //
  542. for ( ULONG tries = 0;
  543. (tries < 5) && (dwStatus == ERROR_SERVICE_DATABASE_LOCKED);
  544. tries++ )
  545. {
  546. scLock = LockServiceDatabase (_schSCManager);
  547. if ( scLock == NULL )
  548. {
  549. dwStatus = GetLastError();
  550. DSSCDebugOut((DEB_ERROR, "LockServiceDatabase(try %d) == %#0x\n",
  551. tries, dwStatus));
  552. if ( dwStatus == ERROR_SERVICE_DATABASE_LOCKED )
  553. {
  554. Sleep ( 2 * 1000 );
  555. }
  556. }
  557. else
  558. {
  559. dwStatus = 0;
  560. }
  561. }
  562. if ( dwStatus != 0 )
  563. {
  564. return dwStatus;
  565. }
  566. // First, we try to create the service.
  567. dwStatus = _CreateService(
  568. lpwszServiceName,
  569. lpwszDisplayName,
  570. GENERIC_WRITE, // Access
  571. fdwServiceType,
  572. fdwStartType,
  573. fdwErrorControl,
  574. lpwszBinaryPathName,
  575. lpwszLoadOrderGroup,
  576. NULL, // Tag ID
  577. lpwszDependencies,
  578. lpwszServiceStartName,
  579. lpwszPassword
  580. );
  581. // It is possible that service exists
  582. if ((dwStatus == ERROR_SERVICE_EXISTS) ||
  583. (dwStatus == ERROR_DUP_NAME))
  584. {
  585. // Open the service
  586. dwStatus = _OpenService(lpwszServiceName,
  587. SERVICE_CHANGE_CONFIG|DELETE);
  588. if (!dwStatus) {
  589. if (!ChangeServiceConfig(_scHandle,
  590. fdwServiceType,
  591. fdwStartType,
  592. fdwErrorControl,
  593. lpwszBinaryPathName,
  594. lpwszLoadOrderGroup,
  595. NULL,
  596. lpwszDependencies,
  597. lpwszServiceStartName,
  598. lpwszPassword,
  599. lpwszDisplayName
  600. )) {
  601. //
  602. // Change didn't work, lets try to delete and recreate this
  603. // service.
  604. //
  605. dwStatus = 0;
  606. if (!DeleteService ( _scHandle)) {
  607. // This is hopeless. Let us give up now
  608. dwStatus = GetLastError();
  609. DSSCDebugOut(( DEB_IERROR,
  610. "Error: %lx in DeleteService: %ws\n",
  611. dwStatus,
  612. lpwszServiceName));
  613. }
  614. _CloseService();
  615. if (!dwStatus) {
  616. // last attempt to create
  617. dwStatus = _CreateService(
  618. lpwszServiceName,
  619. lpwszDisplayName,
  620. GENERIC_WRITE, // Access
  621. fdwServiceType,
  622. fdwStartType,
  623. fdwErrorControl,
  624. lpwszBinaryPathName,
  625. lpwszLoadOrderGroup,
  626. NULL, // Tag ID
  627. lpwszDependencies,
  628. lpwszServiceStartName,
  629. lpwszPassword
  630. );
  631. DSSCDebugOut(( DEB_IERROR,
  632. "This is hopeless. Recreating failed!!\n"));
  633. }
  634. }
  635. } // OpenService
  636. } // CreateService
  637. //
  638. // Set description
  639. //
  640. if (dwStatus == ERROR_SUCCESS) {
  641. SERVICE_DESCRIPTION ServiceDescription;
  642. // Open the service if the above did not
  643. if (_scHandle == NULL) {
  644. dwStatus = _OpenService(
  645. lpwszServiceName,
  646. SERVICE_CHANGE_CONFIG);
  647. }
  648. if (dwStatus == ERROR_SUCCESS) {
  649. ULONG i;
  650. MyFormatMessage(MSG_DFS_DESCRIPTION, MsgBuf, sizeof(MsgBuf));
  651. for (i = 0; MsgBuf[i] != UNICODE_NULL && i < (sizeof(MsgBuf)/sizeof(WCHAR)); i++) {
  652. if (MsgBuf[i] == L'\r')
  653. MsgBuf[i] = UNICODE_NULL;
  654. else if (MsgBuf[i] == L'\n')
  655. MsgBuf[i] = UNICODE_NULL;
  656. }
  657. ServiceDescription.lpDescription = MsgBuf;
  658. dwStatus = ChangeServiceConfig2(
  659. _scHandle,
  660. SERVICE_CONFIG_DESCRIPTION, // InfoLevel
  661. &ServiceDescription);
  662. dwStatus = (dwStatus != 0) ? ERROR_SUCCESS : GetLastError();
  663. }
  664. }
  665. _CloseService();
  666. UnlockServiceDatabase ( scLock);
  667. return dwStatus;
  668. }
  669. //+------------------------------------------------------------------
  670. //
  671. // Function: _StartService
  672. //
  673. // Synopsis:
  674. //
  675. // Effects: Starts the Service and any other
  676. // service dependent on it. It also ensures that the
  677. // service has started befor returning.
  678. //
  679. // Arguments: [pwsz] -- name of the service to be started
  680. //
  681. // Returns: 0 on success
  682. //
  683. // History: Nov 12, 1993 AlokS Created
  684. //
  685. // Notes: This code was borrowed from the original StartDfs code
  686. // written by Aloks and parameterized to allow other
  687. // services to be started. An interesting question is
  688. // whether this should be made a method of CDSSvc class.
  689. // (TBD by AlokS)
  690. //
  691. //-------------------------------------------------------------------
  692. DWORD _SynchStartService(WCHAR *pwszServiceName)
  693. {
  694. DWORD dwRc;
  695. // Open Service Controller
  696. CService cSvc;
  697. if ((dwRc = cSvc.Init())== ERROR_SUCCESS)
  698. {
  699. // Start the Service
  700. dwRc = cSvc._StartService(pwszServiceName);
  701. if (dwRc == ERROR_SERVICE_ALREADY_RUNNING)
  702. {
  703. // We are done!
  704. return ( ERROR_SUCCESS );
  705. }
  706. }
  707. if (dwRc)
  708. {
  709. DSSCDebugOut((DEB_IERROR, "Error starting: %ws\n",pwszServiceName));
  710. return(dwRc);
  711. }
  712. // Wait for the service to start running
  713. SERVICE_STATUS scStatus;
  714. DWORD MaxTries = 0;
  715. do
  716. {
  717. if (!QueryServiceStatus(cSvc.QueryService(),
  718. &scStatus
  719. ))
  720. {
  721. dwRc = GetLastError();
  722. DSSCDebugOut((DEB_IERROR, "Error Querying service\n"));
  723. break;
  724. }
  725. else if (scStatus.dwCurrentState != SERVICE_RUNNING)
  726. {
  727. Sleep(SERVICE_WAIT_TIME);
  728. MaxTries++;
  729. }
  730. } while ( scStatus.dwCurrentState != SERVICE_RUNNING && MaxTries < MAX_SERVICE_WAIT_RETRIES);
  731. if (MaxTries == MAX_SERVICE_WAIT_RETRIES)
  732. {
  733. dwRc = ERROR_SERVICE_REQUEST_TIMEOUT;
  734. }
  735. return(dwRc);
  736. }
  737. //+------------------------------------------------------------------
  738. //
  739. // Function: ConfigDfs
  740. //
  741. // Synopsis:
  742. //
  743. // Effects: Configures DFS File System Driver
  744. //
  745. // Arguments: -none-
  746. //
  747. // Returns: 0 on success
  748. //
  749. // History: May 20, 1993 AlokS Created
  750. //
  751. // Notes:
  752. //
  753. //-------------------------------------------------------------------
  754. DWORD ConfigDfs()
  755. {
  756. DWORD dwErr = ERROR_SUCCESS;
  757. // Open Service Controller
  758. CService cSvc;
  759. if (dwErr = cSvc.Init())
  760. return dwErr;
  761. // Create DFS (Driver)
  762. dwErr = cSvc._ConfigService(
  763. SERVICE_FILE_SYSTEM_DRIVER, // Service Type
  764. SERVICE_BOOT_START, // Start Type
  765. SERVICE_ERROR_NORMAL, // Error Control
  766. // service file
  767. L"\\SystemRoot\\system32\\drivers\\Dfs.sys",
  768. L"filter", // Load order group
  769. NULL, // Dependency
  770. NULL, // Service start name
  771. NULL, // password
  772. L"DfsDriver", // display name
  773. L"DfsDriver" // Service Name
  774. );
  775. if (dwErr)
  776. return dwErr;
  777. //
  778. // Registry Changes
  779. //
  780. //
  781. // Fix up the NetworkProvider order level - delete the Dfs provider
  782. // if one has been inserted there
  783. //
  784. if (dwErr == ERROR_SUCCESS) {
  785. CRegKey cregNP( HKEY_LOCAL_MACHINE,
  786. L"System\\CurrentControlSet\\Control\\NetworkProvider\\Order",
  787. KEY_READ | KEY_WRITE,
  788. NULL,
  789. REG_OPTION_NON_VOLATILE);
  790. dwErr = cregNP.QueryErrorStatus();
  791. if (dwErr == ERROR_SUCCESS) {
  792. CRegSZ cregOrder( cregNP, L"ProviderOrder" );
  793. dwErr = cregOrder.QueryErrorStatus();
  794. if (dwErr == ERROR_SUCCESS) {
  795. WCHAR wszProviders[128];
  796. WCHAR *pwszProviders = wszProviders;
  797. PWCHAR pwszDfs;
  798. ULONG cbProviders = sizeof(wszProviders);
  799. dwErr = cregOrder.GetString( pwszProviders, &cbProviders );
  800. if (dwErr == ERROR_MORE_DATA) {
  801. pwszProviders = new WCHAR[ cbProviders / sizeof(WCHAR) ];
  802. if (pwszProviders == NULL) {
  803. dwErr = ERROR_OUTOFMEMORY;
  804. } else {
  805. dwErr = cregOrder.GetString( pwszProviders, &cbProviders );
  806. }
  807. }
  808. if (dwErr == ERROR_SUCCESS) {
  809. //
  810. // Delete Dfs only if its not already there.
  811. //
  812. pwszDfs = wcsstr(pwszProviders, L"Dfs,");
  813. if (pwszDfs != NULL) {
  814. *pwszDfs = UNICODE_NULL;
  815. wcscat( pwszProviders, pwszDfs + 4);
  816. dwErr = cregOrder.SetString( pwszProviders );
  817. }
  818. }
  819. if (pwszProviders != wszProviders && pwszProviders != NULL) {
  820. delete [] pwszProviders;
  821. }
  822. }
  823. }
  824. }
  825. //
  826. // Cleanup the LocalVolumes section
  827. //
  828. if (dwErr == ERROR_SUCCESS) {
  829. CRegKey cregLV( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES );
  830. dwErr = cregLV.QueryErrorStatus();
  831. if (dwErr == ERROR_SUCCESS) {
  832. dwErr = cregLV.DeleteChildren();
  833. }
  834. }
  835. if (dwErr == ERROR_SUCCESS) {
  836. dwErr = RegDeleteKey( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES );
  837. }
  838. //
  839. // Create an empty local volumes section
  840. //
  841. if (dwErr == ERROR_SUCCESS) {
  842. CRegKey cregLV( HKEY_LOCAL_MACHINE, REG_KEY_LOCAL_VOLUMES );
  843. dwErr = cregLV.QueryErrorStatus();
  844. }
  845. //
  846. // Add DfsInit to be run after autocheck...
  847. //
  848. if (dwErr == ERROR_SUCCESS) {
  849. CRegKey cregSM( HKEY_LOCAL_MACHINE,
  850. L"SYSTEM\\CurrentControlSet\\Control\\Session Manager",
  851. KEY_ALL_ACCESS);
  852. dwErr = cregSM.QueryErrorStatus();
  853. if (dwErr == ERROR_SUCCESS) {
  854. CRegMSZ cregBootExec( cregSM, L"BootExecute" );
  855. dwErr = cregBootExec.QueryErrorStatus();
  856. if (dwErr == ERROR_SUCCESS) {
  857. WCHAR wszBootExec[128];
  858. DWORD cbBootExec = sizeof(wszBootExec);
  859. LPWSTR pwszNextString;
  860. dwErr = cregBootExec.GetString(
  861. wszBootExec,
  862. &cbBootExec);
  863. if (dwErr == ERROR_SUCCESS) {
  864. for (pwszNextString = wszBootExec;
  865. *pwszNextString != UNICODE_NULL &&
  866. (_wcsicmp(pwszNextString, L"DfsInit") != 0);
  867. pwszNextString += (wcslen(pwszNextString)
  868. + 1)) {
  869. ;
  870. }
  871. if (*pwszNextString == UNICODE_NULL) {
  872. wcscpy(pwszNextString, L"DfsInit");
  873. pwszNextString += (sizeof(L"DfsInit") / sizeof(WCHAR));
  874. *pwszNextString = UNICODE_NULL;
  875. cregBootExec.SetString(wszBootExec);
  876. }
  877. }
  878. }
  879. }
  880. // even if we didn't find BootExecute, we want to continue
  881. // with setting up the registry. So return success.
  882. dwErr = ERROR_SUCCESS;
  883. }
  884. // Now Add value so that we recognize that this is the ds version of dfs.
  885. return dwErr;
  886. }
  887. //+------------------------------------------------------------------
  888. //
  889. // Function: StartDfs
  890. //
  891. // Synopsis:
  892. //
  893. // Effects: Starts out the DFS Service.
  894. //
  895. // Arguments: -none-
  896. //
  897. // Returns: 0 on success
  898. //
  899. // History: Nov 12, 1993 AlokS Created
  900. //
  901. // Notes:
  902. //
  903. //-------------------------------------------------------------------
  904. DWORD StartDfs (
  905. GUID *pguidDomain,
  906. PWSTR pwszDomain
  907. )
  908. {
  909. DWORD dwRc;
  910. //
  911. // We load the dfs driver and then call FindDomainController. This
  912. // call to FindDomainController is expected to seed the Dfs driver
  913. // with domain info.
  914. //
  915. dwRc = _SynchStartService(L"Dfs");
  916. return(dwRc);
  917. }
  918. //+------------------------------------------------------------------
  919. //
  920. // Function: RemoveDfs
  921. //
  922. // Synopsis:
  923. //
  924. // Effects: Remove DFS driver
  925. //
  926. //-------------------------------------------------------------------
  927. DWORD
  928. RemoveDfs(void)
  929. {
  930. //DbgCommonApiTrace(RemoveDfs);
  931. DWORD dwErr = ERROR_SUCCESS;
  932. // Open Service Controller
  933. CService cSvc;
  934. if (!(dwErr = cSvc.Init()))
  935. {
  936. // Disable DFS driver
  937. dwErr = cSvc._DisableService(L"Dfs");
  938. }
  939. if (dwErr)
  940. {
  941. return(dwErr);
  942. }
  943. /*
  944. * Registry Changes
  945. */
  946. // Now, we remove entries under DFS entry in registry
  947. //
  948. // Remove Dfs from the NetworkProvider list
  949. //
  950. if (dwErr == ERROR_SUCCESS) {
  951. CRegKey cregNP( HKEY_LOCAL_MACHINE,
  952. L"System\\CurrentControlSet\\Control\\NetworkProvider\\Order",
  953. KEY_READ | KEY_WRITE,
  954. NULL,
  955. REG_OPTION_NON_VOLATILE);
  956. dwErr = cregNP.QueryErrorStatus();
  957. if (dwErr == ERROR_SUCCESS) {
  958. CRegSZ cregOrder( cregNP, L"ProviderOrder" );
  959. dwErr = cregOrder.QueryErrorStatus();
  960. if (dwErr == ERROR_SUCCESS) {
  961. WCHAR wszProviders[128];
  962. WCHAR *pwszProviders = wszProviders;
  963. WCHAR *pwszDfs, *pwszAfterDfs;
  964. ULONG cbProviders = sizeof(wszProviders);
  965. dwErr = cregOrder.GetString( pwszProviders, &cbProviders );
  966. if (dwErr == ERROR_MORE_DATA) {
  967. pwszProviders = new WCHAR[ cbProviders / sizeof(WCHAR) ];
  968. if (pwszProviders == NULL) {
  969. dwErr = ERROR_OUTOFMEMORY;
  970. } else {
  971. dwErr = cregOrder.GetString( pwszProviders, &cbProviders );
  972. }
  973. }
  974. if (dwErr == ERROR_SUCCESS) {
  975. //
  976. // Delete Dfs only if its there.
  977. //
  978. pwszDfs = wcsstr(pwszProviders, L"Dfs,");
  979. if (pwszDfs != NULL) {
  980. pwszAfterDfs = pwszDfs + wcslen(L"Dfs,");
  981. memmove(
  982. (PVOID) pwszDfs,
  983. (PVOID) pwszAfterDfs,
  984. (wcslen( pwszAfterDfs ) + 1) * sizeof(WCHAR));
  985. dwErr = cregOrder.SetString( pwszProviders );
  986. }
  987. }
  988. if (pwszProviders != wszProviders && pwszProviders != NULL) {
  989. delete [] pwszProviders;
  990. }
  991. }
  992. }
  993. }
  994. return dwErr ;
  995. }
  996. //+------------------------------------------------------------------
  997. //
  998. // Function: ConfigDfsService
  999. //
  1000. // Synopsis:
  1001. //
  1002. // Effects: Configures Dfs Service
  1003. //
  1004. //-------------------------------------------------------------------
  1005. DWORD
  1006. ConfigDfsService()
  1007. {
  1008. DWORD dwErr = 0;
  1009. ULONG i;
  1010. // Open Service Controller
  1011. CService cSvc;
  1012. if (dwErr = cSvc.Init())
  1013. return dwErr;
  1014. //
  1015. // Get localizable name of service
  1016. //
  1017. MyFormatMessage(MSG_DFS_COMPONENT_NAME, MsgBuf, sizeof(MsgBuf));
  1018. for (i = 0; MsgBuf[i] != UNICODE_NULL && i < (sizeof(MsgBuf)/sizeof(WCHAR)); i++) {
  1019. if (MsgBuf[i] == L'\r')
  1020. MsgBuf[i] = UNICODE_NULL;
  1021. else if (MsgBuf[i] == L'\n')
  1022. MsgBuf[i] = UNICODE_NULL;
  1023. }
  1024. // Create entry for Dfs Manager
  1025. dwErr = cSvc._ConfigService(
  1026. SERVICE_WIN32_OWN_PROCESS, // Service Type
  1027. SERVICE_AUTO_START, // Start Type
  1028. SERVICE_ERROR_NORMAL, // Error Control
  1029. L"%SystemRoot%\\system32\\Dfssvc.exe", // service binary
  1030. L"Dfs", // Load order group
  1031. L"LanmanWorkstation\0LanmanServer\0DfsDriver\0Mup\0", // Dependency
  1032. NULL, // Logon Name
  1033. NULL, // Logon Password
  1034. MsgBuf, // display name
  1035. L"Dfs" // Service Name
  1036. );
  1037. if (dwErr == ERROR_SUCCESS) {
  1038. CRegKey cregDfs( HKEY_LOCAL_MACHINE,
  1039. &dwErr,
  1040. L"System\\CurrentControlSet\\Services\\Dfs"
  1041. );
  1042. if (dwErr == ERROR_SUCCESS) {
  1043. CRegDWORD DfsVer ((const CRegKey &)cregDfs, L"DfsVersion",
  1044. DFS_VERSION_NUMBER);
  1045. dwErr = DfsVer.QueryErrorStatus();
  1046. }
  1047. }
  1048. return dwErr ;
  1049. }
  1050. //+------------------------------------------------------------------
  1051. //
  1052. // Function: RemoveDfsService
  1053. //
  1054. // Synopsis:
  1055. //
  1056. // Effects: Remove Dfs Service
  1057. //
  1058. // Arguments: -none-
  1059. //
  1060. // Returns: 0 on success
  1061. //
  1062. //
  1063. // History: May 20, 1993 AlokS Created
  1064. //
  1065. // Notes:
  1066. //
  1067. //
  1068. //-------------------------------------------------------------------
  1069. DWORD RemoveDfsService( )
  1070. {
  1071. DWORD dwErr = 0;
  1072. // Open Service Controller
  1073. CService cSvc;
  1074. if (!(dwErr = cSvc.Init()))
  1075. {
  1076. // Delete DFSManager Service
  1077. dwErr = cSvc._DeleteService(L"DfsService");
  1078. }
  1079. return dwErr ;
  1080. }