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.

345 lines
10 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1999 **
  4. //*********************************************************************
  5. //
  6. // REGISTRY.CPP - Implementation of functions to register components.
  7. //
  8. // HISTORY:
  9. //
  10. // 1/27/99 a-jaswed Created.
  11. //
  12. // registry functions.
  13. #include <objbase.h>
  14. #include <assert.h>
  15. #include <appdefs.h>
  16. #include "registry.h"
  17. ////////////////////////////////////////////////////////
  18. // Internal helper functions prototypes
  19. //
  20. // Set the given key and its value.
  21. BOOL setKeyAndValue(const WCHAR* pszPath,
  22. const WCHAR* szSubkey,
  23. const WCHAR* szValue,
  24. const WCHAR* szName = NULL);
  25. // Convert a CLSID into a char string.
  26. void CLSIDtochar(const CLSID& clsid,
  27. WCHAR* szCLSID,
  28. int length);
  29. // Determine if a particular subkey exists.
  30. BOOL SubkeyExists(const WCHAR* pszPath,
  31. const WCHAR* szSubkey);
  32. // Delete szKeyChild and all of its descendents.
  33. LONG recursiveDeleteKey(HKEY hKeyParent, const WCHAR* szKeyChild);
  34. /////////////////////////////////////////////////////////
  35. // Public function implementation
  36. /////////////////////////////////////////////////////////
  37. /////////////////////////////////////////////////////////
  38. // Register the component in the registry.
  39. //
  40. HRESULT RegisterServer( HMODULE hModule, // DLL module handle
  41. const CLSID& clsid, // Class ID
  42. const WCHAR* szFriendlyName, // Friendly Name
  43. const WCHAR* szVerIndProgID, // Programmatic
  44. const WCHAR* szProgID) // IDs
  45. {
  46. // Get server location.
  47. WCHAR szModule[512] ;
  48. DWORD dwResult =
  49. ::GetModuleFileName(hModule,
  50. szModule,
  51. MAX_CHARS_IN_BUFFER(szModule)) ;
  52. assert(dwResult != 0) ;
  53. // Convert a CLSID into a char string.
  54. WCHAR szCLSID[CLSID_STRING_SIZE] ;
  55. CLSIDtochar(clsid, szCLSID, CLSID_STRING_SIZE) ;
  56. // Build the key CLSID\\{...}
  57. WCHAR szKey[64] ;
  58. lstrcpy(szKey, L"CLSID\\");
  59. lstrcat(szKey, szCLSID) ;
  60. // Add the CLSID to the registry.
  61. setKeyAndValue(szKey, NULL, szFriendlyName) ;
  62. // Add server filename key
  63. #ifdef _OUTPROC_SERVER_
  64. setKeyAndValue(szKey, L"LocalServer32", szModule) ;
  65. #else
  66. setKeyAndValue(szKey, L"InprocServer32", szModule) ;
  67. #endif
  68. // Add the ProgID subkey under the CLSID key.
  69. setKeyAndValue(szKey, L"ProgID", szProgID) ;
  70. // Add the version-independent ProgID subkey under CLSID key.
  71. setKeyAndValue( szKey, L"VersionIndependentProgID",
  72. szVerIndProgID) ;
  73. // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
  74. setKeyAndValue(szVerIndProgID, NULL, szFriendlyName);
  75. setKeyAndValue(szVerIndProgID, L"CLSID", szCLSID) ;
  76. setKeyAndValue(szVerIndProgID, L"CurVer", szProgID) ;
  77. // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
  78. setKeyAndValue(szProgID, NULL, szFriendlyName);
  79. setKeyAndValue(szProgID, L"CLSID", szCLSID) ;
  80. return S_OK;
  81. }
  82. /////////////////////////////////////////////////////////
  83. // Remove the component from the registry.
  84. //
  85. LONG UnregisterServer( const CLSID& clsid,
  86. const WCHAR* szVerIndProgID,
  87. const WCHAR* szProgID)
  88. {
  89. // Convert the CLSID into a char.
  90. WCHAR szCLSID[CLSID_STRING_SIZE] ;
  91. CLSIDtochar(clsid, szCLSID, CLSID_STRING_SIZE) ;
  92. // Build the key CLSID\\{...}
  93. WCHAR szKey[80] ;
  94. lstrcpy(szKey, L"CLSID\\");
  95. lstrcat(szKey, szCLSID) ;
  96. // Check for a another server for this component.
  97. #ifdef _OUTPROC_SERVER_
  98. if (SubkeyExists(szKey, L"InprocServer32"))
  99. #else
  100. if (SubkeyExists(szKey, L"LocalServer32"))
  101. #endif
  102. {
  103. // Delete only the path for this server.
  104. #ifdef _OUTPROC_SERVER_
  105. lstrcat(szKey, L"\\LocalServer32") ;
  106. #else
  107. lstrcat(szKey, L"\\InprocServer32") ;
  108. #endif
  109. LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;
  110. assert(lResult == ERROR_SUCCESS) ;
  111. }
  112. else
  113. {
  114. // Delete all related keys.
  115. // Delete the CLSID Key - CLSID\{...}
  116. LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;
  117. assert((lResult == ERROR_SUCCESS) ||
  118. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  119. // Delete the version-independent ProgID Key.
  120. lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
  121. assert((lResult == ERROR_SUCCESS) ||
  122. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  123. // Delete the ProgID key.
  124. lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ;
  125. assert((lResult == ERROR_SUCCESS) ||
  126. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  127. }
  128. return S_OK;
  129. }
  130. ///////////////////////////////////////////////////////////
  131. // Internal helper functions
  132. ///////////////////////////////////////////////////////////
  133. /////////////////////////////////////////////////////////
  134. // Convert a CLSID to a char string.
  135. //
  136. void CLSIDtochar( const CLSID& clsid,
  137. WCHAR* szCLSID,
  138. int length)
  139. {
  140. assert(length >= CLSID_STRING_SIZE) ;
  141. // Get CLSID
  142. LPOLESTR sz = NULL ;
  143. HRESULT hr = StringFromCLSID(clsid, &sz) ;
  144. assert(SUCCEEDED(hr)) ;
  145. assert(NULL != sz);
  146. // Convert from wide characters to non-wide characters.
  147. lstrcpyn(szCLSID, sz, length);
  148. // Free memory.
  149. CoTaskMemFree(sz) ;
  150. }
  151. /////////////////////////////////////////////////////////
  152. // Delete a key and all of its descendents.
  153. //
  154. LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete.
  155. const WCHAR* lpszKeyChild) // Key to delete.
  156. {
  157. // Open the child.
  158. HKEY hKeyChild;
  159. LONG lRes = RegOpenKeyEx( hKeyParent, lpszKeyChild, 0,
  160. KEY_ALL_ACCESS, &hKeyChild);
  161. if (lRes != ERROR_SUCCESS)
  162. {
  163. return lRes;
  164. }
  165. // Enumerate all of the decendents of this child.
  166. FILETIME time;
  167. WCHAR szBuffer[256];
  168. DWORD dwSize = 256;
  169. while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
  170. NULL, NULL, &time) == S_OK)
  171. {
  172. // Delete the decendents of this child.
  173. lRes = recursiveDeleteKey(hKeyChild, szBuffer);
  174. if (lRes != ERROR_SUCCESS)
  175. {
  176. // Cleanup before exiting.
  177. RegCloseKey(hKeyChild);
  178. return lRes;
  179. }
  180. dwSize = 256;
  181. }
  182. // Close the child.
  183. RegCloseKey(hKeyChild);
  184. // Delete this child.
  185. return RegDeleteKey(hKeyParent, lpszKeyChild);
  186. }
  187. /////////////////////////////////////////////////////////
  188. // Determine if a particular subkey exists.
  189. //
  190. BOOL SubkeyExists(const WCHAR* pszPath, // Path of key to check
  191. const WCHAR* szSubkey) // Key to check
  192. {
  193. HKEY hKey ;
  194. WCHAR szKeyBuf[80] ;
  195. // Copy keyname into buffer.
  196. lstrcpy(szKeyBuf, pszPath) ;
  197. // Add subkey name to buffer.
  198. if (szSubkey != NULL)
  199. {
  200. lstrcat(szKeyBuf, L"\\") ;
  201. lstrcat(szKeyBuf, szSubkey ) ;
  202. }
  203. // Determine if key exists by trying to open it.
  204. LONG lResult = ::RegOpenKeyEx(HKEY_CLASSES_ROOT,
  205. szKeyBuf,
  206. 0,
  207. KEY_ALL_ACCESS,
  208. &hKey) ;
  209. if (lResult == ERROR_SUCCESS)
  210. {
  211. RegCloseKey(hKey) ;
  212. return TRUE ;
  213. }
  214. return FALSE ;
  215. }
  216. /////////////////////////////////////////////////////////
  217. // Create a key and set its value.
  218. //
  219. // This helper function was borrowed and modifed from Kraig Brockschmidt's
  220. // book Inside OLE.
  221. //
  222. BOOL setKeyAndValue(const WCHAR* szKey,
  223. const WCHAR* szSubkey,
  224. const WCHAR* szValue,
  225. const WCHAR* szName)
  226. {
  227. HKEY hKey;
  228. WCHAR szKeyBuf[1024] ;
  229. // Copy keyname into buffer.
  230. lstrcpy(szKeyBuf, szKey);
  231. // Add subkey name to buffer.
  232. if (szSubkey != NULL)
  233. {
  234. lstrcat(szKeyBuf, L"\\");
  235. lstrcat(szKeyBuf, szSubkey );
  236. }
  237. // Create and open key and subkey.
  238. long lResult = RegCreateKeyEx( HKEY_CLASSES_ROOT,
  239. szKeyBuf,
  240. 0, NULL, REG_OPTION_NON_VOLATILE,
  241. KEY_ALL_ACCESS, NULL,
  242. &hKey, NULL) ;
  243. if (lResult != ERROR_SUCCESS)
  244. {
  245. return FALSE ;
  246. }
  247. // Set the Value.
  248. if (szValue != NULL)
  249. {
  250. RegSetValueEx(hKey, szName, 0, REG_SZ,
  251. (BYTE *)szValue,
  252. BYTES_REQUIRED_BY_SZ(szValue)
  253. );
  254. }
  255. RegCloseKey(hKey);
  256. return TRUE;
  257. }
  258. // value must be at least 1024 in size;
  259. BOOL getKeyAndValue(const WCHAR* szKey,
  260. const WCHAR* szSubkey,
  261. const WCHAR* szValue,
  262. const WCHAR* szName)
  263. {
  264. HKEY hKey;
  265. WCHAR szKeyBuf[1024] ;
  266. // Copy keyname into buffer.
  267. lstrcpy(szKeyBuf, szKey);
  268. // Add subkey name to buffer.
  269. if (szSubkey != NULL)
  270. {
  271. lstrcat(szKeyBuf, L"\\");
  272. lstrcat(szKeyBuf, szSubkey );
  273. }
  274. // open key and subkey.
  275. long lResult = RegOpenKeyEx( HKEY_CLASSES_ROOT,
  276. szKeyBuf,
  277. 0,
  278. KEY_QUERY_VALUE,
  279. &hKey) ;
  280. if (lResult != ERROR_SUCCESS)
  281. {
  282. return FALSE;
  283. }
  284. // Get the Value.
  285. if (szValue != NULL)
  286. {
  287. DWORD dwType, dwBufferSize = GETKEYANDVALUEBUFFSIZE;
  288. lResult = RegQueryValueEx(hKey, szName, NULL, &dwType, (LPBYTE) szValue, &dwBufferSize);
  289. if (lResult != ERROR_SUCCESS)
  290. {
  291. return FALSE;
  292. }
  293. }
  294. RegCloseKey(hKey);
  295. return TRUE;
  296. }