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.

269 lines
7.6 KiB

  1. /****************************************************************************
  2. *
  3. * REGISTRY.cpp
  4. *
  5. * Microsoft Confidential
  6. * Copyright (c) Microsoft Corporation 1992-1997
  7. * All rights reserved
  8. *
  9. * This module provides functionality for self-registering/unregistering via
  10. * the regsvr32.exe
  11. *
  12. * The code comes almost verbatim from Chapter 7 of Dale Rogerson's
  13. * "Inside COM", and thus is minimally commented.
  14. *
  15. * 4/24/97 jmazner Created
  16. *
  17. ***************************************************************************/
  18. #include "wizard.h"
  19. #include "registry.h"
  20. ////////////////////////////////////////////////////////
  21. //
  22. // Internal helper functions prototypes
  23. //
  24. // Set the given key and its value.
  25. // 7/2/97 jmazner IE bug #41852
  26. // need to choose a particular key name, so updated setKeyAndValue from
  27. // chapter 12 of InsideCom.
  28. /***
  29. BOOL setKeyAndValue(const char* pszPath,
  30. const char* szSubkey,
  31. const char* szValue) ;
  32. ***/
  33. BOOL setKeyAndValue(const TCHAR* pszPath,
  34. const TCHAR* szSubkey,
  35. const TCHAR* szValue,
  36. const TCHAR* szName = NULL) ;
  37. // Convert a CLSID into a char string.
  38. void CLSIDtochar(const CLSID& clsid,
  39. TCHAR* szCLSID,
  40. int length) ;
  41. // Delete szKeyChild and all of its descendents.
  42. LONG recursiveDeleteKey(HKEY hKeyParent, const TCHAR* szKeyChild) ;
  43. ////////////////////////////////////////////////////////
  44. //
  45. // Constants
  46. //
  47. // Size of a CLSID as a string
  48. const int CLSID_STRING_SIZE = 39 ;
  49. /////////////////////////////////////////////////////////
  50. //
  51. // Public function implementation
  52. //
  53. //
  54. // Register the component in the registry.
  55. //
  56. HRESULT RegisterServer(HMODULE hModule, // DLL module handle
  57. const CLSID& clsid, // Class ID
  58. const TCHAR* szFriendlyName, // Friendly Name
  59. const TCHAR* szVerIndProgID, // Programmatic
  60. const TCHAR* szProgID) // IDs
  61. {
  62. // Get server location.
  63. TCHAR szModule[512] ;
  64. DWORD dwResult =
  65. ::GetModuleFileName(hModule,
  66. szModule,
  67. sizeof(szModule)/sizeof(TCHAR)) ;
  68. ASSERT(dwResult != 0) ;
  69. // Convert the CLSID into a char.
  70. TCHAR szCLSID[CLSID_STRING_SIZE] ;
  71. CLSIDtochar(clsid, szCLSID, CLSID_STRING_SIZE) ;
  72. // Build the key CLSID\\{...}
  73. TCHAR szKey[CLSID_STRING_SIZE + 10] ;
  74. lstrcpy(szKey, TEXT("CLSID\\")) ;
  75. lstrcat(szKey, szCLSID) ;
  76. // Add the CLSID to the registry.
  77. setKeyAndValue(szKey, NULL, szFriendlyName) ;
  78. // Add the server filename subkey under the CLSID key.
  79. setKeyAndValue(szKey, TEXT("InprocServer32"), szModule) ;
  80. // 7/2/97 jmazner IE bug #41852
  81. // Add Threading Model
  82. setKeyAndValue(szKey,
  83. TEXT("InprocServer32"),
  84. TEXT("Apartment"),
  85. TEXT("ThreadingModel")) ;
  86. // Add the ProgID subkey under the CLSID key.
  87. setKeyAndValue(szKey, TEXT("ProgID"), szProgID) ;
  88. // Add the version-independent ProgID subkey under CLSID key.
  89. setKeyAndValue(szKey, TEXT("VersionIndependentProgID"),
  90. szVerIndProgID) ;
  91. // Add the version-independent ProgID subkey under HKEY_CLASSES_ROOT.
  92. setKeyAndValue(szVerIndProgID, NULL, szFriendlyName) ;
  93. setKeyAndValue(szVerIndProgID, TEXT("CLSID"), szCLSID) ;
  94. setKeyAndValue(szVerIndProgID, TEXT("CurVer"), szProgID) ;
  95. // Add the versioned ProgID subkey under HKEY_CLASSES_ROOT.
  96. setKeyAndValue(szProgID, NULL, szFriendlyName) ;
  97. setKeyAndValue(szProgID, TEXT("CLSID"), szCLSID) ;
  98. return S_OK ;
  99. }
  100. //
  101. // Remove the component from the registry.
  102. //
  103. LONG UnregisterServer(const CLSID& clsid, // Class ID
  104. const TCHAR* szVerIndProgID, // Programmatic
  105. const TCHAR* szProgID) // IDs
  106. {
  107. // Convert the CLSID into a char.
  108. TCHAR szCLSID[CLSID_STRING_SIZE] ;
  109. CLSIDtochar(clsid, szCLSID, CLSID_STRING_SIZE) ;
  110. // Build the key CLSID\\{...}
  111. TCHAR szKey[64] ;
  112. lstrcpy(szKey, TEXT("CLSID\\")) ;
  113. lstrcat(szKey, szCLSID) ;
  114. // Delete the CLSID Key - CLSID\{...}
  115. LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;
  116. ASSERT((lResult == ERROR_SUCCESS) ||
  117. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  118. // Delete the version-independent ProgID Key.
  119. lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szVerIndProgID) ;
  120. ASSERT((lResult == ERROR_SUCCESS) ||
  121. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  122. // Delete the ProgID key.
  123. lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szProgID) ;
  124. ASSERT((lResult == ERROR_SUCCESS) ||
  125. (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
  126. return S_OK ;
  127. }
  128. ///////////////////////////////////////////////////////////
  129. //
  130. // Internal helper functions
  131. //
  132. // Convert a CLSID to a char string.
  133. void CLSIDtochar(const CLSID& clsid,
  134. TCHAR* szCLSID,
  135. int cch // number of characters in szCLSID
  136. )
  137. {
  138. ASSERT(length >= CLSID_STRING_SIZE) ;
  139. // Get CLSID
  140. LPOLESTR wszCLSID = NULL ;
  141. HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
  142. if (SUCCEEDED(hr))
  143. {
  144. // Covert from wide characters to non-wide.
  145. #ifdef UNICODE
  146. lstrcpyn(szCLSID, (TCHAR *)wszCLSID, cch) ;
  147. #else
  148. wcstombs(szCLSID, wszCLSID, cch) ; // characters are 1 byte.
  149. #endif
  150. // Free memory.
  151. CoTaskMemFree(wszCLSID) ;
  152. }
  153. }
  154. //
  155. // Delete a key and all of its descendents.
  156. //
  157. LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
  158. const TCHAR* lpszKeyChild) // Key to delete
  159. {
  160. // Open the child.
  161. HKEY hKeyChild ;
  162. LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
  163. KEY_ALL_ACCESS, &hKeyChild) ;
  164. if (lRes != ERROR_SUCCESS)
  165. {
  166. return lRes ;
  167. }
  168. // Enumerate all of the decendents of this child.
  169. FILETIME time ;
  170. TCHAR szBuffer[256] ;
  171. DWORD dwSize = 256 ;
  172. while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
  173. NULL, NULL, &time) == S_OK)
  174. {
  175. // Delete the decendents of this child.
  176. lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
  177. if (lRes != ERROR_SUCCESS)
  178. {
  179. // Cleanup before exiting.
  180. RegCloseKey(hKeyChild) ;
  181. return lRes;
  182. }
  183. dwSize = 256 ;
  184. }
  185. // Close the child.
  186. RegCloseKey(hKeyChild) ;
  187. // Delete this child.
  188. return RegDeleteKey(hKeyParent, lpszKeyChild) ;
  189. }
  190. //
  191. // Create a key and set its value.
  192. // - This helper function was borrowed and modifed from
  193. // Kraig Brockschmidt's book Inside OLE.
  194. //
  195. BOOL setKeyAndValue(const TCHAR* szKey,
  196. const TCHAR* szSubkey,
  197. const TCHAR* szValue,
  198. const TCHAR* szName)
  199. {
  200. HKEY hKey;
  201. TCHAR szKeyBuf[1024] ;
  202. // Copy keyname into buffer.
  203. lstrcpy(szKeyBuf, szKey) ;
  204. // Add subkey name to buffer.
  205. if (szSubkey != NULL)
  206. {
  207. lstrcat(szKeyBuf, TEXT("\\")) ;
  208. lstrcat(szKeyBuf, szSubkey ) ;
  209. }
  210. // Create and open key and subkey.
  211. long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
  212. szKeyBuf,
  213. 0, NULL, REG_OPTION_NON_VOLATILE,
  214. KEY_ALL_ACCESS, NULL,
  215. &hKey, NULL) ;
  216. if (lResult != ERROR_SUCCESS)
  217. {
  218. return FALSE ;
  219. }
  220. // Set the Value.
  221. if (szValue != NULL)
  222. {
  223. RegSetValueEx(hKey, szName, 0, REG_SZ,
  224. (BYTE *)szValue,
  225. sizeof(TCHAR)*(lstrlen(szValue)+1)) ;
  226. }
  227. RegCloseKey(hKey) ;
  228. return TRUE ;
  229. }