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.

352 lines
11 KiB

  1. #include "regsvr.h"
  2. #include "reg.h"
  3. #include "str.h"
  4. #include "sfstr.h"
  5. #include "factdata.h"
  6. #include <sddl.h>
  7. #define ARRAYSIZE(a) (sizeof((a))/sizeof((a)[0]))
  8. ///////////////////////////////////////////////////////////////////////////////
  9. // Internal helper functions prototypes
  10. LONG _RecursiveDeleteKey(HKEY hKeyParent, LPCWSTR szKeyChild);
  11. ///////////////////////////////////////////////////////////////////////////////
  12. // Constants
  13. // Size of a CLSID as a string
  14. const int CLSID_STRING_SIZE = 39;
  15. ///////////////////////////////////////////////////////////////////////////////
  16. // Public function implementation
  17. HRESULT RegisterAppID(const CLSID* pclsidAppID)
  18. {
  19. WCHAR szAppID[CLSID_STRING_SIZE];
  20. WCHAR szKey[MAX_KEY] = TEXT("AppID\\");
  21. HRESULT hres = _StringFromGUID(pclsidAppID, szAppID, ARRAYSIZE(szAppID));
  22. if (SUCCEEDED(hres))
  23. {
  24. hres = SafeStrCatN(szKey, szAppID, ARRAYSIZE(szKey));
  25. if (SUCCEEDED(hres))
  26. {
  27. // Add the CLSID key and the FriendlyName
  28. HKEY hkey;
  29. hres= _RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkey, NULL);
  30. if (S_OK == hres)
  31. {
  32. hres = _RegSetString(hkey, L"LocalService", L"ShellHWDetection");
  33. if (SUCCEEDED(hres))
  34. {
  35. PSECURITY_DESCRIPTOR pSD;
  36. ULONG cbSD;
  37. //
  38. // NTRAID#NTBUG9-258937-2001/01/17-jeffreys
  39. //
  40. // Set the launch permissions to prevent COM from ever
  41. // launching the service. The only time we want the service
  42. // to launch is at system startup.
  43. //
  44. // Don't think the owner and group matter, but they must be
  45. // present, or COM thinks the security descriptor is invalid.
  46. // O:SY --> Owner = LocalSystem
  47. // G:BA --> Group = Local Administrators group
  48. //
  49. // The DACL has a single Deny ACE
  50. // D:(D;;1;;;WD) --> Deny COM_RIGHTS_EXECUTE (1) to Everyone (WD)
  51. //
  52. if (ConvertStringSecurityDescriptorToSecurityDescriptorW(L"O:SYG:BAD:(D;;1;;;WD)", SDDL_REVISION, &pSD, &cbSD))
  53. {
  54. hres = _RegSetBinary(hkey, L"LaunchPermission", pSD, cbSD);
  55. LocalFree(pSD);
  56. }
  57. else
  58. {
  59. hres = E_OUTOFMEMORY;
  60. }
  61. }
  62. RegCloseKey(hkey);
  63. }
  64. }
  65. }
  66. return hres;
  67. }
  68. // Register the component in the registry.
  69. HRESULT RegisterServer(HMODULE hModule, REFCLSID rclsid,
  70. LPCWSTR pszFriendlyName, LPCWSTR pszVerIndProgID, LPCWSTR pszProgID,
  71. DWORD dwThreadingModel, BOOL fInprocServer, BOOL fLocalServer,
  72. BOOL fLocalService, LPCWSTR pszLocalService, const CLSID* pclsidAppID)
  73. {
  74. WCHAR szCLSID[CLSID_STRING_SIZE];
  75. WCHAR szKey[MAX_KEY] = TEXT("CLSID\\");
  76. HRESULT hres = _StringFromGUID(&rclsid, szCLSID, ARRAYSIZE(szCLSID));
  77. if (SUCCEEDED(hres))
  78. {
  79. LPWSTR pszModel = NULL;
  80. WCHAR szFree[] = TEXT("Free");
  81. WCHAR szApartment[] = TEXT("Apartment");
  82. WCHAR szNeutral[] = TEXT("Neutral");
  83. WCHAR szBoth[] = TEXT("Both");
  84. hres = SafeStrCatN(szKey, szCLSID, ARRAYSIZE(szKey));
  85. // Boring set of operations....
  86. if (SUCCEEDED(hres))
  87. {
  88. // Add the CLSID key and the FriendlyName
  89. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, NULL, NULL,
  90. pszFriendlyName);
  91. }
  92. if (SUCCEEDED(hres))
  93. {
  94. switch (dwThreadingModel)
  95. {
  96. case THREADINGMODEL_BOTH:
  97. pszModel = szBoth;
  98. break;
  99. case THREADINGMODEL_FREE:
  100. pszModel = szFree;
  101. break;
  102. case THREADINGMODEL_APARTMENT:
  103. pszModel = szApartment;
  104. break;
  105. case THREADINGMODEL_NEUTRAL:
  106. pszModel = szNeutral;
  107. break;
  108. default:
  109. hres = E_FAIL;
  110. break;
  111. }
  112. }
  113. if (SUCCEEDED(hres))
  114. {
  115. // Add the server filename subkey under the CLSID key.
  116. if (fInprocServer)
  117. {
  118. WCHAR szModule[MAX_PATH];
  119. DWORD dwResult = GetModuleFileName(hModule, szModule,
  120. ARRAYSIZE(szModule));
  121. if (dwResult)
  122. {
  123. // Register as Inproc
  124. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  125. TEXT("InprocServer32"), NULL, szModule);
  126. if (SUCCEEDED(hres))
  127. {
  128. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  129. TEXT("InprocServer32"), TEXT("ThreadingModel"),
  130. pszModel);
  131. }
  132. }
  133. }
  134. }
  135. if (SUCCEEDED(hres))
  136. {
  137. // Add the server filename subkey under the CLSID key.
  138. if (fLocalServer)
  139. {
  140. WCHAR szModule[MAX_PATH];
  141. // Note the NULL as 1st arg. This way a DLL can register a
  142. // factory as part of an EXE. Obviously, if this is done
  143. // from 2 EXE's, only the last one will win...
  144. DWORD dwResult = GetModuleFileName(NULL, szModule,
  145. ARRAYSIZE(szModule));
  146. if (dwResult)
  147. {
  148. // Register as LocalServer
  149. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  150. TEXT("LocalServer32"), NULL, szModule);
  151. if (SUCCEEDED(hres))
  152. {
  153. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  154. TEXT("LocalServer32"), TEXT("ThreadingModel"),
  155. pszModel);
  156. }
  157. }
  158. }
  159. }
  160. if (SUCCEEDED(hres))
  161. {
  162. // Add the server filename subkey under the CLSID key.
  163. if (fLocalService)
  164. {
  165. // Register as LocalServer
  166. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  167. TEXT("LocalService"), NULL, pszLocalService);
  168. if (SUCCEEDED(hres))
  169. {
  170. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  171. TEXT("LocalService"), TEXT("ThreadingModel"),
  172. pszModel);
  173. }
  174. {
  175. // We had this bug for a while that a LocalServer32 key was
  176. // also installed
  177. // Delete it on upgrade (stephstm: Jun/02/2000)
  178. // Remove this code when nobody will upgrade from
  179. // builds earlier than 2242
  180. WCHAR szKeyLocal[MAX_KEY];
  181. SafeStrCpyN(szKeyLocal, szKey, ARRAYSIZE(szKeyLocal));
  182. SafeStrCatN(szKeyLocal, TEXT("\\LocalServer32"),
  183. ARRAYSIZE(szKeyLocal));
  184. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKeyLocal);
  185. }
  186. }
  187. }
  188. if (SUCCEEDED(hres))
  189. {
  190. // Add the ProgID subkey under the CLSID key.
  191. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  192. TEXT("ProgID"), NULL, pszProgID);
  193. }
  194. if (SUCCEEDED(hres))
  195. {
  196. // Add the version-independent ProgID subkey under CLSID
  197. // key.
  198. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey,
  199. TEXT("VersionIndependentProgID"), NULL, pszVerIndProgID);
  200. }
  201. if (SUCCEEDED(hres))
  202. {
  203. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID,
  204. NULL, NULL, pszFriendlyName);
  205. }
  206. if (SUCCEEDED(hres))
  207. {
  208. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID,
  209. TEXT("CLSID"), NULL, szCLSID);
  210. }
  211. if (SUCCEEDED(hres))
  212. {
  213. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszVerIndProgID,
  214. TEXT("CurVer"), NULL, pszProgID);
  215. }
  216. if (SUCCEEDED(hres))
  217. {
  218. // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
  219. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszProgID,
  220. NULL, NULL, pszFriendlyName);
  221. }
  222. if (SUCCEEDED(hres))
  223. {
  224. // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT
  225. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, pszProgID,
  226. TEXT("CLSID"), NULL, szCLSID);
  227. }
  228. if (SUCCEEDED(hres))
  229. {
  230. if (pclsidAppID)
  231. {
  232. // do the AppID.
  233. WCHAR szAppID[CLSID_STRING_SIZE];
  234. hres = _StringFromGUID(pclsidAppID, szAppID, ARRAYSIZE(szAppID));
  235. if (SUCCEEDED(hres))
  236. {
  237. hres = _RegSetKeyAndString(HKEY_CLASSES_ROOT, szKey, NULL, TEXT("AppID"), szAppID);
  238. }
  239. RegisterAppID(pclsidAppID);
  240. }
  241. }
  242. }
  243. return hres;
  244. }
  245. // Remove the component from the registry.
  246. HRESULT UnregisterServer(REFCLSID rclsid, LPCWSTR pszVerIndProgID,
  247. LPCWSTR pszProgID)
  248. {
  249. WCHAR szCLSID[CLSID_STRING_SIZE];
  250. WCHAR szKey[MAX_KEY] = TEXT("CLSID\\");
  251. HRESULT hres = _StringFromGUID(&rclsid, szCLSID, ARRAYSIZE(szCLSID));
  252. if (SUCCEEDED(hres))
  253. {
  254. SafeStrCatN(szKey, szCLSID, ARRAYSIZE(szKey));
  255. // Delete the CLSID Key - CLSID\{...}
  256. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, szKey);
  257. // Delete the version-independent ProgID Key.
  258. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, pszVerIndProgID);
  259. // Delete the ProgID key.
  260. _RecursiveDeleteKey(HKEY_CLASSES_ROOT, pszProgID);
  261. }
  262. return S_OK;
  263. }
  264. ///////////////////////////////////////////////////////////////////////////////
  265. // Internal helper functions
  266. // Delete a key and all of its descendents.
  267. LONG _RecursiveDeleteKey(HKEY hKeyParent, LPCWSTR pszKeyChild)
  268. {
  269. HKEY hkeyChild;
  270. LONG lRes = RegOpenKeyEx(hKeyParent, pszKeyChild, 0, KEY_ALL_ACCESS,
  271. &hkeyChild);
  272. if (ERROR_SUCCESS == lRes)
  273. {
  274. // Enumerate all of the decendents of this child.
  275. WCHAR szBuffer[MAX_PATH];
  276. DWORD dwSize = ARRAYSIZE(szBuffer);
  277. while ((ERROR_SUCCESS == lRes) && (S_OK == RegEnumKeyEx(hkeyChild, 0,
  278. szBuffer, &dwSize, NULL, NULL, NULL, NULL)))
  279. {
  280. // Delete the decendents of this child.
  281. lRes = _RecursiveDeleteKey(hkeyChild, szBuffer);
  282. dwSize = ARRAYSIZE(szBuffer);
  283. }
  284. // Close the child.
  285. RegCloseKey(hkeyChild);
  286. }
  287. if (ERROR_SUCCESS == lRes)
  288. {
  289. // Delete this child.
  290. lRes = RegDeleteKey(hKeyParent, pszKeyChild);
  291. }
  292. return lRes;
  293. }