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.

510 lines
15 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1999.
  5. //
  6. // File: DllReg.cpp
  7. //
  8. // Contents: automatic registration and unregistration
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "priv.h"
  12. #include "resource.h"
  13. #include <advpub.h> // for REGINSTALL
  14. #include <sddl.h> // for string security descriptor stuff
  15. #include <shfusion.h>
  16. #include <MSGinaExports.h>
  17. #include <ntlsa.h>
  18. // prototypes
  19. STDAPI DllRegisterServer(void);
  20. STDAPI DllUnregisterServer(void);
  21. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine);
  22. //
  23. // Calls the ADVPACK entry-point which executes an inf
  24. // file section.
  25. //
  26. HRESULT CallRegInstall(HINSTANCE hinstFTP, LPSTR szSection)
  27. {
  28. UNREFERENCED_PARAMETER(hinstFTP);
  29. HRESULT hr = E_FAIL;
  30. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  31. if (hinstAdvPack)
  32. {
  33. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  34. if (pfnri)
  35. {
  36. char szThisDLL[MAX_PATH];
  37. // Get the location of this DLL from the HINSTANCE
  38. if (GetModuleFileNameA(HINST_THISDLL, szThisDLL, ARRAYSIZE(szThisDLL)))
  39. {
  40. STRENTRY seReg[] = {
  41. {"THISDLL", szThisDLL },
  42. { "25", "%SystemRoot%" }, // These two NT-specific entries
  43. { "11", "%SystemRoot%\\system32" }, // must be at the end of the table
  44. };
  45. STRTABLE stReg = {ARRAYSIZE(seReg) - 2, seReg};
  46. hr = pfnri(HINST_THISDLL, szSection, &stReg);
  47. }
  48. }
  49. FreeLibrary(hinstAdvPack);
  50. }
  51. return hr;
  52. }
  53. HRESULT UnregisterTypeLibrary(const CLSID* piidLibrary)
  54. {
  55. HRESULT hr = E_FAIL;
  56. TCHAR szGuid[GUIDSTR_MAX];
  57. HKEY hk;
  58. // convert the libid into a string.
  59. //
  60. SHStringFromGUID(*piidLibrary, szGuid, ARRAYSIZE(szGuid));
  61. if (RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("TypeLib"), 0, MAXIMUM_ALLOWED, &hk) == ERROR_SUCCESS)
  62. {
  63. if (SHDeleteKey(hk, szGuid))
  64. {
  65. // success
  66. hr = S_OK;
  67. }
  68. RegCloseKey(hk);
  69. }
  70. else
  71. {
  72. hr = HRESULT_FROM_WIN32(GetLastError());
  73. }
  74. return hr;
  75. }
  76. HRESULT RegisterTypeLibrary(const CLSID* piidLibrary)
  77. {
  78. HRESULT hr = E_FAIL;
  79. ITypeLib* pTypeLib;
  80. WCHAR wszModuleName[MAX_PATH];
  81. // Load and register our type library.
  82. if (GetModuleFileNameW(HINST_THISDLL, wszModuleName, ARRAYSIZE(wszModuleName)))
  83. {
  84. hr = LoadTypeLib(wszModuleName, &pTypeLib);
  85. if (SUCCEEDED(hr))
  86. {
  87. // call the unregister type library in case we had some old junk in the registry
  88. UnregisterTypeLibrary(piidLibrary);
  89. hr = RegisterTypeLib(pTypeLib, wszModuleName, NULL);
  90. if (FAILED(hr))
  91. {
  92. TraceMsg(TF_WARNING, "RegisterTypeLibrary: RegisterTypeLib failed (%x)", hr);
  93. }
  94. pTypeLib->Release();
  95. }
  96. else
  97. {
  98. TraceMsg(TF_WARNING, "RegisterTypeLibrary: LoadTypeLib failed (%x) on", hr);
  99. }
  100. }
  101. return hr;
  102. }
  103. BOOL SetDacl(LPTSTR pszTarget, SE_OBJECT_TYPE seType, LPCTSTR pszStringSD)
  104. {
  105. BOOL bResult;
  106. PSECURITY_DESCRIPTOR pSD;
  107. bResult = ConvertStringSecurityDescriptorToSecurityDescriptor(pszStringSD,
  108. SDDL_REVISION_1,
  109. &pSD,
  110. NULL);
  111. if (bResult)
  112. {
  113. PACL pDacl;
  114. BOOL bPresent;
  115. BOOL bDefault;
  116. bResult = GetSecurityDescriptorDacl(pSD, &bPresent, &pDacl, &bDefault);
  117. if (bResult)
  118. {
  119. DWORD dwErr;
  120. dwErr = SetNamedSecurityInfo(pszTarget,
  121. seType,
  122. DACL_SECURITY_INFORMATION | UNPROTECTED_DACL_SECURITY_INFORMATION,
  123. NULL,
  124. NULL,
  125. pDacl,
  126. NULL);
  127. if (ERROR_SUCCESS != dwErr)
  128. {
  129. SetLastError(dwErr);
  130. bResult = FALSE;
  131. }
  132. }
  133. LocalFree(pSD);
  134. }
  135. return bResult;
  136. }
  137. STDAPI DllRegisterServer(void)
  138. {
  139. HRESULT hr;
  140. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL")); // keep advpack loaded across multiple calls to RegInstall
  141. hr = CallRegInstall(HINST_THISDLL, "ShellUserOMInstall");
  142. ASSERT(SUCCEEDED(hr));
  143. // Grant Authenticated Users the right to create subkeys under the Hints key.
  144. // This is so non-admins can change their own hint.
  145. SetDacl(TEXT("MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Hints"),
  146. SE_REGISTRY_KEY,
  147. TEXT("D:(A;;0x4;;;AU)")); // 0x4 = KEY_CREATE_SUB_KEY
  148. hr = RegisterTypeLibrary(&LIBID_SHGINALib);
  149. ASSERT(SUCCEEDED(hr));
  150. if (hinstAdvPack)
  151. {
  152. FreeLibrary(hinstAdvPack);
  153. }
  154. return hr;
  155. }
  156. STDAPI DllUnregisterServer(void)
  157. {
  158. return S_OK;
  159. }
  160. //
  161. // This will be going away when we have resource based manifests
  162. //
  163. STDAPI SHSquirtManifest(HINSTANCE hInst, UINT uIdManifest, LPTSTR pszPath)
  164. {
  165. HRESULT hr = E_FAIL;
  166. char szManifest[2048];
  167. if (LoadStringA(hInst, uIdManifest, szManifest, ARRAYSIZE(szManifest)))
  168. {
  169. HANDLE hFile;
  170. SetFileAttributes(pszPath, FILE_ATTRIBUTE_NORMAL);
  171. hFile = CreateFile(pszPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY, NULL);
  172. if (hFile != INVALID_HANDLE_VALUE)
  173. {
  174. DWORD dw = lstrlenA(szManifest) * sizeof(char);
  175. if (WriteFile(hFile, szManifest, dw, &dw, NULL))
  176. {
  177. hr = S_OK;
  178. }
  179. else
  180. {
  181. hr = HRESULT_FROM_WIN32(GetLastError());
  182. }
  183. CloseHandle(hFile);
  184. }
  185. }
  186. return hr;
  187. }
  188. void DoFusion()
  189. {
  190. // First, get the path to explorer.exe.
  191. TCHAR szManifest[MAX_PATH];
  192. GetSystemDirectory(szManifest, ARRAYSIZE(szManifest)); // e.g. c:\winnt\system32
  193. // Tack on logonui.exe.maniest
  194. StrCat(szManifest, TEXT("\\logonui.exe.manifest"));
  195. // Extract the fusion manifest from the resource.
  196. SHSquirtManifest(HINST_THISDLL, IDS_LOGONUIMANIFEST, szManifest);
  197. GetSystemDirectory(szManifest, ARRAYSIZE(szManifest)); // e.g. c:\winnt\system32
  198. // Tack on WindowsLogon.maniest
  199. StrCat(szManifest, TEXT("\\WindowsLogon.manifest"));
  200. // Extract the fusion manifest from the resource.
  201. SHSquirtManifest(HINST_THISDLL, IDS_WINLOGONMANIFEST, szManifest);
  202. }
  203. //
  204. // End going away....
  205. //
  206. // --------------------------------------------------------------------------
  207. // IsLogonTypePresent
  208. //
  209. // Arguments: hKey = HKEY to HKLM\SW\MS\WINNT\CV\Winlogon.
  210. //
  211. // Returns: bool
  212. //
  213. // Purpose: Returns whether the value "LogonType" is present. This helps
  214. // determines upgrade cases.
  215. //
  216. // History: 2000-09-04 vtan created
  217. // --------------------------------------------------------------------------
  218. bool IsLogonTypePresent (HKEY hKey)
  219. {
  220. DWORD dwType, dwLogonType, dwLogonTypeSize;
  221. dwLogonTypeSize = sizeof(dwLogonType);
  222. return((ERROR_SUCCESS == RegQueryValueEx(hKey,
  223. TEXT("LogonType"),
  224. NULL,
  225. &dwType,
  226. reinterpret_cast<LPBYTE>(&dwLogonType),
  227. &dwLogonTypeSize)) &&
  228. (REG_DWORD == dwType));
  229. }
  230. // --------------------------------------------------------------------------
  231. // IsDomainMember
  232. //
  233. // Arguments: <none>
  234. //
  235. // Returns: bool
  236. //
  237. // Purpose: Is this machine a member of a domain? Use the LSA to get this
  238. // information.
  239. //
  240. // History: 1999-09-14 vtan created
  241. // 2000-09-04 vtan copied from msgina
  242. // --------------------------------------------------------------------------
  243. bool IsDomainMember (void)
  244. {
  245. bool fResult;
  246. int iCounter;
  247. NTSTATUS status;
  248. OBJECT_ATTRIBUTES objectAttributes;
  249. LSA_HANDLE lsaHandle;
  250. SECURITY_QUALITY_OF_SERVICE securityQualityOfService;
  251. PPOLICY_DNS_DOMAIN_INFO pDNSDomainInfo;
  252. fResult = false;
  253. securityQualityOfService.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
  254. securityQualityOfService.ImpersonationLevel = SecurityImpersonation;
  255. securityQualityOfService.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
  256. securityQualityOfService.EffectiveOnly = FALSE;
  257. InitializeObjectAttributes(&objectAttributes, NULL, 0, NULL, NULL);
  258. objectAttributes.SecurityQualityOfService = &securityQualityOfService;
  259. iCounter = 0;
  260. do
  261. {
  262. status = LsaOpenPolicy(NULL, &objectAttributes, POLICY_VIEW_LOCAL_INFORMATION, &lsaHandle);
  263. if (RPC_NT_SERVER_TOO_BUSY == status)
  264. {
  265. Sleep(10);
  266. }
  267. } while ((RPC_NT_SERVER_TOO_BUSY == status) && (++iCounter < 10));
  268. ASSERTMSG(iCounter < 10, "Abandoned advapi32!LsaOpenPolicy call - counter limit exceeded\r\n");
  269. if (NT_SUCCESS(status))
  270. {
  271. status = LsaQueryInformationPolicy(lsaHandle, PolicyDnsDomainInformation, reinterpret_cast<void**>(&pDNSDomainInfo));
  272. if (NT_SUCCESS(status) && (pDNSDomainInfo != NULL))
  273. {
  274. fResult = ((pDNSDomainInfo->DnsDomainName.Length != 0) ||
  275. (pDNSDomainInfo->DnsForestName.Length != 0) ||
  276. (pDNSDomainInfo->Sid != NULL));
  277. (NTSTATUS)LsaFreeMemory(pDNSDomainInfo);
  278. }
  279. (NTSTATUS)LsaClose(lsaHandle);
  280. }
  281. return(fResult);
  282. }
  283. // --------------------------------------------------------------------------
  284. // IsDomainMembershipAttempted
  285. //
  286. // Arguments: hKey = HKEY to HKLM\SW\MS\WINNT\CV\Winlogon.
  287. //
  288. // Returns: bool
  289. //
  290. // Purpose: Returns whether a domain join was attempt (success or failure)
  291. // during network install.
  292. //
  293. // History: 2000-09-04 vtan created
  294. // --------------------------------------------------------------------------
  295. bool IsDomainMembershipAttempted (HKEY hKey)
  296. {
  297. DWORD dwType, dwRunNetAccessWizardType, dwRunNetAccessWizardTypeSize;
  298. dwRunNetAccessWizardTypeSize = sizeof(dwRunNetAccessWizardType);
  299. return((ERROR_SUCCESS == RegQueryValueEx(hKey,
  300. TEXT("RunNetAccessWizard"),
  301. NULL,
  302. &dwType,
  303. reinterpret_cast<LPBYTE>(&dwRunNetAccessWizardType),
  304. &dwRunNetAccessWizardTypeSize)) &&
  305. (REG_DWORD == dwType) &&
  306. ((NAW_PSDOMAINJOINED == dwRunNetAccessWizardType) || (NAW_PSDOMAINJOINFAILED == dwRunNetAccessWizardType)));
  307. }
  308. // --------------------------------------------------------------------------
  309. // IsPersonal
  310. //
  311. // Arguments: <none>
  312. //
  313. // Returns: bool
  314. //
  315. // Purpose: Returns whether this product is personal.
  316. //
  317. // History: 2000-09-04 vtan created
  318. // --------------------------------------------------------------------------
  319. bool IsPersonal (void)
  320. {
  321. return(IsOS(OS_PERSONAL) != FALSE);
  322. }
  323. // --------------------------------------------------------------------------
  324. // IsProfessional
  325. //
  326. // Arguments: <none>
  327. //
  328. // Returns: bool
  329. //
  330. // Purpose: Returns whether this product is professional.
  331. //
  332. // History: 2000-09-04 vtan created
  333. // --------------------------------------------------------------------------
  334. bool IsProfessional (void)
  335. {
  336. return(IsOS(OS_PROFESSIONAL) != FALSE);
  337. }
  338. // --------------------------------------------------------------------------
  339. // IsServer
  340. //
  341. // Arguments: <none>
  342. //
  343. // Returns: bool
  344. //
  345. // Purpose: Returns whether this product is server.
  346. //
  347. // History: 2000-09-04 vtan created
  348. // --------------------------------------------------------------------------
  349. bool IsServer (void)
  350. {
  351. return(!IsPersonal() && !IsProfessional());
  352. }
  353. // --------------------------------------------------------------------------
  354. // SetDefaultLogonType
  355. //
  356. // Arguments: ulWizardType = Type of network access configured during setup.
  357. //
  358. // Returns: <none>
  359. //
  360. // Purpose: Sets the default logon type based on network settings. In this case the
  361. // machine is still on a workgroup and therefore will have all
  362. // consumer UI enabled by default. Because join domain was
  363. // requested the logon type is set to classic GINA.
  364. //
  365. // History: 2000-03-14 vtan created
  366. // 2000-07-24 vtan turn on FUS by default
  367. // 2000-09-04 vtan moved from winlogon to shgina
  368. // --------------------------------------------------------------------------
  369. void SetDefaultLogonType (void)
  370. {
  371. HKEY hKeyWinlogon;
  372. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  373. TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
  374. 0,
  375. KEY_QUERY_VALUE,
  376. &hKeyWinlogon))
  377. {
  378. // Any of the following cause the logon type to be defaulted
  379. // which means that the value is NOT written to the registry:
  380. //
  381. // 1. Value already present (this is an upgrade).
  382. // 2. Machine is a domain member (this is not supported).
  383. // 3. Machine attempted to join a domain (this indicates security).
  384. // 4. The product is a server
  385. //
  386. // Otherwise the product is either personal or professional and
  387. // the machine was joined to a workgroup or is a member of a workgroup
  388. // and therefore requires the friendly UI.
  389. if (!IsLogonTypePresent(hKeyWinlogon) &&
  390. !IsDomainMember() &&
  391. !IsDomainMembershipAttempted(hKeyWinlogon) &&
  392. !IsServer())
  393. {
  394. MEMORYSTATUSEX memoryStatusEx;
  395. TBOOL(ShellEnableFriendlyUI(TRUE));
  396. // Multiple users used to be enabled when the friendly UI was
  397. // enabled. However, on 64Mb machines the experience is
  398. // unsatisfactory. Disable it on 64Mb or lower machines.
  399. memoryStatusEx.dwLength = sizeof(memoryStatusEx);
  400. GlobalMemoryStatusEx(&memoryStatusEx);
  401. TBOOL(ShellEnableMultipleUsers((memoryStatusEx.ullTotalPhys / (1024 * 1024) > 64)));
  402. }
  403. TW32(RegCloseKey(hKeyWinlogon));
  404. }
  405. }
  406. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  407. {
  408. HRESULT hr = S_OK;
  409. if (bInstall)
  410. {
  411. DoFusion();
  412. ShellInstallAccountFilterData();
  413. #ifdef _X86_
  414. SetDefaultLogonType();
  415. #endif
  416. }
  417. return(hr);
  418. }