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.

533 lines
14 KiB

  1. // tsuserex.cpp : Implementation of DLL Exports.
  2. // Note: Proxy/Stub Information
  3. // To build a separate proxy/stub DLL,
  4. // run nmake -f tsexusrmps.mk in the project directory.
  5. #include "stdafx.h"
  6. #include "resource.h"
  7. #include "initguid.h"
  8. #include "tsuserex.h" // generated file. class ids.
  9. #include "tsuserex_i.c" // generated file. class ids.
  10. #include "interfaces.h" // Definition of the TSUserExInterfaces class
  11. #ifdef _RTM_
  12. #include "tsusrcpy.h"
  13. #endif
  14. #define GUIDSIZE 40
  15. TCHAR tchSnapinRegKey[] = TEXT( "Software\\Microsoft\\MMC\\SnapIns\\" );
  16. TCHAR tchNodeRegKey[] = TEXT( "Software\\Microsoft\\MMC\\NodeTypes\\" );
  17. TCHAR tchExtKey[] = TEXT( "\\Extensions\\PropertySheet" );
  18. HRESULT Local_RegisterNodeType( const GUID *pGuidNodeType , const GUID *pGuidExtension , LPTSTR szDescription );
  19. HRESULT Local_RegisterSnapinExt( const GUID *pGuidToRegister , const GUID *pAboutGuid , LPTSTR szNameString , LPTSTR szProvider , LPTSTR szVersion );
  20. HRESULT Local_VerifyNodeType( const GUID *pGuidSnapin , const GUID *pGuidSnapinNodeTypeToVerify );
  21. HINSTANCE ghInstance;
  22. HINSTANCE GetInstance()
  23. {
  24. return ghInstance;
  25. }
  26. CComModule _Module;
  27. // this object has IExtendPropertySheet interface.
  28. BEGIN_OBJECT_MAP(ObjectMap)
  29. OBJECT_ENTRY(CLSID_TSUserExInterfaces, TSUserExInterfaces)
  30. #ifdef _RTM_
  31. OBJECT_ENTRY(CLSID_ExtCopyNoUI, CExtCopyNoUI )
  32. #endif
  33. END_OBJECT_MAP()
  34. /////////////////////////////////////////////////////////////////////////////
  35. // DLL Entry Point
  36. extern "C"
  37. BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
  38. {
  39. if (dwReason == DLL_PROCESS_ATTACH)
  40. {
  41. ghInstance = hInstance;
  42. _Module.Init(ObjectMap, hInstance);
  43. DisableThreadLibraryCalls(hInstance);
  44. }
  45. else if (dwReason == DLL_PROCESS_DETACH)
  46. {
  47. // LOGMESSAGE0(_T("DllMain::Process being Detached..."));
  48. _Module.Term();
  49. }
  50. return TRUE; // ok
  51. }
  52. /////////////////////////////////////////////////////////////////////////////
  53. // Used to determine whether the DLL can be unloaded by OLE
  54. STDAPI DllCanUnloadNow(void)
  55. {
  56. // LOGMESSAGE1(_T("DllCanUnloadNow..Returing %s"), _Module.GetLockCount()==0 ? _T("S_OK") : _T("S_FALSE"));
  57. return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
  58. }
  59. /////////////////////////////////////////////////////////////////////////////
  60. // Returns a class factory to create an object of the requested type
  61. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  62. {
  63. // LOGMESSAGE0(_T("DllGetClassObject.."));
  64. return _Module.GetClassObject(rclsid, riid, ppv);
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // DllRegisterServer - Adds entries to the system registry
  68. /* extern */ const CLSID CLSID_LocalUser =
  69. { /* 5d6179c8-17ec-11d1-9aa9-00c04fd8fe93 */
  70. 0x5d6179c8,
  71. 0x17ec,
  72. 0x11d1,
  73. {0x9a, 0xa9, 0x00, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
  74. };
  75. /* extern */ const GUID NODETYPE_User =
  76. { /* 5d6179cc-17ec-11d1-9aa9-00c04fd8fe93 */
  77. 0x5d6179cc,
  78. 0x17ec,
  79. 0x11d1,
  80. {0x9a, 0xa9, 0x00, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
  81. };
  82. // /* extern */ const GUID NODETYPE_DSUser =
  83. //{ /* 228D9A84-C302-11CF-9AA4-00AA004A5691 */
  84. // 0x228D9A84,
  85. // 0xC302,
  86. // 0x11CF,
  87. // {0x9A, 0xA4, 0x00, 0xAA, 0x00, 0x4A, 0x56, 0x91}
  88. //};
  89. // DS Snapin CLSID - {E355E538-1C2E-11d0-8C37-00C04FD8FE93}
  90. const GUID CLSID_DSSnapin =
  91. {
  92. 0xe355e538,
  93. 0x1c2e,
  94. 0x11d0,
  95. {0x8c, 0x37, 0x0, 0xc0, 0x4f, 0xd8, 0xfe, 0x93}
  96. };
  97. /* extern */ const GUID NODETYPE_DSUser =
  98. { /* BF967ABA-0DE6-11D0-A285-00AA003049E2 */
  99. 0xBF967ABA,
  100. 0x0DE6,
  101. 0x11D0,
  102. {0xA2, 0x85, 0x00, 0xAA, 0x00, 0x30, 0x49, 0xE2}
  103. };
  104. // bf967aba0de611d0a28500aa003049e2
  105. STDAPI DllRegisterServer(void)
  106. {
  107. TCHAR tchNameString[ 160 ];
  108. TCHAR tchProvider[ 160 ];
  109. TCHAR tchVersion[ 16 ];
  110. HRESULT hr = _Module.RegisterServer(TRUE);
  111. if( SUCCEEDED( hr ) )
  112. {
  113. // register it as extension to localsecurity snapin
  114. VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_NAMESTRING_SNAPIN , tchNameString , sizeof( tchNameString ) / sizeof( TCHAR ) ) );
  115. VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_PROVIDER_SNAPIN , tchProvider , sizeof( tchProvider ) / sizeof( TCHAR ) ) );
  116. VERIFY_E( 0 , LoadString( _Module.GetResourceInstance( ) , IDS_VERSION_SNAPIN , tchVersion , sizeof( tchVersion ) / sizeof( TCHAR ) ) );
  117. hr = Local_RegisterSnapinExt( &CLSID_TSUserExInterfaces ,
  118. &CLSID_TSUserExInterfaces ,
  119. tchNameString ,
  120. tchProvider ,
  121. tchVersion
  122. );
  123. }
  124. if( SUCCEEDED( hr ) )
  125. {
  126. hr = Local_RegisterNodeType( &NODETYPE_User , &CLSID_TSUserExInterfaces , _T( "Terminal Server property page extension" ) );
  127. }
  128. if( SUCCEEDED( hr ) )
  129. {
  130. // the dsadmin snapin does not list all its node, as there are lot of them
  131. // so before registring ourself to extend the node,
  132. // lets write the nodeType we are going to extend into registry ourselves
  133. hr = Local_VerifyNodeType( &CLSID_DSSnapin , &NODETYPE_DSUser );
  134. }
  135. if( SUCCEEDED( hr ) )
  136. {
  137. hr = Local_RegisterNodeType( &NODETYPE_DSUser , &CLSID_TSUserExInterfaces , _T( "Terminal Server property page extension" ) );
  138. }
  139. return hr;
  140. }
  141. //---------------------------------------------------------------------------
  142. // Local_VerifyNodeType
  143. // Checks first to see if NodeType exists, if not it'll create it
  144. //---------------------------------------------------------------------------
  145. HRESULT Local_VerifyNodeType( const GUID *pGuidSnapin , const GUID *pGuidSnapinNodeTypeToVerify )
  146. {
  147. OLECHAR szSnapin[ GUIDSIZE ];
  148. OLECHAR szSnapinNodeType[ GUIDSIZE ];
  149. HKEY hKey;
  150. ASSERT_( pGuidSnapin != NULL );
  151. ASSERT_( pGuidSnapinNodeTypeToVerify != NULL );
  152. TCHAR tchRegKeyName[ MAX_PATH ];
  153. if( StringFromGUID2( *pGuidSnapin , szSnapin , GUIDSIZE ) == 0 )
  154. {
  155. return E_INVALIDARG;
  156. }
  157. if( StringFromGUID2( *pGuidSnapinNodeTypeToVerify , szSnapinNodeType , GUIDSIZE ) == 0 )
  158. {
  159. return E_INVALIDARG;
  160. }
  161. lstrcpy( tchRegKeyName , tchSnapinRegKey );
  162. lstrcat( tchRegKeyName , szSnapin );
  163. lstrcat( tchRegKeyName , _T( "\\NodeTypes\\" ) );
  164. lstrcat( tchRegKeyName , szSnapinNodeType );
  165. if( RegOpenKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , KEY_READ , &hKey ) != ERROR_SUCCESS )
  166. {
  167. // Key does not exist
  168. // Create the nodetype in snapin and in NodeType
  169. DWORD disp;
  170. if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) != ERROR_SUCCESS )
  171. {
  172. return E_FAIL;
  173. }
  174. RegCloseKey( hKey );
  175. lstrcpy( tchRegKeyName , tchNodeRegKey );
  176. lstrcat( tchRegKeyName , szSnapinNodeType );
  177. if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) != ERROR_SUCCESS )
  178. {
  179. return E_FAIL;
  180. }
  181. }
  182. RegCloseKey( hKey );
  183. return S_OK;
  184. }
  185. //---------------------------------------------------------------------------
  186. // Local_RegisterSnapinExt
  187. // Creates the extension node reg keys
  188. //---------------------------------------------------------------------------
  189. HRESULT Local_RegisterSnapinExt( const GUID *pGuidToRegister , const GUID *pAboutGuid , LPTSTR szNameString , LPTSTR szProvider , LPTSTR szVersion )
  190. {
  191. OLECHAR szGuid[ GUIDSIZE ];
  192. TCHAR tchRegKeyName[ MAX_PATH ];
  193. HKEY hKey;
  194. HKEY hSubKey = NULL;
  195. HRESULT hr = E_FAIL;
  196. ASSERT_( pGuidToRegister != NULL );
  197. ASSERT_( pAboutGuid != NULL );
  198. ASSERT_( szNameString != NULL );
  199. ASSERT_( szProvider != NULL );
  200. ASSERT_( szVersion != NULL );
  201. lstrcpy( tchRegKeyName , tchSnapinRegKey );
  202. if( StringFromGUID2( *pGuidToRegister , szGuid , GUIDSIZE ) == 0 )
  203. {
  204. return E_INVALIDARG;
  205. }
  206. lstrcat( tchRegKeyName , szGuid );
  207. DWORD disp;
  208. do
  209. {
  210. if( RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hKey , &disp ) == ERROR_SUCCESS )
  211. {
  212. // if the key exist overwrite any and all values
  213. OLECHAR szAboutGuid[ GUIDSIZE ];
  214. if( StringFromGUID2( *pAboutGuid , szAboutGuid , GUIDSIZE ) > 0 )
  215. {
  216. RegSetValueEx( hKey , L"About" , 0 , REG_SZ , ( LPBYTE )szAboutGuid , sizeof( szAboutGuid ) );
  217. }
  218. // these calls should not fail but I'll test for it
  219. VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"NameString" , 0 , REG_SZ , ( LPBYTE )szNameString , sizeof( TCHAR ) * ( lstrlen( szNameString ) + 1 ) ) );
  220. VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"Provider" , 0 , REG_SZ , ( LPBYTE )szProvider , sizeof( TCHAR ) * ( lstrlen( szProvider ) + 1 ) ) );
  221. VERIFY_S( ERROR_SUCCESS , RegSetValueEx( hKey , L"Version" , 0 , REG_SZ , ( LPBYTE )szVersion , sizeof( TCHAR ) * ( lstrlen( szVersion ) + 1 ) ) );
  222. /*
  223. lstrcpy( tchRegKeyName , L"NodeTypes\\" );
  224. lstrcat( tchRegKeyName , szGuid );
  225. if( RegCreateKeyEx( hKey , tchRegKeyName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , &hSubKey , &disp ) == ERROR_SUCCESS )
  226. {
  227. hr = S_OK;
  228. }
  229. */
  230. hr = S_OK;
  231. }
  232. } while( 0 );
  233. RegCloseKey( hSubKey );
  234. RegCloseKey( hKey );
  235. return hr;
  236. }
  237. //---------------------------------------------------------------------------
  238. // Local_RegisterNodeType
  239. // pGuidToExt is the snapin we want to extend
  240. // pGuidNodeType is the node in the snapin we'll register under
  241. // pGuidExtension is us the property sheet extension
  242. //---------------------------------------------------------------------------
  243. HRESULT Local_RegisterNodeType( const GUID *pGuidNodeType , const GUID *pGuidExtension , LPTSTR szDescription )
  244. {
  245. OLECHAR szGuidNode[ GUIDSIZE ];
  246. OLECHAR szGuidExt[ GUIDSIZE ];
  247. TCHAR tchRegKeyName[ MAX_PATH ];
  248. HKEY hKey;
  249. ASSERT_( pGuidNodeType != NULL );
  250. ASSERT_( pGuidExtension != NULL );
  251. ASSERT_( szDescription != NULL );
  252. lstrcpy( tchRegKeyName , tchNodeRegKey );
  253. if( StringFromGUID2( *pGuidNodeType , szGuidNode , GUIDSIZE ) == 0 )
  254. {
  255. return E_INVALIDARG;
  256. }
  257. if( StringFromGUID2( *pGuidExtension , szGuidExt , GUIDSIZE ) == 0 )
  258. {
  259. return E_INVALIDARG;
  260. }
  261. lstrcat( tchRegKeyName , szGuidNode );
  262. lstrcat( tchRegKeyName , tchExtKey );
  263. if( RegCreateKey( HKEY_LOCAL_MACHINE , tchRegKeyName , &hKey ) != ERROR_SUCCESS )
  264. {
  265. return E_FAIL;
  266. }
  267. RegSetValueEx( hKey , szGuidExt , 0 , REG_SZ , ( LPBYTE )szDescription , sizeof( TCHAR ) * ( lstrlen( szDescription ) + 1 ) );
  268. RegCloseKey( hKey );
  269. return S_OK;
  270. }
  271. //---------------------------------------------------------------------------
  272. // Delete a key and all of its descendents.
  273. //---------------------------------------------------------------------------
  274. LONG RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild )
  275. {
  276. // Open the child.
  277. HKEY hKeyChild;
  278. LONG lRes = RegOpenKeyEx(hKeyParent, lpszKeyChild , 0 , KEY_ALL_ACCESS, &hKeyChild);
  279. if (lRes != ERROR_SUCCESS)
  280. {
  281. return lRes;
  282. }
  283. // Enumerate all of the decendents of this child.
  284. FILETIME time;
  285. TCHAR szBuffer[256];
  286. DWORD dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
  287. while( RegEnumKeyEx( hKeyChild , 0 , szBuffer , &dwSize , NULL , NULL , NULL , &time ) == S_OK )
  288. {
  289. // Delete the decendents of this child.
  290. lRes = RecursiveDeleteKey(hKeyChild, szBuffer);
  291. if (lRes != ERROR_SUCCESS)
  292. {
  293. RegCloseKey(hKeyChild);
  294. return lRes;
  295. }
  296. dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
  297. }
  298. // Close the child.
  299. RegCloseKey( hKeyChild );
  300. // Delete this child.
  301. return RegDeleteKey( hKeyParent , lpszKeyChild );
  302. }
  303. //---------------------------------------------------------------------------
  304. // Local_UnRegisterSnapinExt
  305. // reconstruct the enter key then delete key
  306. //---------------------------------------------------------------------------
  307. HRESULT Local_UnRegisterSnapinExt( const GUID *pGuidExt )
  308. {
  309. TCHAR tchRegKeyName[ MAX_PATH ];
  310. OLECHAR szGuidExt[ GUIDSIZE ];
  311. ASSERT_( pGuidExt != NULL );
  312. lstrcpy( tchRegKeyName , tchSnapinRegKey );
  313. if( StringFromGUID2( *pGuidExt , szGuidExt , GUIDSIZE ) == 0 )
  314. {
  315. return E_INVALIDARG;
  316. }
  317. lstrcat( tchRegKeyName , szGuidExt );
  318. if( RecursiveDeleteKey( HKEY_LOCAL_MACHINE , tchRegKeyName ) == ERROR_SUCCESS )
  319. {
  320. return S_OK;
  321. }
  322. return S_FALSE;
  323. }
  324. //---------------------------------------------------------------------------
  325. // Local_UnregisterNodeType
  326. //---------------------------------------------------------------------------
  327. HRESULT Local_UnregisterNodeType( const GUID *pGuid , const GUID *pDeleteThisGuid )
  328. {
  329. OLECHAR szGuid[ GUIDSIZE ];
  330. OLECHAR szDeleteThisGuid[ GUIDSIZE ];
  331. HKEY hKey;
  332. ASSERT_( pGuid != NULL );
  333. ASSERT_( pDeleteThisGuid != NULL );
  334. TCHAR tchRegKeyName[ MAX_PATH ];
  335. lstrcpy( tchRegKeyName , tchNodeRegKey );
  336. if( StringFromGUID2( *pGuid , szGuid , GUIDSIZE ) == 0 )
  337. {
  338. return E_FAIL;
  339. }
  340. if( StringFromGUID2( *pDeleteThisGuid , szDeleteThisGuid , GUIDSIZE ) == 0 )
  341. {
  342. return E_FAIL;
  343. }
  344. lstrcat( tchRegKeyName , szGuid );
  345. lstrcat( tchRegKeyName , tchExtKey );
  346. if( RegOpenKey( HKEY_LOCAL_MACHINE , tchRegKeyName , &hKey ) != ERROR_SUCCESS )
  347. {
  348. return E_FAIL;
  349. }
  350. if( RegDeleteValue( hKey , szDeleteThisGuid ) == ERROR_SUCCESS )
  351. {
  352. RegCloseKey( hKey );
  353. return S_OK;
  354. }
  355. return E_FAIL;
  356. }
  357. /////////////////////////////////////////////////////////////////////////////
  358. // DllUnregisterServer - Removes entries from the system registry
  359. STDAPI DllUnregisterServer(void)
  360. {
  361. Local_UnRegisterSnapinExt( &CLSID_TSUserExInterfaces );
  362. Local_UnregisterNodeType( &NODETYPE_User , &CLSID_TSUserExInterfaces );
  363. Local_UnregisterNodeType( &NODETYPE_DSUser , &CLSID_TSUserExInterfaces );
  364. try
  365. {
  366. _Module.UnregisterServer();
  367. }
  368. catch( ... )
  369. {
  370. ODS( L"TSUSEREX : Exception thrown" );
  371. return E_FAIL;
  372. }
  373. return S_OK;
  374. }