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.

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