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.

628 lines
20 KiB

  1. //----------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 2001
  3. //
  4. // File: bitscnfg.cpp
  5. //
  6. // Contents: Configure BITS client service to default settings.
  7. //
  8. // EdwardR 07/27/2001 Initial version.
  9. // 08/03/2001 Add code to fixup ServiceDLL in registry.
  10. // Add code to regsvr qmgrprxy.dll
  11. // 08/13/2001 Add code to support XP as well as Win2k.
  12. //----------------------------------------------------------------------------
  13. #define UNICODE
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #include <malloc.h>
  17. #define VER_WINDOWS_2000 500
  18. #define VER_WINDOWS_XP 501
  19. //
  20. // Service configuration settings:
  21. //
  22. #define BITS_SERVICE_NAME TEXT("BITS")
  23. #define BITS_DISPLAY_NAME TEXT("Background Intelligent Transfer Service")
  24. #define BITS_BINARY_PATH TEXT("%SystemRoot%\\System32\\svchost.exe -k BITSgroup")
  25. #define BITS_LOAD_ORDER_GROUP TEXT("BITSgroup")
  26. #define BITS_SERVICE_TYPE SERVICE_WIN32_SHARE_PROCESS
  27. #define BITS_START_TYPE SERVICE_DEMAND_START
  28. #define BITS_ERROR_CONTROL SERVICE_ERROR_NORMAL
  29. //
  30. // This additional service registry setting is set incorrectly by the
  31. // Darwin install
  32. //
  33. #define REG_SERVICE_PATH TEXT("SYSTEM\\CurrentControlSet\\Services\\BITS")
  34. #define REG_PARAMETERS TEXT("Parameters")
  35. #define REG_SERVICEDLL TEXT("ServiceDll")
  36. #define REG_SERVICEDLL_PATH TEXT("%SystemRoot%\\System32\\qmgr.dll")
  37. //
  38. // For side-by-side install on Windows XP
  39. //
  40. #define BACKSLASH_STR TEXT("\\")
  41. #define BITS_SUBDIRECTORY TEXT("BITS")
  42. #define BITS_QMGR_DLL TEXT("qmgr.dll")
  43. #define REG_BITS TEXT("BITS")
  44. #define REG_BITS_SERVICEDLL TEXT("ServiceDLL")
  45. #define REG_SERVICEDLL_KEY TEXT("Software\\Microsoft\\Windows\\CurrentVersion")
  46. //
  47. // Constants to register qmgrprxy.dll
  48. //
  49. #define BITS_QMGRPRXY_DLL TEXT("qmgrprxy.dll")
  50. #define BITS_BITS15PRXY_DLL TEXT("bitsprx2.dll")
  51. #define BITS_DLL_REGISTER_FN "DllRegisterServer"
  52. typedef HRESULT (*RegisterFn)();
  53. //
  54. // Constants for parsing bitscnfg.exe runstring arguments
  55. //
  56. #define SZ_DELIMITERS " \t"
  57. #define SZ_INSTALL "/i"
  58. #define SZ_UNINSTALL "/u"
  59. #define SZ_DELETE_SERVICE "/d"
  60. #define ACTION_INSTALL 0
  61. #define ACTION_UNINSTALL 1
  62. #define ACTION_DELETE_SERVICE 2
  63. //
  64. // Log file for testing
  65. //
  66. FILE *f = NULL;
  67. //---------------------------------------------------------------------
  68. // RegSetKeyAndValue()
  69. //
  70. // Helper function to create a key, sets a value in the key,
  71. // then close the key.
  72. //
  73. // Parameters:
  74. // pwsKey WCHAR* The name of the key
  75. // pwsSubkey WCHAR* The name of a subkey
  76. // pwsValueName WCHAR* The value name.
  77. // pwsValue WCHAR* The data value to store
  78. // dwType The type for the new registry value.
  79. // dwDataSize The size for non-REG_SZ registry entry types.
  80. //
  81. // Return:
  82. // BOOL TRUE if successful, FALSE otherwise.
  83. //---------------------------------------------------------------------
  84. DWORD RegSetKeyAndValue( const WCHAR *pwsKey,
  85. const WCHAR *pwsSubKey,
  86. const WCHAR *pwsValueName,
  87. const WCHAR *pwsValue,
  88. const DWORD dwType = REG_SZ,
  89. DWORD dwDataSize = 0,
  90. BOOL fReCreate = TRUE )
  91. {
  92. HKEY hKey;
  93. DWORD dwStatus;
  94. DWORD dwSize = 0;
  95. WCHAR *pwsCompleteKey;
  96. if (pwsKey)
  97. dwSize = wcslen(pwsKey);
  98. if (pwsSubKey)
  99. dwSize += wcslen(pwsSubKey);
  100. dwSize = (1+1+dwSize)*sizeof(WCHAR); // Extra +1 for the backslash...
  101. pwsCompleteKey = (WCHAR*)_alloca(dwSize);
  102. wcscpy(pwsCompleteKey,pwsKey);
  103. if (NULL!=pwsSubKey)
  104. {
  105. wcscat(pwsCompleteKey, BACKSLASH_STR);
  106. wcscat(pwsCompleteKey, pwsSubKey);
  107. }
  108. // If the key is already there then delete it, we will recreate it.
  109. if (fReCreate)
  110. {
  111. dwStatus = RegDeleteKey( HKEY_LOCAL_MACHINE,
  112. pwsCompleteKey );
  113. }
  114. dwStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
  115. pwsCompleteKey,
  116. 0,
  117. NULL,
  118. REG_OPTION_NON_VOLATILE,
  119. KEY_ALL_ACCESS,
  120. NULL,
  121. &hKey,
  122. NULL );
  123. if (dwStatus != ERROR_SUCCESS)
  124. {
  125. return dwStatus;
  126. }
  127. if (pwsValue)
  128. {
  129. if ((dwType == REG_SZ)||(dwType == REG_EXPAND_SZ))
  130. dwDataSize = (1+wcslen(pwsValue))*sizeof(WCHAR);
  131. RegSetValueEx( hKey,
  132. pwsValueName, 0, dwType, (BYTE *)pwsValue, dwDataSize );
  133. }
  134. else
  135. {
  136. RegSetValueEx( hKey,
  137. pwsValueName, 0, dwType, (BYTE *)pwsValue, 0 );
  138. }
  139. RegCloseKey(hKey);
  140. return dwStatus;
  141. }
  142. //-------------------------------------------------------------------------
  143. // RegDeleteKeyOrValue()
  144. //
  145. // Delete either the specified sub-key or delete the specified value
  146. // within the sub-key. If pwszValueName is specified, the just delete
  147. // it and leave the key alone. If pwszValueName is NULL, then delete
  148. // the key.
  149. //-------------------------------------------------------------------------
  150. DWORD RegDeleteKeyOrValue( IN const WCHAR *pwszKey,
  151. IN const WCHAR *pwszSubKey,
  152. IN const WCHAR *pwszValueName )
  153. {
  154. LONG lStatus = 0;
  155. DWORD dwLen;
  156. DWORD dwSize;
  157. HKEY hKey;
  158. WCHAR *pwszCompleteKey;
  159. if (!pwszKey || !pwszSubKey)
  160. {
  161. return lStatus;
  162. }
  163. dwLen = wcslen(pwszKey) + wcslen(pwszSubKey) + 2;
  164. dwSize = dwLen * sizeof(WCHAR);
  165. pwszCompleteKey = (WCHAR*)_alloca(dwSize);
  166. wcscpy(pwszCompleteKey,pwszKey);
  167. wcscat(pwszCompleteKey,BACKSLASH_STR);
  168. wcscat(pwszCompleteKey,pwszSubKey);
  169. if (pwszValueName)
  170. {
  171. // Delete a value in a key:
  172. if (f) fwprintf(f,TEXT("Delete Reg Value: %s : %s\n"),pwszCompleteKey,pwszValueName);
  173. lStatus = RegOpenKey(HKEY_LOCAL_MACHINE,pwszCompleteKey,&hKey);
  174. if (lStatus == ERROR_SUCCESS)
  175. {
  176. lStatus = RegDeleteValue(hKey,pwszValueName);
  177. RegCloseKey(hKey);
  178. }
  179. }
  180. else
  181. {
  182. // Delete the specified key:
  183. if (f) fwprintf(f,TEXT("Delete Reg Key: %s\n"),pwszCompleteKey);
  184. lStatus = RegDeleteKey(HKEY_LOCAL_MACHINE,pwszCompleteKey);
  185. }
  186. return lStatus;
  187. }
  188. //-------------------------------------------------------------------------
  189. // RegisterDLL()
  190. //
  191. //-------------------------------------------------------------------------
  192. DWORD RegisterDLL( IN WCHAR *pwszSubdirectory,
  193. IN WCHAR *pwszDllName )
  194. {
  195. DWORD dwStatus = 0;
  196. HMODULE hModule;
  197. RegisterFn pRegisterFn;
  198. UINT nChars;
  199. WCHAR wszDllPath[MAX_PATH+1];
  200. WCHAR wszSystemDirectory[MAX_PATH+1];
  201. if (pwszSubdirectory)
  202. {
  203. nChars = GetSystemDirectory(wszSystemDirectory,MAX_PATH);
  204. if ( (nChars > MAX_PATH)
  205. || (MAX_PATH < (3+wcslen(wszSystemDirectory)+wcslen(BITS_SUBDIRECTORY)+wcslen(pwszDllName))) )
  206. {
  207. return ERROR_BUFFER_OVERFLOW;
  208. }
  209. wcscpy(wszDllPath,wszSystemDirectory);
  210. wcscat(wszDllPath,BACKSLASH_STR);
  211. wcscat(wszDllPath,pwszSubdirectory);
  212. wcscat(wszDllPath,BACKSLASH_STR);
  213. wcscat(wszDllPath,pwszDllName);
  214. }
  215. else
  216. {
  217. if (MAX_PATH < wcslen(pwszDllName))
  218. {
  219. return ERROR_BUFFER_OVERFLOW;
  220. }
  221. wcscpy(wszDllPath,pwszDllName);
  222. }
  223. hModule = LoadLibrary(wszDllPath);
  224. if (!hModule)
  225. {
  226. dwStatus = GetLastError();
  227. return dwStatus;
  228. }
  229. pRegisterFn = (RegisterFn)GetProcAddress(hModule,BITS_DLL_REGISTER_FN);
  230. if (!pRegisterFn)
  231. {
  232. dwStatus = GetLastError();
  233. FreeLibrary(hModule);
  234. return dwStatus;
  235. }
  236. dwStatus = pRegisterFn();
  237. FreeLibrary(hModule);
  238. return dwStatus;
  239. }
  240. //-------------------------------------------------------------------------
  241. // ParseCmdLine()
  242. //
  243. //-------------------------------------------------------------------------
  244. void ParseCmdLine( LPSTR pszCmdLine,
  245. DWORD *pdwAction )
  246. {
  247. CHAR *pszTemp = pszCmdLine;
  248. CHAR *pszArg;
  249. BOOL fFirstTime = TRUE;
  250. *pdwAction = ACTION_INSTALL; // default is install.
  251. while (pszArg=strtok(pszTemp,SZ_DELIMITERS))
  252. {
  253. if (fFirstTime)
  254. {
  255. fFirstTime = FALSE;
  256. pszTemp = NULL;
  257. continue; // Skip over program name...
  258. }
  259. if (!_stricmp(pszArg,SZ_INSTALL))
  260. {
  261. *pdwAction = ACTION_INSTALL;
  262. if (f) fwprintf(f,TEXT("Install: %S\n"),SZ_INSTALL);
  263. }
  264. if (!_stricmp(pszArg,SZ_UNINSTALL))
  265. {
  266. *pdwAction = ACTION_UNINSTALL;
  267. if (f) fwprintf(f,TEXT("Uninstall: %S\n"),SZ_UNINSTALL);
  268. }
  269. if (!_stricmp(pszArg,SZ_DELETE_SERVICE))
  270. {
  271. *pdwAction = ACTION_DELETE_SERVICE;
  272. if (f) fwprintf(f,TEXT("DeleteService: %S\n"),SZ_UNINSTALL);
  273. }
  274. }
  275. }
  276. //-------------------------------------------------------------------------
  277. // DoInstall()
  278. //-------------------------------------------------------------------------
  279. DWORD DoInstall( DWORD dwOsVersion )
  280. {
  281. SC_HANDLE hSCM = NULL;
  282. SC_HANDLE hService = NULL;
  283. DWORD dwStatus = 0;
  284. UINT nChars;
  285. WCHAR wszQmgrPath[MAX_PATH+1];
  286. WCHAR wszSystemDirectory[MAX_PATH+1];
  287. //
  288. // Cleanup the service configuration:
  289. //
  290. if (dwOsVersion == VER_WINDOWS_2000)
  291. {
  292. hSCM = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);
  293. if (hSCM == NULL)
  294. {
  295. dwStatus = GetLastError();
  296. if (f) fwprintf(f,TEXT("OpenSCManager(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  297. goto error;
  298. }
  299. if (f) fwprintf(f,TEXT("Configuring BITS Service... \n"));
  300. hService = OpenService(hSCM,BITS_SERVICE_NAME,SERVICE_CHANGE_CONFIG);
  301. if (hService == NULL)
  302. {
  303. dwStatus = GetLastError();
  304. if (f) fwprintf(f,TEXT("OpenService(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  305. goto error;
  306. }
  307. if (!ChangeServiceConfig(hService,
  308. BITS_SERVICE_TYPE,
  309. BITS_START_TYPE,
  310. BITS_ERROR_CONTROL,
  311. BITS_BINARY_PATH,
  312. NULL, // Load order group (not changing this).
  313. NULL, // Tag ID for load order group (not needed).
  314. // Service dependencies (this is different for Win2k )
  315. // reply on XP installer to overwrite this.
  316. TEXT("LanmanWorkstation\0Rpcss\0SENS\0Wmi\0"),
  317. NULL, // Account Name (not changing this).
  318. NULL, // Account Password (not changing this).
  319. BITS_DISPLAY_NAME))
  320. {
  321. dwStatus = GetLastError();
  322. if (f) fwprintf(f,TEXT("ChangeServiceConfig(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  323. goto error;
  324. }
  325. //
  326. // Fix the ServiceDll registry value...
  327. //
  328. if (f) fwprintf(f,TEXT("bitscnfg.exe: Fix ServiceDll entry.\n"));
  329. dwStatus = RegSetKeyAndValue( REG_SERVICE_PATH,
  330. REG_PARAMETERS,
  331. REG_SERVICEDLL,
  332. REG_SERVICEDLL_PATH,
  333. REG_EXPAND_SZ);
  334. if (dwStatus)
  335. {
  336. if (f) fwprintf(f,TEXT("RegSetKeyAndValue(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  337. goto error;
  338. }
  339. }
  340. //
  341. // Register qmgrproxy.dll
  342. //
  343. if (dwOsVersion == VER_WINDOWS_2000)
  344. {
  345. if (f) fwprintf(f,TEXT("bitscnfg.exe: Register %s.\n"),BITS_QMGRPRXY_DLL);
  346. dwStatus = RegisterDLL(NULL,BITS_QMGRPRXY_DLL);
  347. if (dwStatus != 0)
  348. {
  349. if (f) fwprintf(f,TEXT("RegisterDLL(%s): Failed: 0x%x (%d)\n"),BITS_QMGRPRXY_DLL,dwStatus,dwStatus);
  350. goto error;
  351. }
  352. }
  353. //
  354. // Register bits15prxy.dll
  355. //
  356. if ((dwOsVersion == VER_WINDOWS_2000)||(dwOsVersion == VER_WINDOWS_XP))
  357. {
  358. if (f) fwprintf(f,TEXT("bitscnfg.exe: Register %s.\n"),BITS_BITS15PRXY_DLL);
  359. dwStatus = RegisterDLL(BITS_SUBDIRECTORY,BITS_BITS15PRXY_DLL);
  360. if (dwStatus != 0)
  361. {
  362. if (f) fwprintf(f,TEXT("RegisterDLL(%s): Failed: 0x%x (%d)\n"),BITS_BITS15PRXY_DLL,dwStatus,dwStatus);
  363. goto error;
  364. }
  365. }
  366. //
  367. // Configure WindowsXP BITS to run V1.5 qmgr.dll. This is also configured on Windows2000 systems to ready
  368. // it in case the system is upgraded to WindowsXP. This is done because there is no Migrate.dll to go from
  369. // Windows2000 to WindowsXP.
  370. //
  371. if ((dwOsVersion == VER_WINDOWS_2000)||(dwOsVersion == VER_WINDOWS_XP))
  372. {
  373. nChars = GetSystemDirectory(wszSystemDirectory,MAX_PATH);
  374. if ( (nChars > MAX_PATH)
  375. || (MAX_PATH < (3+wcslen(wszSystemDirectory)+wcslen(BITS_SUBDIRECTORY)+wcslen(BITS_QMGR_DLL))) )
  376. {
  377. if (f) fwprintf(f,TEXT("GetSystemDirectory(): System Path too long.\n"));
  378. goto error;
  379. }
  380. wcscpy(wszQmgrPath,wszSystemDirectory);
  381. wcscat(wszQmgrPath,BACKSLASH_STR);
  382. wcscat(wszQmgrPath,BITS_SUBDIRECTORY);
  383. wcscat(wszQmgrPath,BACKSLASH_STR);
  384. wcscat(wszQmgrPath,BITS_QMGR_DLL);
  385. if (f) fwprintf(f,TEXT("Set BITS V1.5 Override Path: %s\n"),wszQmgrPath);
  386. dwStatus = RegSetKeyAndValue( REG_SERVICEDLL_KEY,
  387. REG_BITS,
  388. REG_BITS_SERVICEDLL,
  389. wszQmgrPath,
  390. REG_SZ, 0, FALSE);
  391. if (dwStatus)
  392. {
  393. if (f) fwprintf(f,TEXT("RegSetKeyAndValue(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  394. goto error;
  395. }
  396. }
  397. error:
  398. if (hService)
  399. {
  400. CloseServiceHandle(hService);
  401. }
  402. if (hSCM)
  403. {
  404. CloseServiceHandle(hSCM);
  405. }
  406. return dwStatus;
  407. }
  408. //-------------------------------------------------------------------------
  409. // DoUninstall()
  410. //
  411. // If this is Windows2000 then delete the BITS service.
  412. //-------------------------------------------------------------------------
  413. DWORD DoUninstall( DWORD dwOsVersion )
  414. {
  415. DWORD dwStatus = 0;
  416. SC_HANDLE hSCM = NULL;
  417. SC_HANDLE hService = NULL;
  418. //
  419. // Delete the BITS thunk DLL registry entry:
  420. //
  421. if (dwOsVersion == VER_WINDOWS_2000)
  422. {
  423. // If Windows2000, then delete the BITS subkey and all its values.
  424. RegDeleteKeyOrValue( REG_SERVICEDLL_KEY,
  425. REG_BITS,
  426. NULL );
  427. }
  428. if (dwOsVersion == VER_WINDOWS_XP)
  429. {
  430. // If WindowsXP, then just delete the ServiceDLL value and leave the key and any other values.
  431. RegDeleteKeyOrValue( REG_SERVICEDLL_KEY,
  432. REG_BITS,
  433. REG_BITS_SERVICEDLL );
  434. }
  435. //
  436. // If this is Windows2000, then delete the service.
  437. //
  438. if (dwOsVersion == VER_WINDOWS_2000)
  439. {
  440. hSCM = OpenSCManager(NULL,SERVICES_ACTIVE_DATABASE,SC_MANAGER_ALL_ACCESS);
  441. if (hSCM == NULL)
  442. {
  443. dwStatus = GetLastError();
  444. if (f) fwprintf(f,TEXT("OpenSCManager(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  445. goto error;
  446. }
  447. if (f) fwprintf(f,TEXT("Configuring BITS Service... \n"));
  448. hService = OpenService(hSCM,BITS_SERVICE_NAME,SERVICE_CHANGE_CONFIG);
  449. if (hService == NULL)
  450. {
  451. dwStatus = GetLastError();
  452. if (dwStatus == ERROR_SERVICE_DOES_NOT_EXIST)
  453. {
  454. dwStatus = 0;
  455. if (f) fwprintf(f,TEXT("OpenService(): Failed: 0x%x (%d) Service doesn't exist.\n"),dwStatus,dwStatus);
  456. }
  457. else
  458. {
  459. if (f) fwprintf(f,TEXT("OpenService(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  460. }
  461. goto error;
  462. }
  463. if (!DeleteService(hService))
  464. {
  465. dwStatus = GetLastError();
  466. if (f) fwprintf(f,TEXT("DeleteService(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  467. }
  468. }
  469. error:
  470. if (hService)
  471. {
  472. CloseServiceHandle(hService);
  473. }
  474. if (hSCM)
  475. {
  476. CloseServiceHandle(hSCM);
  477. }
  478. return dwStatus;
  479. }
  480. //-------------------------------------------------------------------------
  481. // DeleteBitsService()
  482. //
  483. // Currently this is the same action as DoInstall().
  484. //-------------------------------------------------------------------------
  485. DWORD DeleteBitsService( IN DWORD dwOsVersion )
  486. {
  487. return DoUninstall( dwOsVersion );
  488. }
  489. //-------------------------------------------------------------------------
  490. // main()
  491. //
  492. //-------------------------------------------------------------------------
  493. int PASCAL WinMain( HINSTANCE hInstance,
  494. HINSTANCE hPrevInstance,
  495. LPSTR pszCmdLine,
  496. int nCmdShow )
  497. {
  498. SC_HANDLE hSCM = NULL;
  499. SC_HANDLE hService = NULL;
  500. DWORD dwAction;
  501. DWORD dwStatus;
  502. DWORD dwOsVersion;
  503. UINT nChars;
  504. WCHAR wszQmgrPath[MAX_PATH+1];
  505. WCHAR wszSystemDirectory[MAX_PATH+1];
  506. OSVERSIONINFO osVersionInfo;
  507. f = _wfopen(TEXT("c:\\temp\\bitscnfg.log"),TEXT("w"));
  508. if (f) fwprintf(f,TEXT("Runstring: %S\n"),pszCmdLine);
  509. ParseCmdLine(pszCmdLine,&dwAction);
  510. //
  511. // Get the operating system verison (Win2k == 500, XP == 501):
  512. //
  513. osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  514. if (!GetVersionEx(&osVersionInfo))
  515. {
  516. dwStatus = GetLastError();
  517. if (f) fwprintf(f,TEXT("GetVersionEx(): Failed: 0x%x (%d)\n"),dwStatus,dwStatus);
  518. goto error;
  519. }
  520. dwOsVersion = 100*osVersionInfo.dwMajorVersion + osVersionInfo.dwMinorVersion;
  521. if (f) fwprintf(f,TEXT("Windows Version: %d\n"),dwOsVersion);
  522. switch (dwAction)
  523. {
  524. case ACTION_INSTALL:
  525. dwStatus = DoInstall(dwOsVersion);
  526. break;
  527. case ACTION_UNINSTALL:
  528. dwStatus = DoUninstall(dwOsVersion);
  529. break;
  530. case ACTION_DELETE_SERVICE:
  531. dwStatus = DeleteBitsService(dwOsVersion);
  532. break;
  533. default:
  534. if (f) fwprintf(f,TEXT("Undefined Custom Action: %d\n"),dwAction);
  535. break;
  536. }
  537. error:
  538. if (f) fwprintf(f,TEXT("bitscnfg.exe: Complete.\n"));
  539. if (f) fclose(f);
  540. return 0;
  541. }