1 //==============================================================;
3 // This source code is only intended as a supplement to existing Microsoft documentation.
8 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
9 // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
10 // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
13 // Copyright (C) 1999 - 2001 Microsoft Corporation. All Rights Reserved.
17 //==============================================================;
26 // if not standalone comment out next line
29 // list all nodes that are extendable here
30 // List the GUID and then the description
31 // terminate with a NULL, NULL set.
32 EXTENSION_NODE _ExtendableNodes[] = {
35 // list all of the nodes that we extend
36 EXTENDER_NODE _NodeExtensions[] =
39 ////////////////////////////////////////////////////////
41 // Internal helper functions prototypes
44 // Set the given key and its value.
45 BOOL setKeyAndValue(const _TCHAR* pszPath,
46 const _TCHAR* szSubkey,
47 const _TCHAR* szValue) ;
49 // Set the given key and its value in the MMC Snapin location
50 BOOL setSnapInKeyAndValue(const _TCHAR* szKey,
51 const _TCHAR* szSubkey,
53 const _TCHAR* szValue);
55 // Set the given valuename under the key to value
56 BOOL setValue(const _TCHAR* szKey,
57 const _TCHAR* szValueName,
58 const _TCHAR* szValue);
60 BOOL setSnapInExtensionNode(const _TCHAR* szSnapID,
61 const _TCHAR* szNodeID,
62 const _TCHAR* szDescription);
64 // Delete szKeyChild and all of its descendents.
65 LONG recursiveDeleteKey(HKEY hKeyParent, const _TCHAR* szKeyChild) ;
67 ////////////////////////////////////////////////////////
72 // Size of a CLSID as a string
73 //const int CLSID_STRING_SIZE = 39 ;
75 /////////////////////////////////////////////////////////
77 // Public function implementation
81 // Register the component in the registry.
83 HRESULT RegisterServer(HMODULE hModule, // DLL module handle
84 const CLSID& clsid, // Class ID
85 const _TCHAR* szFriendlyName) // IDs
87 // Get server location.
88 _TCHAR szModule[512] ;
90 ::GetModuleFileName(hModule,
92 sizeof(szModule)/sizeof(_TCHAR)) ;
94 assert(dwResult != 0) ;
97 LPOLESTR wszCLSID = NULL ;
98 HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
100 assert(SUCCEEDED(hr)) ;
102 MAKE_TSTRPTR_FROMWIDE(pszCLSID, wszCLSID);
104 // Build the key CLSID\\{...}
106 _tcscpy(szKey, _T("CLSID\\")) ;
107 _tcscat(szKey, pszCLSID) ;
109 // Add the CLSID to the registry.
110 setKeyAndValue(szKey, NULL, szFriendlyName) ;
112 // Add the server filename subkey under the CLSID key.
113 setKeyAndValue(szKey, _T("InprocServer32"), szModule) ;
115 // set the threading model
116 _tcscat(szKey, _T("\\InprocServer32"));
117 setValue(szKey, _T("ThreadingModel"), _T("Apartment"));
120 CoTaskMemFree(wszCLSID) ;
126 // Remove the component from the registry.
128 LONG UnregisterServer(const CLSID& clsid) // IDs
131 LPOLESTR wszCLSID = NULL ;
132 HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
135 // Build the key CLSID\\{...}
137 _tcscpy(szKey, _T("CLSID\\")) ;
139 MAKE_TSTRPTR_FROMWIDE(pszT, wszCLSID);
140 _tcscat(szKey, pszT) ;
142 // Delete the CLSID Key - CLSID\{...}
143 LONG lResult = recursiveDeleteKey(HKEY_CLASSES_ROOT, szKey) ;
144 assert((lResult == ERROR_SUCCESS) ||
145 (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
148 CoTaskMemFree(wszCLSID) ;
154 // Register the snap-in in the registry.
156 HRESULT RegisterSnapin(const CLSID& clsid, // Class ID
157 const _TCHAR* szNameString)
160 LPOLESTR wszCLSID = NULL ;
161 LPOLESTR wszAboutCLSID = NULL;
162 LPOLESTR wszExtendCLSID = NULL;
163 LPOLESTR wszNodeCLSID = NULL;
164 EXTENSION_NODE *pExtensionNode;
165 EXTENDER_NODE *pNodeExtension;
166 _TCHAR szKeyBuf[1024] ;
169 HRESULT hr = StringFromCLSID(clsid, &wszCLSID) ;
171 MAKE_TSTRPTR_FROMWIDE(pszCLSID, wszCLSID);
173 // Add the CLSID to the registry.
174 setSnapInKeyAndValue(pszCLSID, NULL, _T("NameString"), szNameString) ;
177 setSnapInKeyAndValue(pszCLSID, _T("StandAlone"), NULL, NULL);
180 // register each of the node types in _ExtendableNodes as an extendable node
181 for (pExtensionNode = &(_ExtendableNodes[0]);*pExtensionNode->szDescription;pExtensionNode++)
183 hr = StringFromCLSID(pExtensionNode->GUID, &wszExtendCLSID);
184 MAKE_TSTRPTR_FROMWIDE(pszExtendCLSID, wszExtendCLSID);
185 setSnapInExtensionNode(pszCLSID, pszExtendCLSID, pExtensionNode->szDescription);
186 CoTaskMemFree(wszExtendCLSID);
189 // register each of the node extensions
190 for (pNodeExtension = &(_NodeExtensions[0]);*pNodeExtension->szDescription;pNodeExtension++)
192 hr = StringFromCLSID(pNodeExtension->guidNode, &wszExtendCLSID);
193 MAKE_TSTRPTR_FROMWIDE(pszExtendCLSID, wszExtendCLSID);
194 _tcscpy(szKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\NodeTypes\\"));
195 _tcscat(szKeyBuf, pszExtendCLSID);
197 switch (pNodeExtension->eType) {
198 case NameSpaceExtension:
199 _tcscat(szKeyBuf, _T("\\Extensions\\NameSpace"));
201 case ContextMenuExtension:
202 _tcscat(szKeyBuf, _T("\\Extensions\\ContextMenu"));
204 case ToolBarExtension:
205 _tcscat(szKeyBuf, _T("\\Extensions\\ToolBar"));
207 case PropertySheetExtension:
208 _tcscat(szKeyBuf, _T("\\Extensions\\PropertySheet"));
211 _tcscat(szKeyBuf, _T("\\Extensions\\Task"));
213 case DynamicExtension:
214 _tcscat(szKeyBuf, _T("\\Dynamic Extensions"));
219 // Create and open key and subkey.
220 long lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE ,
222 0, NULL, REG_OPTION_NON_VOLATILE,
223 KEY_ALL_ACCESS, NULL,
226 if (lResult != ERROR_SUCCESS)
231 hr = StringFromCLSID(pNodeExtension->guidExtension, &wszNodeCLSID);
232 assert(SUCCEEDED(hr));
234 MAKE_TSTRPTR_FROMWIDE(pszNodeCLSID, wszNodeCLSID);
236 if (pNodeExtension->szDescription != NULL)
238 RegSetValueEx(hKey, pszNodeCLSID, 0, REG_SZ,
239 (BYTE *)pNodeExtension->szDescription,
240 (_tcslen(pNodeExtension->szDescription)+1)*sizeof(_TCHAR)) ;
245 CoTaskMemFree(wszExtendCLSID);
246 CoTaskMemFree(wszNodeCLSID);
251 CoTaskMemFree(wszCLSID) ;
256 // Unregister the snap-in in the registry.
258 HRESULT UnregisterSnapin(const CLSID& clsid) // Class ID
260 _TCHAR szKeyBuf[1024];
261 LPOLESTR wszCLSID = NULL;
264 HRESULT hr = StringFromCLSID(clsid, &wszCLSID);
265 MAKE_TSTRPTR_FROMWIDE(pszCLSID, wszCLSID);
266 // Load the buffer with the Snap-In Location
267 _tcscpy(szKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\SnapIns"));
269 // Copy keyname into buffer.
270 _tcscat(szKeyBuf, _T("\\"));
271 _tcscat(szKeyBuf, pszCLSID);
273 // Delete the CLSID Key - CLSID\{...}
274 LONG lResult = recursiveDeleteKey(HKEY_LOCAL_MACHINE, szKeyBuf);
275 assert((lResult == ERROR_SUCCESS) ||
276 (lResult == ERROR_FILE_NOT_FOUND)) ; // Subkey may not exist.
278 //Uncomment following for loop to unregister all extendable node types
279 //Note that if a snap-in's extendable node types are unregistered,
280 //any extension snap-ins for these node types will have to be re-registered
281 //in order to rebuild their entries under the SOFTWARE\Microsoft\MMC\NodeTypes key
284 // Unregister each of the node types in _ExtendableNodes as an extendable node
285 // Note that this snap-in does not register any extendable node types
287 EXTENSION_NODE *pNode;
288 LPOLESTR wszExtendCLSID = NULL;
290 for (pNode = &(_ExtendableNodes[0]);*pNode->szDescription;pNode++)
292 hr = StringFromCLSID(pNode->GUID, &wszExtendCLSID);
293 MAKE_TSTRPTR_FROMWIDE(pszExtendCLSID, wszExtendCLSID);
295 // Load the buffer with the Snap-In Location
296 _tcscpy(szKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\NodeTypes\\"));
297 // Copy keyname into buffer.
298 _tcscat(szKeyBuf, pszExtendCLSID);
299 recursiveDeleteKey(HKEY_LOCAL_MACHINE, szKeyBuf);
300 CoTaskMemFree(wszExtendCLSID);
306 CoTaskMemFree(wszCLSID);
312 // Delete a key and all of its descendents.
314 LONG recursiveDeleteKey(HKEY hKeyParent, // Parent of key to delete
315 const _TCHAR* lpszKeyChild) // Key to delete
319 LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild, 0,
320 KEY_ALL_ACCESS, &hKeyChild) ;
321 if (lRes != ERROR_SUCCESS)
326 // Enumerate all of the decendents of this child.
328 _TCHAR szBuffer[256] ;
330 while (RegEnumKeyEx(hKeyChild, 0, szBuffer, &dwSize, NULL,
331 NULL, NULL, &time) == S_OK)
333 // Delete the decendents of this child.
334 lRes = recursiveDeleteKey(hKeyChild, szBuffer) ;
335 if (lRes != ERROR_SUCCESS)
337 // Cleanup before exiting.
338 RegCloseKey(hKeyChild) ;
345 RegCloseKey(hKeyChild) ;
347 // Delete this child.
348 return RegDeleteKey(hKeyParent, lpszKeyChild) ;
352 // Create a key and set its value.
353 // - This helper function was borrowed and modifed from
354 // Kraig Brockschmidt's book Inside OLE.
356 BOOL setKeyAndValue(const _TCHAR* szKey,
357 const _TCHAR* szSubkey,
358 const _TCHAR* szValue)
361 _TCHAR szKeyBuf[1024] ;
363 // Copy keyname into buffer.
364 _tcscpy(szKeyBuf, szKey) ;
366 // Add subkey name to buffer.
367 if (szSubkey != NULL)
369 _tcscat(szKeyBuf, _T("\\")) ;
370 _tcscat(szKeyBuf, szSubkey ) ;
373 // Create and open key and subkey.
374 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
376 0, NULL, REG_OPTION_NON_VOLATILE,
377 KEY_ALL_ACCESS, NULL,
379 if (lResult != ERROR_SUCCESS)
387 RegSetValueEx(hKey, NULL, 0, REG_SZ,
389 (_tcslen(szValue)+1)*sizeof(_TCHAR)) ;
397 // Open a key value and set it
399 BOOL setValue(const _TCHAR* szKey,
400 const _TCHAR* szValueName,
401 const _TCHAR* szValue)
404 _TCHAR szKeyBuf[1024] ;
406 // Copy keyname into buffer.
407 _tcscpy(szKeyBuf, szKey) ;
409 // Create and open key and subkey.
410 long lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT ,
412 0, NULL, REG_OPTION_NON_VOLATILE,
413 KEY_ALL_ACCESS, NULL,
415 if (lResult != ERROR_SUCCESS)
423 RegSetValueEx(hKey, szValueName, 0, REG_SZ,
425 (_tcslen(szValue)+1)*sizeof(_TCHAR)) ;
434 // Create a key and set its value.
435 // - This helper function was borrowed and modifed from
436 // Kraig Brockschmidt's book Inside OLE.
438 BOOL setSnapInKeyAndValue(const _TCHAR* szKey,
439 const _TCHAR* szSubkey,
440 const _TCHAR* szName,
441 const _TCHAR* szValue)
444 _TCHAR szKeyBuf[1024] ;
446 // Load the buffer with the Snap-In Location
447 _tcscpy(szKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\SnapIns"));
449 // Copy keyname into buffer.
450 _tcscat(szKeyBuf, _T("\\")) ;
451 _tcscat(szKeyBuf, szKey) ;
453 // Add subkey name to buffer.
454 if (szSubkey != NULL)
456 _tcscat(szKeyBuf, _T("\\")) ;
457 _tcscat(szKeyBuf, szSubkey ) ;
460 // Create and open key and subkey.
461 long lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE ,
463 0, NULL, REG_OPTION_NON_VOLATILE,
464 KEY_ALL_ACCESS, NULL,
466 if (lResult != ERROR_SUCCESS)
474 RegSetValueEx(hKey, szName, 0, REG_SZ,
476 (_tcslen(szValue)+1)*sizeof(_TCHAR)) ;
483 BOOL setSnapInExtensionNode(const _TCHAR* szSnapID,
484 const _TCHAR* szNodeID,
485 const _TCHAR* szDescription)
488 _TCHAR szSnapNodeKeyBuf[1024] ;
489 _TCHAR szMMCNodeKeyBuf[1024];
491 // Load the buffer with the Snap-In Location
492 _tcscpy(szSnapNodeKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\SnapIns\\"));
493 // add in the clisid into buffer.
494 _tcscat(szSnapNodeKeyBuf, szSnapID) ;
495 _tcscat(szSnapNodeKeyBuf, _T("\\NodeTypes\\"));
496 _tcscat(szSnapNodeKeyBuf, szNodeID) ;
498 // Load the buffer with the NodeTypes Location
499 _tcscpy(szMMCNodeKeyBuf, _T("SOFTWARE\\Microsoft\\MMC\\NodeTypes\\"));
500 _tcscat(szMMCNodeKeyBuf, szNodeID) ;
502 // Create and open the Snapin Key.
503 long lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE ,
505 0, NULL, REG_OPTION_NON_VOLATILE,
506 KEY_ALL_ACCESS, NULL,
508 if (lResult != ERROR_SUCCESS)
514 if (szDescription != NULL)
516 RegSetValueEx(hKey, NULL, 0, REG_SZ,
517 (BYTE *)szDescription,
518 (_tcslen(szDescription)+1)*sizeof(_TCHAR)) ;
523 // Create and open the NodeTypes Key.
524 lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE ,
526 0, NULL, REG_OPTION_NON_VOLATILE,
527 KEY_ALL_ACCESS, NULL,
529 if (lResult != ERROR_SUCCESS)
535 if (szDescription != NULL)
537 RegSetValueEx(hKey, NULL, 0, REG_SZ,
538 (BYTE *)szDescription,
539 (_tcslen(szDescription)+1)*sizeof(_TCHAR)) ;