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.

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