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.

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