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.

7709 lines
210 KiB

  1. //Copyright (c) 1998 - 1999 Microsoft Corporation
  2. /*********************************************************************************************
  3. *
  4. *
  5. * Module Name:
  6. *
  7. * CfgComp.cpp
  8. *
  9. * Abstract:
  10. * This Module contains the implemetation of functions for the CfgBkEnd Component
  11. *
  12. * Author: Arathi Kundapur. a-akunda
  13. * Owner: alhen
  14. *
  15. *
  16. * Revision:
  17. *
  18. *
  19. ************************************************************************************************/
  20. #include "stdafx.h"
  21. #define SECURITY_WIN32
  22. #include "PtrArray.h"
  23. #include "CfgBkEnd.h"
  24. #include <winsta.h>
  25. #include <regapi.h>
  26. #include "defines.h"
  27. #include "CfgComp.h"
  28. #include "Security.h"
  29. #include <utildll.h>
  30. #define INITGUID
  31. #include "objbase.h"
  32. #include "initguid.h"
  33. #include <netcfgx.h>
  34. #include <cfg.h>
  35. #include "devguid.h"
  36. #include <aclapi.h>
  37. #include <sddl.h>
  38. #define REG_GUID_TABLE REG_CONTROL_TSERVER L"\\lanatable\\"
  39. #define REG_GUID_TABLE_T REG_CONTROL_TSERVER L"\\lanatable"
  40. #define LANA_ID L"LanaId"
  41. #define ARRAYSIZE( rg ) sizeof( rg ) / sizeof( rg[0] )
  42. #ifdef DBG
  43. bool g_fDebug = false;
  44. #endif
  45. /***********************************************************************************************************/
  46. #define RELEASEPTR(iPointer) if(iPointer) \
  47. { \
  48. iPointer->Release();\
  49. iPointer = NULL;\
  50. }
  51. /***************************************************************************************************************/
  52. LPTSTR g_pszDefaultSecurity[] = {
  53. L"DefaultSecurity",
  54. L"ConsoleSecurity"
  55. };
  56. DWORD g_numDefaultSecurity = sizeof(g_pszDefaultSecurity)/sizeof(g_pszDefaultSecurity[0]);
  57. BOOL TestUserForAdmin( );
  58. DWORD RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild );
  59. /***************************************************************************************************************
  60. Name: GetSecurityDescriptor
  61. Purpose: Gets the Security Descriptor for a Winstation
  62. Returns: HRESULT.
  63. Params:
  64. in: pWSName - Name of the Winstation.
  65. out: pSize - Size of the allocated buffer
  66. ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
  67. ****************************************************************************************************************/
  68. STDMETHODIMP CCfgComp::GetSecurityDescriptor(PWINSTATIONNAMEW pWSName, long * pSize,PSECURITY_DESCRIPTOR * ppSecurityDescriptor)
  69. {
  70. HRESULT hResult = S_OK;
  71. if(NULL == pSize || NULL == ppSecurityDescriptor || NULL == pWSName)
  72. return E_INVALIDARG;
  73. *pSize =0;
  74. *ppSecurityDescriptor = NULL;
  75. hResult = GetWinStationSecurity(FALSE, pWSName,(PSECURITY_DESCRIPTOR *)ppSecurityDescriptor);
  76. if( SUCCEEDED( hResult ) && *ppSecurityDescriptor != NULL )
  77. {
  78. *pSize = GetSecurityDescriptorLength(*ppSecurityDescriptor);
  79. }
  80. return hResult;
  81. }
  82. /***************************************************************************************************************
  83. Name: SetSecurityDescriptor
  84. Purpose: Sets the Security Descriptor for a Winstation
  85. Returns: HRESULT.
  86. Params:
  87. in: pWsName - Name of the Winstation.
  88. Size - Size of the allocated buffer
  89. pSecurityDescriptor - Pointer to the Security Descriptor
  90. ****************************************************************************************************************/
  91. BOOL
  92. CCfgComp::ValidDefaultSecurity(
  93. const WCHAR* pwszName
  94. )
  95. /*++
  96. --*/
  97. {
  98. for( DWORD i=0; i < g_numDefaultSecurity; i++ )
  99. {
  100. if( lstrcmpi( g_pszDefaultSecurity[i], pwszName ) == 0 )
  101. {
  102. break;
  103. }
  104. }
  105. return ( i >= g_numDefaultSecurity ) ? FALSE : TRUE;
  106. }
  107. HRESULT
  108. CCfgComp::SetSecurityDescriptor(
  109. BOOL bDefaultSecurity,
  110. PWINSTATIONNAMEW pWsName,
  111. DWORD Size,
  112. PSECURITY_DESCRIPTOR pSecurityDescriptor
  113. )
  114. /*++
  115. --*/
  116. {
  117. HRESULT hResult = S_OK;
  118. HKEY Handle1 = NULL, Handle2 = NULL;
  119. //Check if the caller has write permissions.
  120. if(!m_bAdmin)
  121. {
  122. ODS( L"SetSecurityDescriptor : User Is not Admin. \n" );
  123. return E_ACCESSDENIED;
  124. }
  125. //Check the parametes for NULL
  126. if(NULL == pWsName || NULL == pSecurityDescriptor || 0 == Size)
  127. return E_INVALIDARG;
  128. if( TRUE == bDefaultSecurity && FALSE == ValidDefaultSecurity( pWsName ) )
  129. {
  130. return E_INVALIDARG;
  131. }
  132. //Check for the validity of the Winstation name
  133. /*if(NULL == GetWSObject(pWsName)) //Commented out to get Rename Work. This might not be needed .
  134. return E_INVALIDARG;*/
  135. //Check if the data passed is a valid security descriptor
  136. if(ERROR_SUCCESS != ValidateSecurityDescriptor((PSECURITY_DESCRIPTOR)pSecurityDescriptor))
  137. return E_INVALIDARG;
  138. if(Size != GetSecurityDescriptorLength((PSECURITY_DESCRIPTOR)pSecurityDescriptor))
  139. return E_INVALIDARG;
  140. //Make the Resitry entries required.
  141. if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,KEY_ALL_ACCESS, &Handle1 ) != ERROR_SUCCESS )
  142. {
  143. return E_FAIL;
  144. }
  145. if( TRUE == bDefaultSecurity )
  146. {
  147. if( RegSetValueEx( Handle1, pWsName, 0, REG_BINARY,(BYTE *)pSecurityDescriptor, Size ) != ERROR_SUCCESS )
  148. {
  149. hResult = E_FAIL;
  150. }
  151. }
  152. else
  153. {
  154. if( RegOpenKeyEx(Handle1, pWsName, 0, KEY_ALL_ACCESS, &Handle2 ) != ERROR_SUCCESS )
  155. {
  156. RegCloseKey(Handle1);
  157. return E_FAIL;
  158. }
  159. if( RegSetValueEx( Handle2, L"Security", 0, REG_BINARY,(BYTE *)pSecurityDescriptor, Size ) != ERROR_SUCCESS )
  160. {
  161. hResult = E_FAIL;
  162. }
  163. }
  164. if( Handle1 != NULL )
  165. {
  166. RegCloseKey(Handle1);
  167. }
  168. if( Handle2 != NULL )
  169. {
  170. RegCloseKey(Handle2);
  171. }
  172. return hResult;
  173. }
  174. STDMETHODIMP CCfgComp::SetSecurityDescriptor(PWINSTATIONNAMEW pWsName, DWORD Size,PSECURITY_DESCRIPTOR pSecurityDescriptor)
  175. {
  176. return SetSecurityDescriptor( FALSE, pWsName, Size, pSecurityDescriptor );
  177. }
  178. /***************************************************************************************************************
  179. Name: GetUserConfig
  180. Purpose: Gets the UserConfig for a Winstation
  181. Returns: HRESULT.
  182. Params:
  183. in: pWSName - Name of the Winstation.
  184. out: pSize - Size of the allocated buffer
  185. ppUser - Pointer to the buffer containing the UserConfig
  186. ****************************************************************************************************************/
  187. STDMETHODIMP CCfgComp::GetUserConfig(PWINSTATIONNAMEW pWsName, long * pSize, PUSERCONFIG * ppUser, BOOLEAN bPerformMerger)
  188. {
  189. HRESULT hResult = S_OK;
  190. WINSTATIONCONFIG2W WSConfig;
  191. LONG Size = 0;
  192. ULONG Length = 0;
  193. *pSize = 0;
  194. *ppUser = NULL;
  195. //Read the information from the registry.
  196. POLICY_TS_MACHINE p;
  197. memset(&p, 0, sizeof(POLICY_TS_MACHINE));
  198. if((ERROR_SUCCESS != RegWinStationQueryEx(NULL,&p,pWsName,&WSConfig,sizeof(WINSTATIONCONFIG2W),&Length,bPerformMerger)))
  199. return E_FAIL;
  200. Size = sizeof(WSConfig.Config.User);
  201. *ppUser = (PUSERCONFIG)CoTaskMemAlloc(Size);
  202. if(*ppUser == NULL)
  203. return E_OUTOFMEMORY;
  204. CopyMemory((PVOID)*ppUser,(CONST VOID *)&WSConfig.Config.User,Size);
  205. *pSize = Size;
  206. return hResult;
  207. }
  208. /***************************************************************************************************************
  209. Name: GetEncryptionLevels
  210. Purpose: Gets the Encyption Levels for a Winstation
  211. Returns: HRESULT.
  212. Params:
  213. in: pName - Name of the Winstation or the Winstation Driver depending the value of Type
  214. Type - Specifies whether the Name is a Winstation name or WD Name (WsName, WdName)
  215. out: pNumEncryptionLevels - Number of Encryption Levels
  216. ppEncryption - Pointer to the buffer containing the Encryption Levels
  217. ****************************************************************************************************************/
  218. STDMETHODIMP CCfgComp::GetEncryptionLevels(WCHAR * pName, NameType Type,ULONG * pNumEncryptionLevels,Encryption ** ppEncryption)
  219. {
  220. HRESULT hResult = S_OK;
  221. PWD pWD = NULL;
  222. PWS pWS = NULL;
  223. ULONG NumLevels = 0, Size =0 ,i = 0;
  224. EncryptionLevel *pEncryptionLevels = NULL;
  225. //Check the parameters
  226. if(NULL == pNumEncryptionLevels || NULL == pName || NULL == ppEncryption)
  227. return E_INVALIDARG;
  228. *pNumEncryptionLevels = 0;
  229. *ppEncryption = NULL;
  230. //Get the pointer to the appropriate WD object.
  231. if(Type == WsName)
  232. {
  233. pWS = GetWSObject(pName);
  234. if(NULL == pWS)
  235. return E_INVALIDARG;
  236. pWD = GetWdObject(pWS->wdName);
  237. if(NULL == pWD)
  238. return E_FAIL;
  239. }
  240. else if(Type == WdName)
  241. {
  242. pWD = GetWdObject(pName);
  243. if(NULL == pWD)
  244. return E_INVALIDARG;
  245. }
  246. else
  247. return E_INVALIDARG;
  248. //Check if this object has the extension dll associated with it.
  249. //Check if the function for encryption levels was exposed in the dll
  250. if(!(pWD->hExtensionDLL && pWD->lpfnExtEncryptionLevels))
  251. return E_FAIL;
  252. //Get the EncryptionLevels. The Strings should be seperately extracted from the resource
  253. NumLevels = (pWD->lpfnExtEncryptionLevels)(&pWS->wdName, &pEncryptionLevels);
  254. if(NULL == pEncryptionLevels)
  255. return E_FAIL;
  256. Size = sizeof(Encryption);
  257. Size = NumLevels * sizeof(Encryption);
  258. *ppEncryption = (Encryption*)CoTaskMemAlloc(Size);
  259. if(*ppEncryption == NULL)
  260. return E_OUTOFMEMORY;
  261. //copy the relevent data to the Encryption structure
  262. for(i = 0; i < NumLevels; i++)
  263. {
  264. //Extract the string corresponding to the levels.
  265. if(0 == LoadString(pWD->hExtensionDLL,pEncryptionLevels[i].StringID,
  266. ((*ppEncryption)[i]).szLevel, sizeof( ( ( *ppEncryption )[ i ] ).szLevel ) / sizeof( TCHAR ) ) )
  267. {
  268. hResult = E_FAIL;
  269. break;
  270. }
  271. ((*ppEncryption)[i]).RegistryValue = pEncryptionLevels[i].RegistryValue;
  272. ((*ppEncryption)[i]).szDescr[ 0 ] = 0;
  273. if( pWD->lpfnExtGetEncryptionLevelDescr != NULL )
  274. {
  275. int nResID = 0;
  276. if( ( pWD->lpfnExtGetEncryptionLevelDescr )( pEncryptionLevels[i].RegistryValue , &nResID ) != -1 )
  277. {
  278. LoadString( pWD->hExtensionDLL , nResID , ((*ppEncryption)[i]).szDescr , sizeof( ( (*ppEncryption )[ i ] ).szDescr ) / sizeof( TCHAR ) );
  279. }
  280. }
  281. ((*ppEncryption)[i]).Flags = pEncryptionLevels[i].Flags;
  282. }
  283. *pNumEncryptionLevels = NumLevels;
  284. //pEncrptionLevels need not be cleaned up as it is global data in Rdpcfgex.dll
  285. if(FAILED(hResult))
  286. {
  287. if(*ppEncryption)
  288. {
  289. CoTaskMemFree(*ppEncryption);
  290. *ppEncryption = NULL;
  291. *pNumEncryptionLevels = 0;
  292. }
  293. }
  294. return hResult;
  295. }
  296. /***************************************************************************************************************
  297. Name: FillWdArray
  298. Purpose: Internal function to fill the m_WdArray
  299. Returns: HRESULT.
  300. Params:
  301. ****************************************************************************************************************/
  302. STDMETHODIMP CCfgComp::FillWdArray()
  303. {
  304. //Use the functionalities already provided by the regapi,
  305. //instead of reinventing the wheel
  306. long Status;
  307. ULONG Index, Index2, ByteCount, Entries, Entries2;
  308. PDNAMEW PdKey;
  309. WDNAMEW WdKey;
  310. LONG QStatus;
  311. WDCONFIG2W WdConfig;
  312. PDCONFIG3W PdConfig;
  313. TCHAR WdDll[MAX_PATH];
  314. HRESULT hResult = S_OK;
  315. /*
  316. TCHAR * pPdName = NULL;
  317. */
  318. PWD pWd = NULL;
  319. //Delete if there are already entries in the list
  320. DeleteWDArray();
  321. //Enumerate the WD's from the Registry
  322. for ( Index = 0, Entries = 1, ByteCount = sizeof(WDNAMEW);
  323. (Status =
  324. RegWdEnumerateW( NULL,
  325. &Index,
  326. &Entries,
  327. WdKey,
  328. &ByteCount )) == ERROR_SUCCESS;
  329. ByteCount = sizeof(WDNAMEW) )
  330. {
  331. if ((QStatus = RegWdQueryW( NULL, WdKey, &WdConfig,
  332. sizeof(WdConfig),
  333. &ByteCount)) != ERROR_SUCCESS )
  334. {
  335. hResult = E_FAIL;
  336. break;
  337. }
  338. /*
  339. * Only place this Wd in the WdList if it's DLL is present
  340. * on the system.
  341. */
  342. GetSystemDirectory( WdDll, MAX_PATH );
  343. lstrcat( WdDll, TEXT("\\Drivers\\") );
  344. lstrcat( WdDll, WdConfig.Wd.WdDLL );
  345. lstrcat( WdDll, TEXT(".sys" ) );
  346. if ( lstr_access( WdDll, 0 ) != 0 )
  347. continue;
  348. /*
  349. * Create a new WdList object and initialize from WdConfig
  350. * structure, adding it to the end of the WdList.
  351. */
  352. pWd = new WD;
  353. if(NULL == pWd)
  354. {
  355. hResult = E_OUTOFMEMORY;
  356. break;
  357. }
  358. lstrcpy(pWd->wdName,WdConfig.Wd.WdName);
  359. lstrcpy(pWd->wdKey,WdKey);
  360. pWd->wd2 = WdConfig;
  361. // Load the extension DLL for this WD
  362. pWd->hExtensionDLL = ::LoadLibrary(WdConfig.Wd.CfgDLL);
  363. if(pWd->hExtensionDLL)
  364. {
  365. // ODS( L"Loaded extension dll\n" );
  366. // Get the entry points
  367. pWd->lpfnExtStart = (LPFNEXTSTARTPROC)::GetProcAddress(pWd->hExtensionDLL, szStart);
  368. pWd->lpfnExtEnd = (LPFNEXTENDPROC)::GetProcAddress(pWd->hExtensionDLL, szEnd);
  369. pWd->lpfnExtEncryptionLevels = (LPFNEXTENCRYPTIONLEVELSPROC)::GetProcAddress(pWd->hExtensionDLL, szEncryptionLevels);
  370. pWd->lpfnExtDeleteObject = (LPFNEXTDELETEOBJECTPROC)::GetProcAddress(pWd->hExtensionDLL, szDeleteObject);
  371. pWd->lpfnExtRegQuery = (LPFNEXTREGQUERYPROC)::GetProcAddress(pWd->hExtensionDLL, szRegQuery);
  372. pWd->lpfnExtRegCreate = (LPFNEXTREGCREATEPROC)::GetProcAddress(pWd->hExtensionDLL, szRegCreate);
  373. pWd->lpfnExtRegDelete = (LPFNEXTREGDELETEPROC)::GetProcAddress(pWd->hExtensionDLL, szRegDelete);
  374. pWd->lpfnExtDupObject = (LPFNEXTDUPOBJECTPROC)::GetProcAddress(pWd->hExtensionDLL, szDupObject);
  375. pWd->lpfnGetCaps = ( LPFNEXTGETCAPABILITIES )::GetProcAddress( pWd->hExtensionDLL , szGetCaps );
  376. pWd->lpfnExtGetEncryptionLevelDescr =
  377. ( LPFNEXTGETENCRYPTIONLEVELDESCPROC )::GetProcAddress( pWd->hExtensionDLL , szGetEncryptionLevelDescr );
  378. // Call the ExtStart() function in the extension DLL
  379. if(pWd->lpfnExtStart)(*pWd->lpfnExtStart)(&WdConfig.Wd.WdName);
  380. }
  381. if( !m_WDArray.Add( pWd) )
  382. {
  383. ODS(L"CFGBKEND:FillWdArray adding wd failed\n" );
  384. delete pWd;
  385. hResult = E_OUTOFMEMORY;
  386. break;
  387. }
  388. //Get the names of the Transport drivers associated with this WD
  389. for ( Index2 = 0, Entries2 = 1, ByteCount = sizeof(PDNAMEW);
  390. (Status = RegPdEnumerateW(NULL,WdKey,TRUE,&Index2,&Entries2,PdKey,&ByteCount)) == ERROR_SUCCESS;
  391. ByteCount = sizeof(PDNAMEW))
  392. {
  393. PDCONFIG3W *pPdConfig = NULL;
  394. if ((QStatus = RegPdQueryW(NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount)) != ERROR_SUCCESS)
  395. {
  396. hResult = E_FAIL;
  397. break;
  398. }
  399. /*
  400. * Create a new PdName and initialize from PdConfig
  401. * structure, then add to the TdName list.
  402. */
  403. pPdConfig = new PDCONFIG3W;
  404. if( pPdConfig == NULL )
  405. {
  406. hResult = E_OUTOFMEMORY;
  407. break;
  408. }
  409. *pPdConfig = PdConfig;
  410. if( !pWd->PDConfigArray.Add( pPdConfig ) )
  411. {
  412. ODS( L"CFGBKEND:FillWdArray adding PDCONFIG3W failed\n" );
  413. delete pPdConfig;
  414. hResult = E_OUTOFMEMORY;
  415. break;
  416. }
  417. /*
  418. pPdName = new PDNAMEW;
  419. if(NULL == pPdName)
  420. {
  421. hResult = E_OUTOFMEMORY;
  422. break;
  423. }
  424. lstrcpy((TCHAR *)pPdName,PdConfig.Data.PdName);
  425. pWd->PDNameArray.Add(pPdName);
  426. */
  427. }
  428. }
  429. if(FAILED(hResult))
  430. {
  431. //Error has occured, cleanup m_WDArray
  432. DeleteWDArray();
  433. }
  434. return hResult;
  435. }
  436. /***************************************************************************************************************
  437. Name: Initialize
  438. Purpose: Initializes the object
  439. Returns: HRESULT.
  440. Params:
  441. ****************************************************************************************************************/
  442. STDMETHODIMP CCfgComp::Initialize()
  443. {
  444. HRESULT hResult = S_OK;
  445. #ifdef DBG
  446. HKEY hKey;
  447. LONG lStatus;
  448. // To control debug spewage add/remove this regkey
  449. lStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  450. L"Software\\Microsoft\\TSCC\\Debug",
  451. 0,
  452. KEY_READ,
  453. &hKey );
  454. if( lStatus == ERROR_SUCCESS )
  455. {
  456. g_fDebug = true;
  457. RegCloseKey( hKey );
  458. }
  459. #endif
  460. //If already initialized, return
  461. if(m_bInitialized)
  462. return CFGBKEND_ALREADY_INITIALIZED;
  463. //Is the user the admin?
  464. /*
  465. if(RegWinStationAccessCheck(NULL, KEY_ALL_ACCESS))
  466. {
  467. m_bAdmin = FALSE;
  468. }
  469. else
  470. {
  471. m_bAdmin = TRUE;
  472. }
  473. */
  474. m_bAdmin = TestUserForAdmin( );
  475. // Fill up the WdArray with information regarding the Wd's installed on this machine.
  476. hResult = FillWdArray();
  477. if(SUCCEEDED(hResult))
  478. {
  479. //Fill up the WsArray with the info about the WS's on this machine.
  480. hResult = FillWsArray();
  481. }
  482. if(SUCCEEDED(hResult))
  483. m_bInitialized = TRUE;
  484. else
  485. {
  486. //if Failed, Cleanup the memory used.
  487. DeleteWSArray();
  488. DeleteWDArray();
  489. }
  490. return hResult;
  491. }
  492. /***************************************************************************************************************
  493. Name: FillWsArray
  494. Purpose: Internal function to fill m_WsArray
  495. Returns: HRESULT.
  496. Params:
  497. ****************************************************************************************************************/
  498. STDMETHODIMP CCfgComp::FillWsArray()
  499. {
  500. LONG Status;
  501. ULONG Index, ByteCount, Entries;
  502. WINSTATIONNAMEW WSName;
  503. PWS pWsObject = NULL;
  504. HRESULT hResult = S_OK;
  505. WINSTATIONCONFIG2W* pWSConfig = NULL;
  506. ULONG Size = 0;
  507. //Ensure that the WS is empty.
  508. DeleteWSArray();
  509. Index = 0;
  510. Size = sizeof(WINSTATIONCONFIG2W);
  511. pWSConfig = (WINSTATIONCONFIG2W*)LocalAlloc(LMEM_FIXED, Size);
  512. if(pWSConfig == NULL)
  513. {
  514. return E_FAIL;
  515. }
  516. //Enumerate Winstations
  517. for ( Index = 0, Entries = 1, ByteCount = sizeof(WINSTATIONNAMEW);
  518. (Status =
  519. RegWinStationEnumerateW( NULL, &Index, &Entries,
  520. WSName, &ByteCount )) == ERROR_SUCCESS;
  521. ByteCount = sizeof(WINSTATIONNAMEW) )
  522. {
  523. ULONG Length;
  524. Status = RegWinStationQueryW(NULL,
  525. WSName,
  526. pWSConfig,
  527. sizeof(WINSTATIONCONFIG2W), &Length);
  528. if(Status)
  529. {
  530. continue;
  531. }
  532. //Insert a WS object into the m_WSArray.
  533. hResult = InsertInWSArray(WSName, pWSConfig, &pWsObject);
  534. if (FAILED(hResult))
  535. break;
  536. }
  537. if(pWSConfig != NULL)
  538. {
  539. LocalFree(pWSConfig);
  540. pWSConfig = NULL;
  541. }
  542. if(FAILED(hResult))
  543. {
  544. DeleteWSArray();
  545. }
  546. return hResult;
  547. }
  548. /***************************************************************************************************************
  549. Name: InsertInWSArray
  550. Purpose: Internal function to Insert a new WS in the m_WsArray
  551. Returns: HRESULT.
  552. Params:
  553. in: pWSName - Name of the Winstation.
  554. pWSConfig - PWINSTATIONCONFIG2W structure
  555. out: ppObject - Pointer to the new object
  556. ****************************************************************************************************************/
  557. STDMETHODIMP CCfgComp::InsertInWSArray( PWINSTATIONNAMEW pWSName,
  558. PWINSTATIONCONFIG2W pWSConfig,
  559. PWS * ppObject )
  560. {
  561. int Index = 0,Size = 0;
  562. BOOL bAdded;
  563. PWS pObject;
  564. HRESULT hResult = S_OK;
  565. if (pWSName == NULL || pWSConfig == NULL || ppObject == NULL)
  566. return E_INVALIDARG;
  567. //Create a new WS object and initialize.
  568. pObject = new WS;
  569. if ( NULL == pObject )
  570. return E_OUTOFMEMORY;
  571. // make sure the winstation name doesn't exceed our buffer length
  572. if (lstrlen(pWSName) > WINSTATIONNAME_LENGTH)
  573. return E_INVALIDARG;
  574. lstrcpy(pObject->Name, pWSName);
  575. pObject->fEnableWinstation = pWSConfig->Create.fEnableWinStation ? 1 : 0;
  576. lstrcpy( pObject->pdName, pWSConfig->Pd[0].Create.PdName );
  577. pObject->PdClass = (DWORD)pWSConfig->Pd[0].Create.SdClass;
  578. // New addition
  579. if( pObject->PdClass == SdAsync )
  580. {
  581. lstrcpy( pObject->DeviceName , pWSConfig->Pd[0].Params.Async.DeviceName );
  582. }
  583. //
  584. lstrcpy( pObject->wdName, pWSConfig->Wd.WdName );
  585. lstrcpy( pObject->Comment, pWSConfig->Config.Comment );
  586. pObject->LanAdapter = (pObject->PdClass == SdNetwork) ? pWSConfig->Pd[0].Params.Network.LanAdapter : ( ULONG )-1;
  587. pObject->uMaxInstanceCount = pWSConfig->Create.MaxInstanceCount;
  588. //Traverse the WSArray and insert this new WS,
  589. //keeping the list sorted by Name.
  590. PWS pTempWs = NULL;
  591. for ( Index = 0, bAdded = FALSE,Size = m_WSArray.GetSize();
  592. Index < Size; Index++ )
  593. {
  594. pTempWs = (PWS)m_WSArray[Index];
  595. if ( lstrcmpi( pTempWs->Name,pObject->Name ) > 0)
  596. {
  597. if( !m_WSArray.InsertAt(Index, pObject ) )
  598. {
  599. ODS( L"CFGBKEND:InsertInWSArray failed\n" );
  600. delete pObject;
  601. *ppObject = NULL;
  602. return E_OUTOFMEMORY;
  603. }
  604. bAdded = TRUE;
  605. break;
  606. }
  607. }
  608. //If we haven't yet added the WS, add it now to the tail
  609. if( !bAdded )
  610. {
  611. if( !m_WSArray.Add(pObject) )
  612. {
  613. ODS( L"CFGBKEND:InsertInWSArray failed\n" );
  614. delete pObject;
  615. *ppObject = NULL;
  616. return E_OUTOFMEMORY;
  617. }
  618. }
  619. //Set the ppObject referenced WS pointer to the new WS
  620. //pointer and return the index of the new WS
  621. *ppObject = pObject;
  622. return hResult;
  623. } // end CCfgComp::InsertInWSArray
  624. /***************************************************************************************************************
  625. Name: GetWdObject
  626. Purpose: Internal function to get a WD object from m_WdArray
  627. Returns: PWD - pointer to a WD object.
  628. Params:
  629. in: pWd - Name of the WD
  630. ****************************************************************************************************************/
  631. PWD CCfgComp::GetWdObject(PWDNAMEW pWdName)
  632. {
  633. PWD pObject;
  634. int Size = 0,Index = 0;
  635. //Traverse the WD list
  636. for (Index = 0, Size = m_WDArray.GetSize(); Index < Size; Index ++)
  637. {
  638. pObject = (PWD)m_WDArray[Index];
  639. if ( !lstrcmpi( pObject->wdName, pWdName ) )
  640. {
  641. return(pObject);
  642. }
  643. /* when PWD includes WDCONFIG2
  644. if( !lstrcmpi( pObject->wd2.Wd.WdName , pWdName ) )
  645. {
  646. return pObject;
  647. }
  648. */
  649. }
  650. return(NULL);
  651. } // end GetWdObject
  652. //--------------------------------------------------------------------------------------------------------------
  653. // expected return values WDF_ICA or WDF_TSHARE
  654. //--------------------------------------------------------------------------------------------------------------
  655. STDMETHODIMP CCfgComp::GetWdType( PWDNAMEW pWdName , PULONG pulType )
  656. {
  657. if( pWdName == NULL || pulType == NULL )
  658. {
  659. return E_INVALIDARG;
  660. }
  661. PWD pwdObject = GetWdObject( pWdName );
  662. if( pwdObject != NULL )
  663. {
  664. *pulType = pwdObject->wd2.Wd.WdFlag;
  665. return S_OK;
  666. }
  667. return E_FAIL;
  668. }
  669. /***************************************************************************************************************
  670. Name: GetWSObject
  671. Purpose: Internal function to get a WS Object from m_WsArray
  672. Returns: PWS - Pointer to a WS Object.
  673. Params:
  674. in: pWSName - Name of the Winstation.
  675. ****************************************************************************************************************/
  676. PWS CCfgComp::GetWSObject(WINSTATIONNAMEW WSName)
  677. {
  678. PWS pObject;
  679. int Size = 0,Index = 0;
  680. //Refresh( );
  681. //Traverse the WD list
  682. for (Index = 0, Size = m_WSArray.GetSize(); Index < Size; Index ++)
  683. {
  684. pObject = (PWS)m_WSArray[Index];
  685. if ( !lstrcmpi( pObject->Name, WSName ) )
  686. {
  687. return(pObject);
  688. }
  689. }
  690. return(NULL);
  691. } // end GetWdObject
  692. /***************************************************************************************************************
  693. Name: GetWinStationSecurity
  694. Purpose: Internal function used to Get Winstation Security
  695. Returns: HRESULT.
  696. Params:
  697. in: pWSName - Name of the Winstation.
  698. out: ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
  699. ****************************************************************************************************************/
  700. HRESULT CCfgComp::GetWinStationSecurity( BOOL bDefault, PWINSTATIONNAMEW pWSName,PSECURITY_DESCRIPTOR *ppSecurityDescriptor )
  701. {
  702. DWORD SDLength = 0;
  703. DWORD ValueType =0;
  704. HKEY Handle1 = NULL;
  705. HKEY Handle2 = NULL;
  706. HRESULT hResult = S_OK;
  707. //BOOL bDefault = FALSE;
  708. WCHAR ValueName[32]; // Just some number enough to hold string "Security" and DefaultSecurity"
  709. DWORD dwError = ERROR_SUCCESS;
  710. if(NULL == ppSecurityDescriptor)
  711. {
  712. return E_INVALIDARG;
  713. }
  714. if( TRUE == bDefault )
  715. {
  716. if(NULL == pWSName )
  717. {
  718. //Default Security
  719. lstrcpy( ValueName, L"DefaultSecurity" );
  720. }
  721. else if( lstrlen(pWSName) > sizeof(ValueName) / sizeof(ValueName[0]) - 1 )
  722. {
  723. ODS( L"CFGBKEND : GetWinStationSecurity -- default security key name is too long\n" );
  724. return E_INVALIDARG;
  725. }
  726. else
  727. {
  728. ZeroMemory( ValueName, sizeof(ValueName) );
  729. lstrcpy( ValueName, pWSName );
  730. }
  731. }
  732. else
  733. {
  734. lstrcpy( ValueName, L"Security" );
  735. }
  736. *ppSecurityDescriptor = NULL;
  737. if( RegOpenKeyEx(HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,KEY_READ, &Handle1 ) != ERROR_SUCCESS)
  738. {
  739. ODS( L"CFGBKEND : GetWinStationSecurity -- RegOpenKey failed\n" );
  740. return E_FAIL;
  741. }
  742. if(!bDefault)
  743. {
  744. if( RegOpenKeyEx( Handle1, pWSName , 0 , KEY_READ/*KEY_ALL_ACCESS*/, &Handle2 )!= ERROR_SUCCESS)
  745. {
  746. ODS( L"CFGBKEND : GetWinStationSecurity -- RegOpenKey( 2 ) failed\n" );
  747. RegCloseKey(Handle1);
  748. return E_FAIL;
  749. }
  750. RegCloseKey(Handle1);
  751. Handle1 = Handle2;
  752. Handle2 = NULL;
  753. }
  754. dwError = RegQueryValueEx( Handle1, ValueName, NULL, &ValueType,NULL, &SDLength );
  755. if( dwError != ERROR_SUCCESS )
  756. {
  757. RegCloseKey(Handle1);
  758. //I custom SD is not found, try default SD
  759. //Check bDefault flag to avoid infinite recursion
  760. if(dwError == ERROR_FILE_NOT_FOUND && !bDefault)
  761. {
  762. if(_wcsicmp(pWSName,L"Console"))
  763. {
  764. //Not a console session
  765. return GetWinStationSecurity(TRUE, NULL, ppSecurityDescriptor);
  766. }
  767. else
  768. {
  769. //This is a console session
  770. //It has different default SD
  771. return GetWinStationSecurity(TRUE, L"ConsoleSecurity", ppSecurityDescriptor);
  772. }
  773. }
  774. else
  775. {
  776. ODS( L"CFGBKEND : GetWinStationSecurity -- RegQueryValueEx failed for -- " );
  777. ODS( ValueName );
  778. ODS( L"\n" );
  779. return E_FAIL;
  780. }
  781. }
  782. //Return error if not correct data type
  783. if (ValueType != REG_BINARY)
  784. {
  785. ODS( L"CFGBKEND : GetWinStationSecurity -- ValueType != REG_BINARY\n" );
  786. RegCloseKey(Handle1);
  787. return ERROR_FILE_NOT_FOUND;
  788. }
  789. //Allocate a buffer to read the Security info and read it
  790. // ACLUI uses LocalFree
  791. // *ppSecurityDescriptor = CoTaskMemAlloc(SDLength);
  792. *ppSecurityDescriptor = ( PSECURITY_DESCRIPTOR )LocalAlloc( LMEM_FIXED , SDLength );
  793. if ( *ppSecurityDescriptor == NULL )
  794. {
  795. RegCloseKey(Handle1);
  796. return E_OUTOFMEMORY;
  797. }
  798. if( RegQueryValueEx( Handle1,ValueName, NULL, &ValueType,(BYTE *) *ppSecurityDescriptor, &SDLength ) == ERROR_SUCCESS )
  799. {
  800. //Check for a valid SD before returning.
  801. if( ERROR_SUCCESS != ValidateSecurityDescriptor( *ppSecurityDescriptor ) )
  802. {
  803. hResult = E_FAIL;
  804. }
  805. }
  806. else
  807. {
  808. hResult = E_FAIL;
  809. }
  810. if(Handle1)
  811. {
  812. RegCloseKey(Handle1);
  813. Handle1 = NULL;
  814. }
  815. if(Handle2)
  816. {
  817. RegCloseKey(Handle2);
  818. Handle2 = NULL;
  819. }
  820. if(FAILED(hResult))
  821. {
  822. if( *ppSecurityDescriptor != NULL )
  823. {
  824. // CoTaskMemFree(*ppSecurityDescriptor);
  825. LocalFree( *ppSecurityDescriptor );
  826. *ppSecurityDescriptor = NULL;
  827. }
  828. }
  829. return hResult;
  830. } // GetWinStationSecurity
  831. //This function is borrowed from security.c in the tscfg project
  832. /***************************************************************************************************************
  833. Name: ValidateSecurityDescriptor
  834. Purpose: Internal function to Validate a Security Descriptor
  835. Returns: DWORD - Error Status.
  836. Params:
  837. in: pSecurityDescriptor - pointer to a security Descriptor.
  838. ****************************************************************************************************************/
  839. DWORD CCfgComp::ValidateSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurityDescriptor)
  840. {
  841. // DWORD Error = ERROR_SUCCESS;
  842. if( IsValidSecurityDescriptor( pSecurityDescriptor ) )
  843. {
  844. return ERROR_SUCCESS;
  845. }
  846. else
  847. {
  848. return GetLastError( );
  849. }
  850. } // end ValidateSecurityDescriptor
  851. /***************************************************************************************************************
  852. Name: GetWinstationList
  853. Purpose: Gets the List of Winstations installed on a Machine
  854. Returns: HRESULT.
  855. Params:
  856. out: NumWinstations - pointer to the Number of Winstations returned.
  857. Size - pointer to the size of allocated buffer.
  858. ppWS - Pointer to the allocated buffer containing the WS Structures
  859. ****************************************************************************************************************/
  860. STDMETHODIMP CCfgComp::GetWinstationList(ULONG * NumWinstations, ULONG * Size, PWS * ppWS)
  861. {
  862. HRESULT hResult = S_OK;
  863. //If not initialized return error
  864. if(!m_bInitialized)
  865. return CFGBKEND_E_NOT_INITIALIZED;
  866. WS * pWSTemp = NULL;
  867. if(NULL == NumWinstations || NULL == Size || NULL == ppWS)
  868. return E_INVALIDARG;
  869. *NumWinstations = 0;
  870. *Size = 0;
  871. *ppWS = NULL;
  872. ULONG Num = m_WSArray.GetSize();
  873. *ppWS = (PWS)CoTaskMemAlloc(Num * sizeof(WS));
  874. if(NULL == *ppWS)
  875. return E_OUTOFMEMORY;
  876. pWSTemp = (WS *)(*ppWS);
  877. for(ULONG i = 0; i < Num ; i++)
  878. {
  879. lstrcpy(pWSTemp[i].Name,((WS *)m_WSArray[i])->Name);
  880. lstrcpy(pWSTemp[i].pdName,((WS *)m_WSArray[i])->pdName);
  881. lstrcpy(pWSTemp[i].wdName,((WS *)m_WSArray[i])->wdName);
  882. lstrcpy(pWSTemp[i].Comment,((WS *)m_WSArray[i])->Comment);
  883. pWSTemp[i].uMaxInstanceCount =((WS *)m_WSArray[i])->uMaxInstanceCount;
  884. pWSTemp[i].fEnableWinstation =((WS *)m_WSArray[i])->fEnableWinstation;
  885. pWSTemp[i].LanAdapter = ((WS *)m_WSArray[i])->LanAdapter;
  886. pWSTemp[i].PdClass = ((WS *)m_WSArray[i])->PdClass;
  887. }
  888. *NumWinstations = Num;
  889. *Size = Num * sizeof(WS);
  890. return hResult;
  891. }
  892. /***************************************************************************************************************
  893. Name: GetWdTypeList
  894. Purpose: Gets the List of Winstation Drivers
  895. Returns: HRESULT.
  896. Params:
  897. out: pNumWd - pointer to the number of entries returned.
  898. pSize - pointer to the size of the allocated buffer
  899. ppData - Pointer to an array of WDNAMEW
  900. ****************************************************************************************************************/
  901. STDMETHODIMP CCfgComp::GetWdTypeList(ULONG * pNumWd, ULONG * pSize, WCHAR ** ppData)
  902. {
  903. HRESULT hResult = S_OK;
  904. //If not initialized return error
  905. if(!m_bInitialized)
  906. return CFGBKEND_E_NOT_INITIALIZED;
  907. if(NULL == pNumWd || NULL == pSize || NULL == ppData)
  908. return E_INVALIDARG;
  909. WDNAMEW * pWdTemp = NULL;
  910. *pNumWd = 0;
  911. *pSize = 0;
  912. *ppData = NULL;
  913. ULONG Num = m_WDArray.GetSize();
  914. *ppData = (WCHAR *)CoTaskMemAlloc(Num * sizeof(WDNAMEW));
  915. if(NULL == *ppData)
  916. return E_OUTOFMEMORY;
  917. pWdTemp = (WDNAMEW *)(*ppData);
  918. for(ULONG i = 0; i < Num ; i++)
  919. {
  920. lstrcpy(pWdTemp[i],((WD *)m_WDArray[i])->wdName);
  921. }
  922. *pNumWd = Num;
  923. *pSize = Num * sizeof(WS);
  924. return hResult;
  925. }
  926. /***************************************************************************************************************
  927. Name: IsWSNameUnique
  928. Purpose: Checks if the Name is already not an existing winstation
  929. Returns: HRESULT.
  930. Params:
  931. in: pWSName - Name of the Winstation.
  932. out: pUnique - pointer to whether the winstation name is unique
  933. ****************************************************************************************************************/
  934. STDMETHODIMP CCfgComp::IsWSNameUnique(PWINSTATIONNAMEW pWSName,BOOL * pUnique)
  935. {
  936. if(NULL == pWSName || NULL == pUnique)
  937. return E_INVALIDARG;
  938. *pUnique = FALSE;
  939. if((NULL == GetWSObject(pWSName)) && (lstrcmpi(pWSName,m_szConsole)))
  940. *pUnique = TRUE;
  941. return S_OK;
  942. }
  943. /***************************************************************************************************************
  944. Name: GetTransportTypes
  945. Purpose: Gets the Security Descriptor for a Winstation
  946. Returns: HRESULT.
  947. Params:
  948. in: Name - Name of the Winstation or WD depending on the value of Type.
  949. Type - Specifies whether the Name is a Winstation name or WD Name (WsName, WdName)
  950. out: pNumPd - pointer to the number of Transport types returned
  951. pSize - Size of the allocated buffer
  952. ppSecurityDescriptor - Pointer to the buffer containing the Transport types supported
  953. ****************************************************************************************************************/
  954. STDMETHODIMP CCfgComp::GetTransportTypes(WCHAR * Name, NameType Type,ULONG * pNumPd, ULONG * pSize, WCHAR * * ppData)
  955. {
  956. HRESULT hResult = S_OK;
  957. //If not initialized return error
  958. if(!m_bInitialized)
  959. return CFGBKEND_E_NOT_INITIALIZED;
  960. if(NULL == pNumPd || NULL == pSize || NULL == ppData || NULL == Name)
  961. return E_INVALIDARG;
  962. WD * pWD = NULL;
  963. WS * pWS = NULL;
  964. *pNumPd = 0;
  965. *pSize = 0;
  966. *ppData = NULL;
  967. PDNAMEW * pPdTemp = NULL;
  968. if(Type == WsName)
  969. {
  970. pWS = GetWSObject(Name);
  971. if(NULL == pWS)
  972. return E_INVALIDARG;
  973. pWD = GetWdObject(pWS->wdName);
  974. if(NULL == pWD)
  975. return E_FAIL;
  976. }
  977. else if(Type == WdName)
  978. {
  979. pWD = GetWdObject(Name);
  980. if(NULL == pWD)
  981. return E_INVALIDARG;
  982. }
  983. else
  984. return E_INVALIDARG;
  985. // ULONG Num = (pWD->PDNameArray).GetSize();
  986. ULONG Num = ( pWD->PDConfigArray ).GetSize( );
  987. *ppData = (WCHAR *)CoTaskMemAlloc(Num * sizeof(PDNAMEW));
  988. if(NULL == *ppData)
  989. return E_OUTOFMEMORY;
  990. pPdTemp = (PDNAMEW *)(*ppData);
  991. for(ULONG i = 0; i < Num ; i++)
  992. {
  993. // PDNAMEW * pPdName = (PDNAMEW *)pWD->PDNameArray[i];
  994. PDNAMEW * pPdName = &( ( PDCONFIG3W * )pWD->PDConfigArray[i] )->Data.PdName;
  995. lstrcpy(pPdTemp[i], *pPdName);
  996. }
  997. *pNumPd = Num;
  998. *pSize = Num * sizeof(PDNAMEW);
  999. return hResult;
  1000. }
  1001. /***************************************************************************************************************
  1002. Name: GetLanAdapterList
  1003. Purpose: Gets the List of Lan Adapters associated with a given protocol
  1004. Returns: HRESULT.
  1005. Params:
  1006. in: pdName - Name of the protocol.
  1007. out: pNumAdapters:pointer to the number of Lan adapters returned
  1008. pSize - Size of the allocated buffer
  1009. ppSecurityDescriptor - Pointer to An Array of DEVICENAME's
  1010. ****************************************************************************************************************/
  1011. STDMETHODIMP CCfgComp::GetLanAdapterList(WCHAR * pdName, ULONG * pNumAdapters, ULONG * pSize, WCHAR ** ppData)
  1012. {
  1013. HRESULT hResult = S_OK, hr = S_OK;
  1014. //If not initialized return error
  1015. if(!m_bInitialized)
  1016. {
  1017. ODS( L"CCfgComp::GetLanAdapterList returned CFGBKEND_E_NOT_INITIALIZED\n" );
  1018. return CFGBKEND_E_NOT_INITIALIZED;
  1019. }
  1020. if(NULL == pdName || NULL == ppData || NULL == pNumAdapters || NULL == pSize)
  1021. {
  1022. ODS( L"CCfgComp::GetLanAdapterList returned INVALIDARG \n" );
  1023. return E_INVALIDARG;
  1024. }
  1025. *pNumAdapters = 0;
  1026. *pSize = 0;
  1027. *ppData = NULL;
  1028. int NumAdapters = 0;
  1029. TCHAR * pszDevice = NULL;
  1030. int length = 0;
  1031. DEVICENAMEW * pTempPointer = NULL;
  1032. CPtrArray DeviceArray;
  1033. //Interface pointer declarations
  1034. TCHAR szProtocol[256];
  1035. INetCfg * pnetCfg = NULL;
  1036. INetCfgClass * pNetCfgClass = NULL;
  1037. INetCfgClass * pNetCfgClassAdapter = NULL;
  1038. INetCfgComponent * pNetCfgComponent = NULL;
  1039. INetCfgComponent * pNetCfgComponentprot = NULL;
  1040. IEnumNetCfgComponent * pEnumComponent = NULL;
  1041. INetCfgComponentBindings * pBinding = NULL;
  1042. LPWSTR pDisplayName = NULL;
  1043. DWORD dwCharacteristics;
  1044. ULONG count = 0;
  1045. if( 0 == lstrcmpi( pdName , L"tcp" ) )
  1046. {
  1047. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_TCPIP);
  1048. }
  1049. else if( 0 == lstrcmpi( pdName , L"netbios" ) )
  1050. {
  1051. lstrcpy(szProtocol,NETCFG_SERVICE_CID_MS_NETBIOS);
  1052. }
  1053. else if( 0 == lstrcmpi( pdName, L"ipx" ) )
  1054. {
  1055. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
  1056. }
  1057. else if( 0 == lstrcmpi( pdName , L"spx" ) )
  1058. {
  1059. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWSPX);
  1060. }
  1061. else
  1062. {
  1063. return E_INVALIDARG;
  1064. }
  1065. /*
  1066. * Assumption: No NetBios Lana MAPPING
  1067. */
  1068. //The First entry will be "All Lan Adapters"
  1069. pszDevice = new TCHAR[DEVICENAME_LENGTH];
  1070. if(NULL == pszDevice)
  1071. {
  1072. return E_OUTOFMEMORY;
  1073. }
  1074. length = LoadString(g_hInstance,IDS_ALL_LAN_ADAPTERS, pszDevice, DEVICENAME_LENGTH );
  1075. NumAdapters++;
  1076. if( !DeviceArray.Add(pszDevice) )
  1077. {
  1078. ODS(L"CCfgComp::GetLanAdapterList failed to add device name\n" );
  1079. delete[] pszDevice;
  1080. return E_OUTOFMEMORY;
  1081. }
  1082. do
  1083. {
  1084. ODS( L"CFGBKEND : CoCreateInstance\n" );
  1085. hResult = CoCreateInstance(CLSID_CNetCfg,NULL,CLSCTX_SERVER,IID_INetCfg,(LPVOID *)&pnetCfg);
  1086. if( FAILED( hResult ) )
  1087. {
  1088. ODS( L"CFGBKEND : CoCreateInstance(CLSID_CNetCfg) failed\n" );
  1089. break;
  1090. }
  1091. if( pnetCfg != NULL )
  1092. {
  1093. ODS( L"pnetCfg->Initialize\n" );
  1094. // shaun cox changed the netcfgx.idl file
  1095. // alhen
  1096. hResult = pnetCfg->Initialize( NULL );
  1097. if( FAILED( hResult ) || pnetCfg == NULL )
  1098. {
  1099. ODS( L"CFGBKEND : netCfg::Init failed\n" );
  1100. break;
  1101. }
  1102. if( lstrcmpi( szProtocol , NETCFG_SERVICE_CID_MS_NETBIOS ) == 0 )
  1103. {
  1104. ODS( L"pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETSERVICE\n" );
  1105. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETSERVICE ,IID_INetCfgClass,(void **)&pNetCfgClass);
  1106. if( FAILED( hResult ) || pNetCfgClass == NULL)
  1107. {
  1108. ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
  1109. break;
  1110. }
  1111. }
  1112. else
  1113. {
  1114. ODS( L"pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETTRANS\n" );
  1115. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS ,IID_INetCfgClass,(void **)&pNetCfgClass);
  1116. if( FAILED( hResult ) || pNetCfgClass == NULL)
  1117. {
  1118. ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
  1119. break;
  1120. }
  1121. }
  1122. ODS( L"pnetCfg->QueryNetCfgClass\n" );
  1123. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET ,IID_INetCfgClass,(void **)&pNetCfgClassAdapter);
  1124. if( FAILED( hResult ) || pNetCfgClassAdapter == NULL )
  1125. {
  1126. ODS( L"CFGBKEND : pnetCfg->QueryNetCfgClass failed\n" );
  1127. break;
  1128. }
  1129. ODS( L"pNetCfgClass->FindComponent\n");
  1130. hResult = pNetCfgClass->FindComponent(szProtocol,&pNetCfgComponentprot);
  1131. if( FAILED( hResult ) || pNetCfgComponentprot == NULL)
  1132. {
  1133. ODS( L"CFGBKEND : pnetCfg->FindComponent\n" );
  1134. break;
  1135. }
  1136. ODS( L"pNetCfgComponentprot->QueryInterface\n" );
  1137. hResult = pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings,(void **)&pBinding);
  1138. if( FAILED( hResult ) || pBinding == NULL )
  1139. {
  1140. ODS( L"CFGBKEND : pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings ) failed \n " );
  1141. break;
  1142. }
  1143. ODS( L"pNetCfgClassAdapter->EnumComponents\n" );
  1144. hResult = pNetCfgClassAdapter->EnumComponents(&pEnumComponent);
  1145. RELEASEPTR(pNetCfgClassAdapter);
  1146. if( FAILED( hResult ) || pEnumComponent == NULL )
  1147. {
  1148. ODS( L"CFGBKEND : pNetCfgClassAdapter->EnumComponents failed \n" );
  1149. break;
  1150. }
  1151. // hResult = S_OK;
  1152. while(TRUE)
  1153. {
  1154. ODS( L"pEnumComponent->Next(1,&pNetCfgComponent,&count) \n" );
  1155. hr = pEnumComponent->Next(1,&pNetCfgComponent,&count);
  1156. if(count == 0 || NULL == pNetCfgComponent)
  1157. {
  1158. break;
  1159. }
  1160. ODS( L"pNetCfgComponent->GetCharacteristics(&dwCharacteristics) \n" );
  1161. hr = pNetCfgComponent->GetCharacteristics(&dwCharacteristics);
  1162. if( FAILED( hr ) )
  1163. {
  1164. RELEASEPTR(pNetCfgComponent);
  1165. ODS( L"CFGBKEND : pNetCfgComponent->GetCharacteristics failed\n" );
  1166. continue;
  1167. }
  1168. if(dwCharacteristics & NCF_PHYSICAL)
  1169. {
  1170. ODS( L"pBinding->IsBoundTo(pNetCfgComponent)\n" );
  1171. if(S_OK == pBinding->IsBoundTo(pNetCfgComponent))
  1172. {
  1173. ODS( L"pNetCfgComponent->GetDisplayName(&pDisplayName)\n" );
  1174. hResult = pNetCfgComponent->GetDisplayName(&pDisplayName);
  1175. if( FAILED( hResult ) )
  1176. {
  1177. ODS( L"CFGBKEND : pNetCfgComponent->GetDisplayName failed\n");
  1178. RELEASEPTR(pNetCfgComponent);
  1179. continue;
  1180. }
  1181. // this is not a leak Device array copies the ptr
  1182. // and we release towards the end
  1183. pszDevice = new TCHAR[DEVICENAME_LENGTH];
  1184. if(NULL == pszDevice)
  1185. {
  1186. hResult = E_OUTOFMEMORY;
  1187. break;
  1188. }
  1189. lstrcpy(pszDevice,pDisplayName);
  1190. DBGMSG( L"CFGBKEND: Adapter name %ws\n" , pszDevice );
  1191. if( !DeviceArray.Add(pszDevice) )
  1192. {
  1193. ODS( L"CFGBKEND: device name not added to list\n" );
  1194. delete[] pszDevice;
  1195. hResult = E_OUTOFMEMORY;
  1196. break;
  1197. }
  1198. NumAdapters++;
  1199. CoTaskMemFree(pDisplayName);
  1200. }
  1201. }
  1202. RELEASEPTR(pNetCfgComponent);
  1203. }
  1204. }
  1205. }while( 0 );
  1206. ODS( L"RELEASEPTR(pBinding)\n" );
  1207. RELEASEPTR(pBinding);
  1208. ODS( L"RELEASEPTR(pEnumComponent)\n" );
  1209. RELEASEPTR(pEnumComponent);
  1210. ODS( L"RELEASEPTR(pNetCfgComponentprot)\n" );
  1211. RELEASEPTR(pNetCfgComponentprot);
  1212. ODS( L"RELEASEPTR(pNetCfgComponent)\n" );
  1213. RELEASEPTR(pNetCfgComponent);
  1214. ODS( L"RELEASEPTR(pNetCfgClass)\n" );
  1215. RELEASEPTR(pNetCfgClass);
  1216. if( pnetCfg != NULL )
  1217. {
  1218. pnetCfg->Uninitialize();
  1219. }
  1220. ODS( L"RELEASEPTR(pnetCfg)\n" );
  1221. RELEASEPTR(pnetCfg);
  1222. if( SUCCEEDED( hResult ) )
  1223. {
  1224. //Allocate Memory using CoTaskMemAlloc and copy data
  1225. *ppData = (WCHAR *)CoTaskMemAlloc(NumAdapters * sizeof(TCHAR) * DEVICENAME_LENGTH);
  1226. if(*ppData == NULL)
  1227. {
  1228. hResult = E_OUTOFMEMORY;
  1229. }
  1230. else
  1231. {
  1232. pTempPointer = (DEVICENAMEW *)(*ppData);
  1233. for(int i=0; i<NumAdapters; i++)
  1234. {
  1235. lstrcpy(pTempPointer[i],(TCHAR *)DeviceArray[i]);
  1236. }
  1237. }
  1238. }
  1239. for(int i=0;i < DeviceArray.GetSize();i++)
  1240. {
  1241. ODS( L"Deleteing DeviceArray\n" );
  1242. // I told u so.
  1243. delete [] DeviceArray[i];
  1244. }
  1245. *pNumAdapters = NumAdapters;
  1246. return hResult;
  1247. }
  1248. /***************************************************************************************************************
  1249. Name: GetLanAdapterList2
  1250. Purpose: Gets the List of Lan Adapters associated with a given protocol
  1251. Determine if lan ids are valid
  1252. Returns: HRESULT.
  1253. Params:
  1254. in: pdName - Name of the protocol.
  1255. out: pNumAdapters: pointer to the number of Lan adapters returned
  1256. ppGuidtbl:
  1257. GUIDTBL
  1258. -----------------------------
  1259. DispName display name [ 128 ]
  1260. guidNIC 32 byte buffer
  1261. dwLana value is set if regkey entry exist otherwise it will be created in the order obtained
  1262. dwStatus Any errors reported on a particular guid entry
  1263. -----------------------------
  1264. ****************************************************************************************************************/
  1265. STDMETHODIMP CCfgComp::GetLanAdapterList2(WCHAR * pdName, ULONG * pNumAdapters , PGUIDTBL *ppGuidtbl )
  1266. {
  1267. HRESULT hResult = S_OK;
  1268. int nMaxLanAdapters = 4;
  1269. //If not initialized return error
  1270. if(!m_bInitialized)
  1271. {
  1272. ODS( L"CCfgComp::GetLanAdapterList2 returned CFGBKEND_E_NOT_INITIALIZED\n" );
  1273. return CFGBKEND_E_NOT_INITIALIZED;
  1274. }
  1275. if(NULL == pdName || NULL == pNumAdapters )
  1276. {
  1277. ODS( L"CCfgComp::GetLanAdapterList2 returned INVALIDARG \n" );
  1278. return E_INVALIDARG;
  1279. }
  1280. *pNumAdapters = 0;
  1281. int NumAdapters = 0;
  1282. //
  1283. *ppGuidtbl = ( PGUIDTBL )CoTaskMemAlloc( sizeof( GUIDTBL ) * nMaxLanAdapters );
  1284. if( *ppGuidtbl == NULL )
  1285. {
  1286. return E_OUTOFMEMORY;
  1287. }
  1288. ZeroMemory( *ppGuidtbl , sizeof( GUIDTBL ) * nMaxLanAdapters );
  1289. //Interface pointer declarations
  1290. TCHAR szProtocol[256];
  1291. INetCfg * pnetCfg = NULL;
  1292. INetCfgClass * pNetCfgClass = NULL;
  1293. INetCfgClass * pNetCfgClassAdapter = NULL;
  1294. INetCfgComponent * pNetCfgComponent = NULL;
  1295. INetCfgComponent * pNetCfgComponentprot = NULL;
  1296. IEnumNetCfgComponent * pEnumComponent = NULL;
  1297. INetCfgComponentBindings * pBinding = NULL;
  1298. LPWSTR pDisplayName = NULL;
  1299. DWORD dwCharacteristics;
  1300. ULONG count = 0;
  1301. if( 0 == lstrcmpi( pdName , L"tcp" ) )
  1302. {
  1303. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_TCPIP);
  1304. }
  1305. else if( 0 == lstrcmpi( pdName , L"netbios" ) )
  1306. {
  1307. lstrcpy(szProtocol,NETCFG_SERVICE_CID_MS_NETBIOS);
  1308. }
  1309. else if( 0 == lstrcmpi( pdName, L"ipx" ) )
  1310. {
  1311. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
  1312. }
  1313. else if( 0 == lstrcmpi( pdName , L"spx" ) )
  1314. {
  1315. //lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWSPX);
  1316. lstrcpy(szProtocol,NETCFG_TRANS_CID_MS_NWIPX);
  1317. }
  1318. else
  1319. {
  1320. return E_INVALIDARG;
  1321. }
  1322. /*
  1323. * Assumption: No NetBios Lana MAPPING
  1324. */
  1325. //The First entry will be "All Lan Adapters"
  1326. if( lstrcmpi( pdName , L"netbios" ) != 0 )
  1327. {
  1328. LoadString( g_hInstance , IDS_ALL_LAN_ADAPTERS , (*ppGuidtbl )[0].DispName , DEVICENAME_LENGTH );
  1329. NumAdapters++;
  1330. }
  1331. do
  1332. {
  1333. ODS( L"CFGBKEND:GetLanAdapterList2 CoCreateInstance\n" );
  1334. hResult = CoCreateInstance(CLSID_CNetCfg,NULL,CLSCTX_SERVER,IID_INetCfg,(LPVOID *)&pnetCfg);
  1335. if( FAILED( hResult ) )
  1336. {
  1337. ODS( L"CFGBKEND:GetLanAdapterList2 CoCreateInstance(CLSID_CNetCfg) failed\n" );
  1338. break;
  1339. }
  1340. if( pnetCfg != NULL )
  1341. {
  1342. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->Initialize\n" );
  1343. // shaun cox changed the netcfgx.idl file
  1344. // alhen
  1345. hResult = pnetCfg->Initialize( NULL );
  1346. if( FAILED( hResult ) )
  1347. {
  1348. ODS( L"CFGBKEND:GetLanAdapterList2 netCfg::Init failed\n" );
  1349. break;
  1350. }
  1351. if( lstrcmpi( szProtocol , NETCFG_SERVICE_CID_MS_NETBIOS ) == 0 )
  1352. {
  1353. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETSERVICE\n" );
  1354. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETSERVICE ,IID_INetCfgClass,(void **)&pNetCfgClass);
  1355. if( FAILED( hResult ) || pNetCfgClass == NULL)
  1356. {
  1357. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
  1358. break;
  1359. }
  1360. }
  1361. else
  1362. {
  1363. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass for GUID_DEVCLASS_NETTRANS\n" );
  1364. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS ,IID_INetCfgClass,(void **)&pNetCfgClass);
  1365. if( FAILED( hResult ) || pNetCfgClass == NULL)
  1366. {
  1367. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
  1368. break;
  1369. }
  1370. }
  1371. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass\n" );
  1372. hResult = pnetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NET ,IID_INetCfgClass,(void **)&pNetCfgClassAdapter);
  1373. if( FAILED( hResult ) || pNetCfgClassAdapter == NULL )
  1374. {
  1375. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->QueryNetCfgClass failed\n" );
  1376. break;
  1377. }
  1378. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClass->FindComponent\n");
  1379. hResult = pNetCfgClass->FindComponent(szProtocol,&pNetCfgComponentprot);
  1380. if( FAILED( hResult ) || pNetCfgComponentprot == NULL)
  1381. {
  1382. ODS( L"CFGBKEND:GetLanAdapterList2 pnetCfg->FindComponent\n" );
  1383. break;
  1384. }
  1385. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponentprot->QueryInterface\n" );
  1386. hResult = pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings,(void **)&pBinding);
  1387. if( FAILED( hResult ) || pBinding == NULL )
  1388. {
  1389. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponentprot->QueryInterface(IID_INetCfgComponentBindings ) failed \n " );
  1390. break;
  1391. }
  1392. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClassAdapter->EnumComponents\n" );
  1393. hResult = pNetCfgClassAdapter->EnumComponents(&pEnumComponent);
  1394. RELEASEPTR(pNetCfgClassAdapter);
  1395. if( FAILED( hResult ) || pEnumComponent == NULL )
  1396. {
  1397. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgClassAdapter->EnumComponents failed \n" );
  1398. break;
  1399. }
  1400. // hResult = S_OK;
  1401. while(TRUE)
  1402. {
  1403. ODS( L"CFGBKEND:GetLanAdapterList2 pEnumComponent->Next(1,&pNetCfgComponent,&count) \n" );
  1404. hResult = pEnumComponent->Next(1,&pNetCfgComponent,&count);
  1405. if(count == 0 || NULL == pNetCfgComponent)
  1406. {
  1407. break;
  1408. }
  1409. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetCharacteristics(&dwCharacteristics) \n" );
  1410. hResult = pNetCfgComponent->GetCharacteristics(&dwCharacteristics);
  1411. if( FAILED( hResult ) )
  1412. {
  1413. RELEASEPTR(pNetCfgComponent);
  1414. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetCharacteristics failed\n" );
  1415. continue;
  1416. }
  1417. DBGMSG( L"dwCharacteritics are 0x%x\n", dwCharacteristics );
  1418. if((dwCharacteristics & NCF_PHYSICAL) ||
  1419. ((dwCharacteristics & NCF_VIRTUAL) && !(dwCharacteristics & NCF_HIDDEN)))
  1420. {
  1421. ODS( L"CFGBKEND:GetLanAdapterList2 pBinding->IsBoundTo(pNetCfgComponent)\n" );
  1422. if(S_OK == pBinding->IsBoundTo(pNetCfgComponent))
  1423. {
  1424. if( NumAdapters >= nMaxLanAdapters )
  1425. {
  1426. // add four more adapters
  1427. nMaxLanAdapters += 4;
  1428. *ppGuidtbl = ( PGUIDTBL )CoTaskMemRealloc( *ppGuidtbl , sizeof( GUIDTBL ) * nMaxLanAdapters );
  1429. if( *ppGuidtbl == NULL )
  1430. {
  1431. RELEASEPTR(pNetCfgComponent);
  1432. return E_OUTOFMEMORY;
  1433. }
  1434. }
  1435. ULONG ulDeviceStatus = 0;
  1436. hResult = pNetCfgComponent->GetDeviceStatus( &ulDeviceStatus );
  1437. if( FAILED( hResult ) )
  1438. {
  1439. DBGMSG( L"CFGBKEND:GetLanAdapterList2 GetDevice failed with 0x%x\n" , hResult );
  1440. RELEASEPTR(pNetCfgComponent);
  1441. continue;
  1442. }
  1443. DBGMSG( L"GetDevice status returned 0x%x\n" , ulDeviceStatus );
  1444. if( ulDeviceStatus == CM_PROB_DEVICE_NOT_THERE )
  1445. {
  1446. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDeviceStatus PNP device not there\n");
  1447. RELEASEPTR(pNetCfgComponent);
  1448. continue;
  1449. }
  1450. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDisplayName\n" );
  1451. hResult = pNetCfgComponent->GetDisplayName(&pDisplayName);
  1452. if( FAILED( hResult ) )
  1453. {
  1454. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetDisplayName failed\n");
  1455. RELEASEPTR(pNetCfgComponent);
  1456. continue;
  1457. }
  1458. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetInstanceGuid\n" );
  1459. hResult = pNetCfgComponent->GetInstanceGuid( & ( ( *ppGuidtbl )[ NumAdapters ].guidNIC ) );
  1460. if( FAILED( hResult ) )
  1461. {
  1462. ODS( L"CFGBKEND:GetLanAdapterList2 pNetCfgComponent->GetInstanceGuid failed\n");
  1463. RELEASEPTR(pNetCfgComponent);
  1464. continue;
  1465. }
  1466. lstrcpy( ( *ppGuidtbl )[ NumAdapters ].DispName , pDisplayName );
  1467. // the lana value will be adjusted if guid entry exist
  1468. // ( *ppGuidtbl )[ NumAdapters ].dwLana = ( DWORD )NumAdapters;
  1469. NumAdapters++;
  1470. CoTaskMemFree(pDisplayName);
  1471. }
  1472. }
  1473. RELEASEPTR(pNetCfgComponent);
  1474. }
  1475. }
  1476. }while( 0 );
  1477. ODS( L"RELEASEPTR(pBinding)\n" );
  1478. RELEASEPTR(pBinding);
  1479. ODS( L"RELEASEPTR(pEnumComponent)\n" );
  1480. RELEASEPTR(pEnumComponent);
  1481. ODS( L"RELEASEPTR(pNetCfgComponentprot)\n" );
  1482. RELEASEPTR(pNetCfgComponentprot);
  1483. ODS( L"RELEASEPTR(pNetCfgComponent)\n" );
  1484. RELEASEPTR(pNetCfgComponent);
  1485. ODS( L"RELEASEPTR(pNetCfgClass)\n" );
  1486. RELEASEPTR(pNetCfgClass);
  1487. if( pnetCfg != NULL )
  1488. {
  1489. pnetCfg->Uninitialize();
  1490. }
  1491. ODS( L"RELEASEPTR(pnetCfg)\n" );
  1492. RELEASEPTR(pnetCfg);
  1493. if( SUCCEEDED( hResult ) )
  1494. {
  1495. //
  1496. // Verify the existence of the guidtable and its entries
  1497. // also re-assign lana ids.
  1498. //
  1499. VerifyGuidsExistence( ppGuidtbl , ( int )NumAdapters , pdName );
  1500. }
  1501. *pNumAdapters = NumAdapters;
  1502. return hResult;
  1503. }
  1504. /***************************************************************************************************************
  1505. Name: VerifyGuidsExistence
  1506. Purpose: Determines the existence of the guid entries and reassigns lana ids
  1507. Note: ppGuidtbl passed in is valid
  1508. Returns: void
  1509. Params: [in] GUIDTBL **
  1510. [in] number of guid entries
  1511. ***************************************************************************************************************/
  1512. void CCfgComp::VerifyGuidsExistence( PGUIDTBL *ppGuidtbl , int cItems , WCHAR *pdName )
  1513. {
  1514. HKEY hKey;
  1515. DWORD dwStatus;
  1516. TCHAR tchRootKey[ MAX_PATH ];
  1517. TCHAR tchGuid[ 40 ];
  1518. ODS( L"CFGBKEND:VerifyGuidsExistence\n" );
  1519. int nStart = 1;
  1520. if( lstrcmpi( pdName , L"netbios" ) == 0 )
  1521. {
  1522. nStart = 0;
  1523. }
  1524. for( int idx = nStart ; idx < cItems ; ++idx )
  1525. {
  1526. lstrcpy( tchRootKey , REG_GUID_TABLE );
  1527. StringFromGUID2( ( *ppGuidtbl )[ idx ].guidNIC , tchGuid , ARRAYSIZE( tchGuid ) );
  1528. lstrcat( tchRootKey , tchGuid );
  1529. dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE , tchRootKey , 0 , KEY_READ , &hKey );
  1530. ( *ppGuidtbl )[ idx ].dwStatus = dwStatus;
  1531. if( dwStatus == ERROR_SUCCESS )
  1532. {
  1533. DWORD dwSize = sizeof( DWORD );
  1534. RegQueryValueEx( hKey , LANA_ID , NULL , NULL , ( LPBYTE ) &( ( *ppGuidtbl )[ idx ].dwLana ) , &dwSize );
  1535. DBGMSG( L"CFGBKEND: VerifyGuidsExistence LanaId retrieved = %d\n" , ( *ppGuidtbl )[ idx ].dwLana );
  1536. }
  1537. else
  1538. {
  1539. ODS( L"CFGBKEND: VerifyGuidsExistence NIC must be new\n" );
  1540. ( *ppGuidtbl )[ idx ].dwLana = 0 ;
  1541. }
  1542. RegCloseKey( hKey );
  1543. }
  1544. return;
  1545. }
  1546. /***************************************************************************************************************
  1547. Name: BuildGuidTable
  1548. Purpose: Given valid table entries reconstruct table
  1549. Note: ppGuidtbl passed in is valid and 1 base
  1550. Returns: HRESULT
  1551. Params: [in] GUIDTBL **
  1552. [in] number of guid entries
  1553. ***************************************************************************************************************/
  1554. HRESULT CCfgComp::BuildGuidTable( PGUIDTBL *ppGuidtbl , int cItems , WCHAR *pdName )
  1555. {
  1556. HKEY hKey;
  1557. HKEY hSubKey;
  1558. DWORD dwStatus;
  1559. DWORD dwDisp;
  1560. DWORD dwSize = sizeof( DWORD );
  1561. TCHAR tchRootKey[ MAX_PATH ];
  1562. TCHAR tchGuid[ 40 ];
  1563. DWORD rgdwOldLanaIds[ 256 ] = { 0 }; // man what machine will hold 256 nics?
  1564. // get last lanaIndex
  1565. dwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE , REG_GUID_TABLE , 0 , KEY_READ , &hKey );
  1566. DWORD dwMaxIdVal = 0;
  1567. DWORD dwVal = 0;
  1568. int nOldAdapters = 0;
  1569. if( dwStatus == ERROR_SUCCESS )
  1570. {
  1571. do
  1572. {
  1573. dwStatus = RegEnumKey( hKey , nOldAdapters , tchGuid , sizeof( tchGuid ) / sizeof( TCHAR ) );
  1574. if( dwStatus != ERROR_SUCCESS )
  1575. {
  1576. break;
  1577. }
  1578. if( RegOpenKeyEx( hKey , tchGuid , 0 , KEY_READ , &hSubKey ) == ERROR_SUCCESS )
  1579. {
  1580. RegQueryValueEx( hSubKey , LANA_ID , NULL , NULL , ( LPBYTE ) &dwVal , &dwSize );
  1581. rgdwOldLanaIds[ nOldAdapters ] = dwVal;
  1582. // calculate max value
  1583. if( dwMaxIdVal < dwVal )
  1584. {
  1585. dwMaxIdVal = dwVal;
  1586. }
  1587. RegCloseKey( hSubKey );
  1588. }
  1589. nOldAdapters++;
  1590. _ASSERTE( nOldAdapters < 256 );
  1591. } while( 1 );
  1592. RegCloseKey( hKey );
  1593. }
  1594. // remove old table
  1595. RecursiveDeleteKey( HKEY_LOCAL_MACHINE , REG_GUID_TABLE_T );
  1596. // create new table
  1597. int nStart = 1;
  1598. if( lstrcmpi( pdName , L"netbios" ) == 0 )
  1599. {
  1600. nStart = 0;
  1601. }
  1602. for( int idx = nStart ; idx < cItems ; ++idx )
  1603. {
  1604. lstrcpy( tchRootKey , REG_GUID_TABLE );
  1605. StringFromGUID2( ( *ppGuidtbl )[ idx ].guidNIC , tchGuid , ARRAYSIZE( tchGuid ) );
  1606. lstrcat( tchRootKey , tchGuid );
  1607. // modify lana id
  1608. if( ( *ppGuidtbl )[ idx ].dwStatus != ERROR_SUCCESS )
  1609. {
  1610. ( *ppGuidtbl )[ idx ].dwLana = 0;
  1611. AdjustLanaId( ppGuidtbl , cItems , idx , &dwMaxIdVal , rgdwOldLanaIds , &nOldAdapters , nStart );
  1612. }
  1613. dwStatus = RegCreateKeyEx( HKEY_LOCAL_MACHINE , tchRootKey , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_READ|KEY_WRITE , NULL , &hKey , &dwDisp );
  1614. ( *ppGuidtbl )[ idx ].dwStatus = dwStatus;
  1615. if( dwStatus == ERROR_SUCCESS )
  1616. {
  1617. RegSetValueEx( hKey , LANA_ID , 0 , REG_DWORD , ( LPBYTE )& ( ( *ppGuidtbl )[ idx ].dwLana ) , sizeof( DWORD ) );
  1618. RegCloseKey( hKey );
  1619. }
  1620. }
  1621. return S_OK;
  1622. }
  1623. /*-----------------------------------------------------------------------------------------------
  1624. AdjustLanaId
  1625. PARAMETERS: pGuidtbl : Table of queried entries
  1626. cItems : Number of items in list
  1627. idx : Entry to modify lana
  1628. pdwMaxIndex : New max value of lana index
  1629. NOTES: Since Lana is a dword; after 2^32-1 iterations lana ids will recycle to
  1630. the first available entry
  1631. -----------------------------------------------------------------------------------------------*/
  1632. HRESULT CCfgComp::AdjustLanaId( PGUIDTBL *ppGuidtbl , int cItems , int idx , PDWORD pdwMaxId , PDWORD pdwOldLanaIds , int* pnOldItems , int nStart )
  1633. {
  1634. // find the maxium value for the lana_id
  1635. for( int i = nStart ; i < cItems ; ++i )
  1636. {
  1637. if( *pdwMaxId < ( *ppGuidtbl )[ i ].dwLana )
  1638. {
  1639. *pdwMaxId = ( *ppGuidtbl )[ i ].dwLana ;
  1640. }
  1641. }
  1642. *pdwMaxId = *pdwMaxId + 1;
  1643. // check for overflow max id will be 0xfffffffe
  1644. if( *pdwMaxId == ( DWORD )-1 )
  1645. {
  1646. *pdwMaxId = 1;
  1647. do
  1648. {
  1649. for( i = 0 ; i < *pnOldItems; ++i )
  1650. {
  1651. if( *pdwMaxId == pdwOldLanaIds[ i ] )
  1652. {
  1653. *pdwMaxId = *pdwMaxId + 1;
  1654. break;
  1655. }
  1656. }
  1657. if( i >= *pnOldItems )
  1658. {
  1659. // no duplicate found use the current maxid
  1660. break;
  1661. }
  1662. } while( 1 );
  1663. }
  1664. ( *ppGuidtbl )[ idx ].dwLana = *pdwMaxId;
  1665. // add new entry to the old table
  1666. if( *pnOldItems < 256 )
  1667. {
  1668. pdwOldLanaIds[ *pnOldItems ] = *pdwMaxId;
  1669. *pnOldItems = *pnOldItems + 1;
  1670. }
  1671. return S_OK;
  1672. }
  1673. //----------------------------------------------------------------------------------------------
  1674. // Delete a key and all of its descendents.
  1675. //----------------------------------------------------------------------------------------------
  1676. DWORD RecursiveDeleteKey( HKEY hKeyParent , LPTSTR lpszKeyChild )
  1677. {
  1678. // Open the child.
  1679. HKEY hKeyChild;
  1680. DWORD dwRes = RegOpenKeyEx(hKeyParent, lpszKeyChild , 0 , KEY_WRITE | KEY_READ, &hKeyChild);
  1681. if (dwRes != ERROR_SUCCESS)
  1682. {
  1683. return dwRes;
  1684. }
  1685. // Enumerate all of the decendents of this child.
  1686. FILETIME time;
  1687. TCHAR szBuffer[256];
  1688. DWORD dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
  1689. while( RegEnumKeyEx( hKeyChild , 0 , szBuffer , &dwSize , NULL , NULL , NULL , &time ) == S_OK )
  1690. {
  1691. // Delete the decendents of this child.
  1692. dwRes = RecursiveDeleteKey(hKeyChild, szBuffer);
  1693. if (dwRes != ERROR_SUCCESS)
  1694. {
  1695. RegCloseKey(hKeyChild);
  1696. return dwRes;
  1697. }
  1698. dwSize = sizeof( szBuffer ) / sizeof( TCHAR );
  1699. }
  1700. // Close the child.
  1701. RegCloseKey( hKeyChild );
  1702. // Delete this child.
  1703. return RegDeleteKey( hKeyParent , lpszKeyChild );
  1704. }
  1705. /***************************************************************************************************************
  1706. Name: SetUserConfig
  1707. Purpose: Sets the UserConfig for a Winstation
  1708. Returns: HRESULT.
  1709. Params:
  1710. in: pWSName - Name of the Winstation.
  1711. pUserConfig - Pointer to the UserConfig to be set
  1712. ****************************************************************************************************************/
  1713. STDMETHODIMP CCfgComp::SetUserConfig(PWINSTATIONNAMEW pWsName, ULONG /*size*/, PUSERCONFIG pUserConfig , PDWORD pdwStatus)
  1714. {
  1715. *pdwStatus = ERROR_INVALID_PARAMETER;
  1716. //If not initialized return error
  1717. if(!m_bInitialized)
  1718. return CFGBKEND_E_NOT_INITIALIZED;
  1719. //Check if the caller has write permissions.
  1720. if( !m_bAdmin)
  1721. {
  1722. *pdwStatus = ERROR_ACCESS_DENIED;
  1723. ODS( L"CFGBKEND: ERROR_ACCESS_DENIED\n" );
  1724. return E_ACCESSDENIED;
  1725. }
  1726. //Check the parameters for NULL
  1727. if(NULL == pWsName || NULL == pUserConfig)
  1728. {
  1729. return E_INVALIDARG;
  1730. }
  1731. //Check for the validity of the Winstation name
  1732. if(NULL == GetWSObject(pWsName))
  1733. {
  1734. *pdwStatus = ERROR_INVALID_NAME;
  1735. return E_INVALIDARG;
  1736. }
  1737. *pdwStatus = RegCreateUserConfigW(NULL, pWsName, pUserConfig);
  1738. return S_OK;
  1739. }
  1740. /***************************************************************************************************************
  1741. Name: EnableWinstation
  1742. Purpose: Enables/Disables a given Winstation
  1743. Returns: HRESULT.
  1744. Params:
  1745. in: pWSName - Name of the Winstation.
  1746. fEnable - TRUE: Enable, FALSE:Disable
  1747. ****************************************************************************************************************/
  1748. STDMETHODIMP CCfgComp::EnableWinstation(PWINSTATIONNAMEW pWSName, BOOL fEnable)
  1749. {
  1750. WINSTATIONCONFIG2W WsConfig;
  1751. LONG Status;
  1752. ULONG Length;
  1753. //If not initialized return error
  1754. if(!m_bInitialized)
  1755. return CFGBKEND_E_NOT_INITIALIZED;
  1756. //Check if the caller has write permissions.
  1757. if(!m_bAdmin)
  1758. return E_ACCESSDENIED;
  1759. //Check the parametes for NULL
  1760. if(NULL == pWSName)
  1761. return E_INVALIDARG;
  1762. //Check for the validity of the Winstation name, this would eliminate the system console
  1763. if(NULL == GetWSObject(pWSName))
  1764. return E_INVALIDARG;
  1765. // Query the registry for WinStation data
  1766. Status = RegWinStationQueryW( NULL,pWSName,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
  1767. if(Status)
  1768. return E_FAIL;
  1769. WsConfig.Create.fEnableWinStation = fEnable;
  1770. Status = RegWinStationCreateW(NULL,pWSName,FALSE,&WsConfig,sizeof(WsConfig));
  1771. if ( Status)
  1772. return E_FAIL;
  1773. return S_OK;
  1774. }
  1775. /***************************************************************************************************************
  1776. Name: RenameWinstation
  1777. Purpose: Renames a given Winstation
  1778. Returns: HRESULT.
  1779. Params:
  1780. in: pOldWinstation - Name of the Winstation to be renamed.
  1781. pNewWinstation - New Name for the Winstation
  1782. ****************************************************************************************************************/
  1783. STDMETHODIMP CCfgComp::RenameWinstation(PWINSTATIONNAMEW pOldWinstation, PWINSTATIONNAMEW pNewWinstation)
  1784. {
  1785. WINSTATIONCONFIG2W WsConfig;
  1786. LONG Status, size = 0;
  1787. ULONG Length; BOOL Unique;
  1788. void * pExtObject = NULL;
  1789. void * pExtDupObject = NULL;
  1790. HRESULT hResult = S_OK;
  1791. PWD pWD = NULL;
  1792. PWS pWS = NULL;
  1793. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  1794. //If not initialized return error
  1795. if(!m_bInitialized)
  1796. return CFGBKEND_E_NOT_INITIALIZED;
  1797. //Check if the caller has write permissions.
  1798. if(!m_bAdmin)
  1799. return E_ACCESSDENIED;
  1800. //Check the parametes for NULL
  1801. if(NULL == pOldWinstation || NULL == pNewWinstation)
  1802. return E_INVALIDARG;
  1803. //Check winstation names are of valid lengths
  1804. if ( lstrlen(pOldWinstation) > WINSTATIONNAME_LENGTH || lstrlen(pNewWinstation) > WINSTATIONNAME_LENGTH )
  1805. return E_INVALIDARG;
  1806. IsWSNameUnique(pNewWinstation,&Unique);
  1807. if(!Unique)
  1808. return E_INVALIDARG;
  1809. //The new Winstation Name cannot be Console
  1810. if(0 ==(lstrcmpi(pNewWinstation,m_szConsole)))
  1811. return E_INVALIDARG;
  1812. //Check the length of the new winstation name
  1813. if(lstrlen(pNewWinstation) > WINSTATIONNAME_LENGTH)
  1814. return E_INVALIDARG;
  1815. //Check for the validity of the Winstation name, this would eliminate the system console
  1816. pWS = GetWSObject(pOldWinstation);
  1817. if(NULL == pWS)
  1818. return E_INVALIDARG;
  1819. //Get the WD object associated with this Winstation.
  1820. pWD = GetWdObject(pWS->wdName);
  1821. if(NULL == pWD)
  1822. return E_FAIL;
  1823. //Query the registry for WinStation data
  1824. Status = RegWinStationQueryW(NULL,pOldWinstation,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
  1825. if(Status)
  1826. return E_FAIL;
  1827. //Get the ExtensionObject data(third party) this will be used for Creating and Deleting the registry keys.
  1828. if(pWD->lpfnExtRegQuery && pWD->hExtensionDLL)
  1829. {
  1830. pExtObject = (pWD->lpfnExtRegQuery)(pOldWinstation, &(WsConfig.Pd[0]));
  1831. }
  1832. // Get the Security descriptor for the old Winstation
  1833. // Must free pSecurityDescriptor via LocalFree]
  1834. // check to see if previous winstation had a security key defined --
  1835. // we do this so that if the default security was used we don't
  1836. // create a "security" keyvalue in the new winstation
  1837. HKEY hKeyWinstation;
  1838. HKEY hKeyWinstationName;
  1839. if( RegOpenKeyEx(
  1840. HKEY_LOCAL_MACHINE ,
  1841. WINSTATION_REG_NAME,
  1842. 0,
  1843. KEY_READ,
  1844. &hKeyWinstation ) == ERROR_SUCCESS)
  1845. {
  1846. if( RegOpenKeyEx(
  1847. hKeyWinstation ,
  1848. pOldWinstation ,
  1849. 0 ,
  1850. KEY_READ,
  1851. &hKeyWinstationName ) == ERROR_SUCCESS)
  1852. {
  1853. if( RegQueryValueEx(
  1854. hKeyWinstationName ,
  1855. L"Security" ,
  1856. NULL ,
  1857. NULL ,
  1858. NULL ,
  1859. NULL ) == ERROR_SUCCESS )
  1860. {
  1861. hResult = GetSecurityDescriptor(
  1862. pOldWinstation ,
  1863. &size ,
  1864. &pSecurityDescriptor );
  1865. }
  1866. RegCloseKey( hKeyWinstationName );
  1867. }
  1868. RegCloseKey( hKeyWinstation );
  1869. }
  1870. if( FAILED( hResult ) )
  1871. {
  1872. DBGMSG( L"CFGBKEND!RenameWinstation GetSecurityDescriptor failed 0x%x\n " , hResult );
  1873. return E_FAIL;
  1874. }
  1875. do
  1876. {
  1877. //Create a new registry key with the data.
  1878. Status = RegWinStationCreateW(NULL,pNewWinstation,TRUE,&WsConfig,sizeof(WsConfig));
  1879. if( Status != ERROR_SUCCESS )
  1880. {
  1881. hResult = E_FAIL;
  1882. break;
  1883. }
  1884. //Create new extension data.
  1885. if(pWD->lpfnExtDupObject && pWD->hExtensionDLL && pExtObject)
  1886. {
  1887. pExtDupObject = (pWD->lpfnExtDupObject)(pExtObject);
  1888. if(pWD->lpfnExtRegCreate && pWD->hExtensionDLL && pExtDupObject)
  1889. {
  1890. (pWD->lpfnExtRegCreate)(pNewWinstation,pExtDupObject,TRUE);
  1891. }
  1892. }
  1893. //Set the Security information from the previous Winstation
  1894. if( pSecurityDescriptor != NULL )
  1895. {
  1896. hResult = SetSecurityDescriptor(pNewWinstation,size,pSecurityDescriptor);
  1897. if( FAILED( hResult ) )
  1898. {
  1899. break;
  1900. }
  1901. }
  1902. //delete old extension data
  1903. if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtObject)
  1904. {
  1905. if( ERROR_SUCCESS != ( ( pWD->lpfnExtRegDelete )( pOldWinstation , pExtObject ) ) )
  1906. {
  1907. hResult = CFGBKEND_EXTDELETE_FAILED;
  1908. }
  1909. }
  1910. //Delete old registy key
  1911. Status = RegWinStationDeleteW(NULL,pOldWinstation);
  1912. if( Status != ERROR_SUCCESS )
  1913. {
  1914. //delete the new winstation that was created
  1915. if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtDupObject)
  1916. {
  1917. (pWD->lpfnExtRegDelete)(pNewWinstation,pExtDupObject);
  1918. }
  1919. RegWinStationDeleteW(NULL,pNewWinstation);
  1920. hResult = E_FAIL;
  1921. break;
  1922. }
  1923. //update the object created in the list of winstation objects.
  1924. lstrcpy(pWS->Name, pNewWinstation);
  1925. } while( 0 );
  1926. //Release pSecurityDescriptor Memory
  1927. if( pSecurityDescriptor != NULL )
  1928. {
  1929. LocalFree( pSecurityDescriptor );
  1930. }
  1931. //Delete the Extension Objects.
  1932. if(pWD->lpfnExtDeleteObject && pWD->hExtensionDLL)
  1933. {
  1934. if( pExtObject )
  1935. (pWD->lpfnExtDeleteObject)(pExtObject);
  1936. if(pExtDupObject)
  1937. (pWD->lpfnExtDeleteObject)(pExtDupObject);
  1938. }
  1939. if(hResult == CFGBKEND_EXTDELETE_FAILED)
  1940. {
  1941. if(pWD->lpfnExtRegDelete && pWD->hExtensionDLL && pExtObject)
  1942. (pWD->lpfnExtRegDelete)(pOldWinstation,pExtObject);
  1943. }
  1944. // force termsrv to re-read settings!!!
  1945. hResult = ForceUpdate( );
  1946. return hResult;
  1947. }
  1948. /***************************************************************************************************************
  1949. Name: IsSessionReadOnly
  1950. Purpose: Checks if the Current session readonly.
  1951. Returns: HRESULT.
  1952. Params:
  1953. out: pReadOnly - pointer to whether the current session is readonly.
  1954. ****************************************************************************************************************/
  1955. STDMETHODIMP CCfgComp::IsSessionReadOnly(BOOL * pReadOnly)
  1956. {
  1957. //If not initialized return error
  1958. if(!m_bInitialized)
  1959. return CFGBKEND_E_NOT_INITIALIZED;
  1960. if(NULL == pReadOnly)
  1961. return E_INVALIDARG;
  1962. *pReadOnly = !m_bAdmin;
  1963. return S_OK;
  1964. }
  1965. /***************************************************************************************************************
  1966. Name: UnInitialize
  1967. Purpose: Uninitializes the Object
  1968. Returns: HRESULT.
  1969. Params:
  1970. ****************************************************************************************************************/
  1971. STDMETHODIMP CCfgComp::UnInitialize()
  1972. {
  1973. //If not initialized return error
  1974. if(!m_bInitialized)
  1975. return CFGBKEND_E_NOT_INITIALIZED;
  1976. DeleteWDArray();
  1977. DeleteWSArray();
  1978. m_bInitialized = FALSE;
  1979. return S_OK;
  1980. }
  1981. /***************************************************************************************************************
  1982. Name: DeleteWDArray
  1983. Purpose: Internal function to delete m_WdArray
  1984. Returns: void.
  1985. Params:
  1986. ****************************************************************************************************************/
  1987. void CCfgComp::DeleteWDArray()
  1988. {
  1989. for(int i = 0; i < m_WDArray.GetSize();i++)
  1990. {
  1991. PWD pWd = ( PWD )m_WDArray[ i ];
  1992. if( pWd != NULL )
  1993. {
  1994. if( pWd->hExtensionDLL != NULL )
  1995. {
  1996. // ODS( L"Freeing extension dll\n" );
  1997. FreeLibrary( pWd->hExtensionDLL );
  1998. }
  1999. for( int j = 0 ; j < pWd->PDConfigArray.GetSize( ); j++ )
  2000. {
  2001. if( pWd->PDConfigArray[ j ] != NULL )
  2002. {
  2003. delete[] pWd->PDConfigArray[ j ];
  2004. }
  2005. }
  2006. delete[] m_WDArray[i];
  2007. }
  2008. }
  2009. m_WDArray.RemoveAll( );
  2010. return;
  2011. }
  2012. /***************************************************************************************************************
  2013. Name: DeleteWSArray
  2014. Purpose: Internal function to delete m_WSArray
  2015. Returns: void.
  2016. Params:
  2017. ****************************************************************************************************************/
  2018. void CCfgComp::DeleteWSArray()
  2019. {
  2020. for(int i = 0; i <m_WSArray.GetSize();i++)
  2021. {
  2022. if(m_WSArray[i])
  2023. delete [] m_WSArray[i];
  2024. }
  2025. m_WSArray.RemoveAll( );
  2026. return;
  2027. }
  2028. /***************************************************************************************************************
  2029. Name: GetDefaultSecurityDescriptor
  2030. Purpose: Gets the Default Security Descriptor for a Winstation
  2031. Returns: HRESULT.
  2032. Params:
  2033. out: pSize - Size of the allocated buffer
  2034. ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
  2035. ****************************************************************************************************************/
  2036. STDMETHODIMP CCfgComp::GetDefaultSecurityDescriptor(long * pSize, PSECURITY_DESCRIPTOR * ppSecurityDescriptor)
  2037. {
  2038. HRESULT hResult = S_OK;
  2039. //If not initialized return error
  2040. if( !m_bInitialized )
  2041. {
  2042. return CFGBKEND_E_NOT_INITIALIZED;
  2043. }
  2044. if(NULL == pSize || NULL == ppSecurityDescriptor)
  2045. {
  2046. return E_INVALIDARG;
  2047. }
  2048. *pSize = 0;
  2049. *ppSecurityDescriptor = NULL;
  2050. //Try Getting Default Security Descriptor
  2051. hResult = GetWinStationSecurity(TRUE, NULL,(PSECURITY_DESCRIPTOR *)ppSecurityDescriptor);
  2052. if(SUCCEEDED(hResult) && *ppSecurityDescriptor != NULL )
  2053. {
  2054. *pSize = GetSecurityDescriptorLength( *ppSecurityDescriptor );
  2055. }
  2056. return hResult;
  2057. }
  2058. /***************************************************************************************************************
  2059. Name: UpDateWS
  2060. Purpose: UpDates the Winstation Information
  2061. Returns: HRESULT.
  2062. Params:
  2063. in: winstationInfo - WS
  2064. Data - Data fields to be updated
  2065. ****************************************************************************************************************/
  2066. STDMETHODIMP CCfgComp::UpDateWS( PWS pWinstationInfo, DWORD Data , PDWORD pdwStatus, BOOLEAN bPerformMerger )
  2067. {
  2068. WINSTATIONCONFIG2W WSConfig;
  2069. ULONG Length;
  2070. _ASSERTE( pWinstationInfo != NULL );
  2071. *pdwStatus = 0;
  2072. if( pWinstationInfo == NULL || !( Data & UPDATE_ALL ) )
  2073. {
  2074. return E_INVALIDARG;
  2075. }
  2076. //If not initialized return error
  2077. if(!m_bInitialized)
  2078. return CFGBKEND_E_NOT_INITIALIZED;
  2079. //Check if the caller has write permissions.
  2080. if( !m_bAdmin)
  2081. {
  2082. *pdwStatus = ERROR_ACCESS_DENIED;
  2083. return E_ACCESSDENIED;
  2084. }
  2085. //Check for the validity of the Winstation name, this would eliminate the system console
  2086. if(NULL == GetWSObject( pWinstationInfo->Name ) )
  2087. {
  2088. *pdwStatus = ERROR_INVALID_NAME;
  2089. return E_INVALIDARG;
  2090. }
  2091. // Query the registry for WinStation data
  2092. POLICY_TS_MACHINE p;
  2093. memset(&p, 0, sizeof(POLICY_TS_MACHINE));
  2094. *pdwStatus = RegWinStationQueryEx( NULL, &p, pWinstationInfo->Name,&WSConfig,sizeof(WINSTATIONCONFIG2W), &Length, bPerformMerger);
  2095. if( *pdwStatus != ERROR_SUCCESS )
  2096. {
  2097. return E_FAIL;
  2098. }
  2099. if( Data & UPDATE_LANADAPTER )
  2100. {
  2101. WSConfig.Pd[0].Params.Network.LanAdapter = pWinstationInfo->LanAdapter;
  2102. }
  2103. if( Data & UPDATE_ENABLEWINSTATION )
  2104. {
  2105. WSConfig.Create.fEnableWinStation = pWinstationInfo->fEnableWinstation;
  2106. }
  2107. if( Data & UPDATE_MAXINSTANCECOUNT )
  2108. {
  2109. WSConfig.Create.MaxInstanceCount = pWinstationInfo->uMaxInstanceCount;
  2110. }
  2111. if( Data & UPDATE_COMMENT )
  2112. {
  2113. lstrcpy( WSConfig.Config.Comment , pWinstationInfo->Comment );
  2114. }
  2115. /*
  2116. switch(Data)
  2117. {
  2118. case LANADAPTER:
  2119. WSConfig.Pd[0].Params.Network.LanAdapter = winstationInfo.LanAdapter;
  2120. break;
  2121. case ENABLEWINSTATION:
  2122. WSConfig.Create.fEnableWinStation = winstationInfo.fEnableWinstation;
  2123. break;
  2124. case MAXINSTANCECOUNT:
  2125. WSConfig.Create.MaxInstanceCount = winstationInfo.uMaxInstanceCount;
  2126. break;
  2127. case COMMENT:
  2128. lstrcpy(WSConfig.Config.Comment,winstationInfo.Comment);
  2129. break;
  2130. // case ASYNC:
  2131. // break;
  2132. case ALL:
  2133. WSConfig.Pd[0].Params.Network.LanAdapter = winstationInfo.LanAdapter;
  2134. WSConfig.Create.fEnableWinStation = winstationInfo.fEnableWinstation;
  2135. WSConfig.Create.MaxInstanceCount = winstationInfo.uMaxInstanceCount;
  2136. lstrcpy(WSConfig.Config.Comment,winstationInfo.Comment);
  2137. break;
  2138. default:
  2139. return E_INVALIDARG;
  2140. break;
  2141. }
  2142. */
  2143. *pdwStatus = RegWinStationCreateW( NULL , pWinstationInfo->Name , FALSE , &WSConfig , sizeof( WSConfig ) );
  2144. if( *pdwStatus != ERROR_SUCCESS )
  2145. {
  2146. return E_FAIL;
  2147. }
  2148. // force termsrv to re-read settings!!!
  2149. return ForceUpdate( );
  2150. }
  2151. /***************************************************************************************************************
  2152. Name: GetWSInfo
  2153. Purpose: Gets Information about a Winstation
  2154. Returns: HRESULT.
  2155. Params:
  2156. in: pWSName - Name of the Winstation.
  2157. out: pSize - Size of the allocated buffer
  2158. ppWS - Pointer to the buffer containing the WS
  2159. ****************************************************************************************************************/
  2160. STDMETHODIMP CCfgComp::GetWSInfo(PWINSTATIONNAME pWSName, long * pSize, WS ** ppWS)
  2161. {
  2162. //If not initialized return error
  2163. if(!m_bInitialized)
  2164. return CFGBKEND_E_NOT_INITIALIZED;
  2165. PWS pWS1 = NULL;
  2166. if(NULL == pWSName || NULL == pSize || NULL == ppWS)
  2167. return E_INVALIDARG;
  2168. *ppWS = NULL;
  2169. *pSize = 0;
  2170. pWS1 = GetWSObject(pWSName);
  2171. if(NULL == pWS1)
  2172. return E_INVALIDARG;
  2173. *ppWS = (WS *)CoTaskMemAlloc(sizeof(WS));
  2174. if(NULL == *ppWS)
  2175. return E_OUTOFMEMORY;
  2176. CopyMemory((PVOID)*ppWS,(CONST VOID *)pWS1,sizeof(WS));
  2177. *pSize = sizeof(WS);
  2178. return S_OK;
  2179. }
  2180. /***************************************************************************************************************
  2181. Name: CreateNewWS
  2182. Purpose: Creates a new WS
  2183. Returns: HRESULT.
  2184. Params:
  2185. in: WinstationInfo - Info about new UI.
  2186. UserCnfgSize - Size of the Userconfig Buffer
  2187. pserConfig - Pointer to USERCONFIG.
  2188. pAsyncConfig - Can be NULL if async is not used
  2189. ****************************************************************************************************************/
  2190. STDMETHODIMP CCfgComp::CreateNewWS(WS WinstationInfo, long UserCnfgSize, PUSERCONFIG pUserConfig,PASYNCCONFIGW pAsyncConfig)
  2191. {
  2192. WINSTATIONCONFIG2W WSConfig;
  2193. WDCONFIG2W WdConfig;
  2194. PDCONFIG3W PdConfig;
  2195. BOOL Unique;
  2196. ULONG ByteCount;
  2197. HRESULT hResult = S_OK;
  2198. PWD pWd = NULL;
  2199. DWORD dwStatus = ERROR_SUCCESS;
  2200. //If not initialized return error
  2201. if(!m_bInitialized)
  2202. {
  2203. ODS( L"CFGBKEND : CreateNewWS not initialized\n" );
  2204. return CFGBKEND_E_NOT_INITIALIZED;
  2205. }
  2206. do
  2207. {
  2208. //Check if the caller has write permissions.
  2209. if(!m_bAdmin)
  2210. {
  2211. ODS( L"CFGBKEND : CreateNewWS not Admin\n" );
  2212. hResult = E_ACCESSDENIED;
  2213. break;
  2214. }
  2215. pWd = GetWdObject(WinstationInfo.wdName);
  2216. if(NULL == pWd)
  2217. {
  2218. ODS( L"CFGBKEND : CreateNewWS no WD Object found\n" );
  2219. hResult = E_INVALIDARG;
  2220. break;
  2221. }
  2222. if(UserCnfgSize != sizeof(USERCONFIGW) && pUserConfig == NULL)
  2223. {
  2224. ODS( L"CFGBKEND : CreateNewWS UserConfig invalid\n" );
  2225. hResult = E_INVALIDARG;
  2226. break;
  2227. }
  2228. //See if the Name of the Winstation is Unique
  2229. hResult = IsWSNameUnique(WinstationInfo.Name,&Unique);
  2230. if( FAILED( hResult ) )
  2231. {
  2232. break;
  2233. }
  2234. if(0 == Unique)
  2235. {
  2236. ODS( L"CFGBKEND : CreateNewWS WINSTA name not unique\n" );
  2237. hResult = E_INVALIDARG;
  2238. break;
  2239. }
  2240. //Check the length of the new winstation name
  2241. if(lstrlen(WinstationInfo.Name) > WINSTATIONNAME_LENGTH)
  2242. {
  2243. hResult = E_INVALIDARG;
  2244. break;
  2245. }
  2246. //Now begins the actual work.
  2247. ZeroMemory(&WSConfig, sizeof(WINSTATIONCONFIG2W));
  2248. //WINSTATIONCONFIG2W.Create
  2249. WSConfig.Create.fEnableWinStation = WinstationInfo.fEnableWinstation;
  2250. WSConfig.Create.MaxInstanceCount = WinstationInfo.uMaxInstanceCount;
  2251. //WINSTATIONCONFIG2W.Wd
  2252. dwStatus = RegWdQueryW(NULL,pWd->wdKey, &WdConfig,sizeof(WdConfig),&ByteCount);
  2253. if(ERROR_SUCCESS != dwStatus )
  2254. {
  2255. DBGMSG( L"CFGBKEND : CreateNewWS@RegWdQuery failed with 0x%x\n" , dwStatus );
  2256. hResult = E_FAIL;
  2257. break;
  2258. }
  2259. WSConfig.Wd = WdConfig.Wd;
  2260. //WINSTATIONCONFIG2W.Config
  2261. lstrcpy(WSConfig.Config.Comment,WinstationInfo.Comment);
  2262. CopyMemory( ( PVOID )&WSConfig.Config.User , ( CONST VOID * )pUserConfig , UserCnfgSize );
  2263. //WINSTATIONCONFIG2W.Pd
  2264. dwStatus = RegPdQueryW( NULL , pWd->wdKey , TRUE , WinstationInfo.pdName , &PdConfig , sizeof(PdConfig) , &ByteCount );
  2265. if( ERROR_SUCCESS != dwStatus )
  2266. {
  2267. DBGMSG( L"CFGBKEND : CreateNewWS RegPdQuery failed with 0x%x\n" , dwStatus );
  2268. hResult = E_FAIL;
  2269. break;
  2270. }
  2271. WSConfig.Pd[0].Create = PdConfig.Data;
  2272. WSConfig.Pd[0].Params.SdClass = (SDCLASS)WinstationInfo.PdClass;
  2273. if(SdNetwork == (SDCLASS)WinstationInfo.PdClass)
  2274. {
  2275. WSConfig.Pd[0].Params.Network.LanAdapter = WinstationInfo.LanAdapter;
  2276. }
  2277. else if(SdAsync == (SDCLASS)WinstationInfo.PdClass)
  2278. {
  2279. if(NULL != pAsyncConfig)
  2280. {
  2281. pAsyncConfig->fConnectionDriver = *( pAsyncConfig->ModemName ) ? TRUE : FALSE;
  2282. WSConfig.Pd[0].Params.Async = *pAsyncConfig;
  2283. CDCONFIG cdConfig;
  2284. SetupAsyncCdConfig( pAsyncConfig , &cdConfig );
  2285. if( cdConfig.CdName[ 0 ] != 0 )
  2286. {
  2287. dwStatus = RegCdCreateW( NULL , pWd->wdKey , cdConfig.CdName , TRUE , &cdConfig , sizeof( CDCONFIG ) );
  2288. if( dwStatus != ERROR_SUCCESS )
  2289. {
  2290. DBGMSG( L"CFGBKEND: RegCdCreateW returned 0x%x\n", dwStatus );
  2291. if( dwStatus == ERROR_ALREADY_EXISTS )
  2292. {
  2293. hResult = S_FALSE;
  2294. }
  2295. else if( dwStatus == ERROR_CANTOPEN )
  2296. {
  2297. hResult = E_ACCESSDENIED;
  2298. break;
  2299. }
  2300. else
  2301. {
  2302. hResult = E_FAIL;
  2303. break;
  2304. }
  2305. }
  2306. WSConfig.Cd = cdConfig;
  2307. }
  2308. }
  2309. }
  2310. //Get the additional Pd's. Currently only ICA has this.
  2311. GetPdConfig(pWd->wdKey,WSConfig);
  2312. //Try Creating
  2313. dwStatus = ( DWORD )RegWinStationCreate( NULL , WinstationInfo.Name , TRUE , &WSConfig , sizeof(WINSTATIONCONFIG2) );
  2314. if( dwStatus != ERROR_SUCCESS )
  2315. {
  2316. DBGMSG( L"CFGBKEND : CreateNewWS@RegWinStationCreate failed 0x%x\n" , dwStatus );
  2317. hResult = E_FAIL;
  2318. break;
  2319. }
  2320. //Create the extension Data, Currently only ICA has this
  2321. void * pExtObject = NULL;
  2322. if(pWd->lpfnExtRegQuery && pWd->hExtensionDLL)
  2323. {
  2324. pExtObject = (pWd->lpfnExtRegQuery)(L"", &(WSConfig.Pd[0]));
  2325. }
  2326. if(pExtObject)
  2327. {
  2328. if(pWd->lpfnExtRegCreate)
  2329. {
  2330. (pWd->lpfnExtRegCreate)(WinstationInfo.Name,pExtObject,TRUE);
  2331. }
  2332. }
  2333. //Delete the extension object
  2334. if(pWd->lpfnExtDeleteObject && pExtObject)
  2335. {
  2336. (pWd->lpfnExtDeleteObject )(pExtObject );
  2337. }
  2338. //Add the Winstation to our local list.
  2339. PWS pObject = NULL;
  2340. hResult = InsertInWSArray(WinstationInfo.Name,&WSConfig,&pObject);
  2341. if( SUCCEEDED( hResult ) )
  2342. {
  2343. hResult = ForceUpdate( );
  2344. }
  2345. else
  2346. {
  2347. break;
  2348. }
  2349. }while( 0 );
  2350. return hResult;
  2351. }
  2352. /***************************************************************************************************************
  2353. Name: GetDefaultUserConfig
  2354. Purpose: Gets the Default User Configuration for a given Winstation Driver
  2355. Returns: HRESULT.
  2356. Params:
  2357. in: WdName - Name of the Winstation Driver.
  2358. out: pSize - Size of the allocated buffer
  2359. ppUser - Pointer to the buffer containing the UserConfig
  2360. ****************************************************************************************************************/
  2361. STDMETHODIMP CCfgComp::GetDefaultUserConfig(WCHAR * WdName,long * pSize, PUSERCONFIG * ppUser)
  2362. {
  2363. LONG QStatus;
  2364. WDCONFIG2W WdConfig;
  2365. ULONG ByteCount;
  2366. PWD pWd = NULL;
  2367. //If not initialized return error
  2368. if(!m_bInitialized)
  2369. return CFGBKEND_E_NOT_INITIALIZED;
  2370. if(NULL == pSize || NULL == ppUser || NULL == WdName)
  2371. return E_INVALIDARG;
  2372. pWd = GetWdObject(WdName);
  2373. if(NULL == pWd)
  2374. return E_INVALIDARG;
  2375. if (( QStatus = RegWdQueryW( NULL, pWd->wdKey, &WdConfig,
  2376. sizeof(WdConfig),
  2377. &ByteCount )) != ERROR_SUCCESS )
  2378. return E_FAIL;
  2379. *ppUser = (PUSERCONFIG)CoTaskMemAlloc(sizeof(WdConfig.User));
  2380. if(*ppUser == NULL)
  2381. return E_OUTOFMEMORY;
  2382. CopyMemory((PVOID)*ppUser,(CONST VOID *)&WdConfig.User,sizeof(WdConfig.User));
  2383. *pSize = sizeof(WdConfig.User);
  2384. return S_OK;
  2385. }
  2386. /***************************************************************************************************************
  2387. Name: IsNetWorkConnectionUnique
  2388. Purpose: Checks if the combination of Winstation driver name, LanAdapter and the transport is Unique.
  2389. Returns: HRESULT.
  2390. Params:
  2391. in: WdName - Name of the Winstation Driver.
  2392. PdName - Name of the Transport
  2393. LanAdapter - LanAdapter Index
  2394. out: pUnique - pointer to whether the information is unique or not.
  2395. ****************************************************************************************************************/
  2396. STDMETHODIMP CCfgComp::IsNetWorkConnectionUnique(WCHAR * WdName, WCHAR * PdName, ULONG LanAdapter, BOOL * pUnique)
  2397. {
  2398. //If not initialized return error
  2399. if( !m_bInitialized )
  2400. {
  2401. return CFGBKEND_E_NOT_INITIALIZED;
  2402. }
  2403. //Check for uniqueness of this combination,
  2404. //Transport, Type , LanAdapter
  2405. if( NULL == WdName || NULL == PdName || NULL == pUnique )
  2406. {
  2407. return E_INVALIDARG;
  2408. }
  2409. *pUnique = TRUE;
  2410. int nSize = m_WSArray.GetSize();
  2411. for(int i = 0; i < nSize; i++ )
  2412. {
  2413. if(lstrcmpi(WdName,((WS *)(m_WSArray[i]))->wdName) == 0 )
  2414. {
  2415. if(lstrcmpi(PdName,((WS *)(m_WSArray[i]))->pdName) == 0)
  2416. {
  2417. // Make sure there's not a lanadapter configured for all settings
  2418. if( ( LanAdapter == 0 ) ||
  2419. ( LanAdapter == ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter ) ||
  2420. ( ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter == 0 ) )
  2421. //( oldLanAdapter != ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter && ( ( WS * )( m_WSArray[ i ] ) )->LanAdapter == 0 ) )
  2422. {
  2423. *pUnique = FALSE;
  2424. break;
  2425. }
  2426. }
  2427. }
  2428. }
  2429. return S_OK;
  2430. }
  2431. /***************************************************************************************************************
  2432. Name: DeleteWS
  2433. Purpose: Deletes a given Winstation
  2434. Returns: HRESULT.
  2435. Params:
  2436. in: pWSName - Name of the Winstation.
  2437. out: pSize - Size of the allocated buffer
  2438. ppSecurityDescriptor - Pointer to the buffer containing the security descriptor
  2439. ****************************************************************************************************************/
  2440. STDMETHODIMP CCfgComp::DeleteWS(PWINSTATIONNAME pWs)
  2441. {
  2442. HRESULT hResult = S_OK;
  2443. PWS pWinsta = NULL;
  2444. PWD pWD = NULL;
  2445. void * pExtObject = NULL;
  2446. WINSTATIONCONFIG2W WsConfig;
  2447. ULONG Length = 0;
  2448. long Status;
  2449. //If not initialized return error
  2450. if(!m_bInitialized)
  2451. return CFGBKEND_E_NOT_INITIALIZED;
  2452. //Check if the caller has write permissions.
  2453. if(!m_bAdmin)
  2454. return E_ACCESSDENIED;
  2455. //Check if Valid Winstation Name
  2456. if(NULL == pWs || lstrlen(pWs) > WINSTATIONNAME_LENGTH)
  2457. return E_INVALIDARG;
  2458. //Check for the validity of the Winstation name,
  2459. pWinsta = GetWSObject(pWs);
  2460. if(NULL == pWinsta)
  2461. return E_INVALIDARG;
  2462. //Get the WD object associated with this Winstation.
  2463. pWD = GetWdObject(pWinsta->wdName);
  2464. if(NULL == pWD)
  2465. return E_FAIL;
  2466. //Query the registry for WinStation data
  2467. Status = RegWinStationQueryW(NULL,pWs,&WsConfig,sizeof(WINSTATIONCONFIG2W), &Length);
  2468. if(Status)
  2469. return E_FAIL;
  2470. #if 0 // tscc now uses aclui
  2471. // Remove name entry keys
  2472. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
  2473. HKEY hKey;
  2474. lstrcat( tchRegPath , pWs );
  2475. lstrcat( tchRegPath , L"\\NamedEntries" );
  2476. OutputDebugString( tchRegPath );
  2477. if( RegOpenKey( HKEY_LOCAL_MACHINE , tchRegPath , &hKey ) == ERROR_SUCCESS )
  2478. {
  2479. RegDeleteValue( hKey , L"cbSize" );
  2480. RegDeleteValue( hKey , L"NE" );
  2481. RegCloseKey( hKey );
  2482. RegDeleteKey( HKEY_LOCAL_MACHINE , tchRegPath );
  2483. }
  2484. #endif
  2485. //Get the ExtensionObject data(third party) this will be used for Creating and Deleting the registry keys.
  2486. if(pWD->lpfnExtRegQuery && pWD->hExtensionDLL)
  2487. {
  2488. pExtObject = (pWD->lpfnExtRegQuery)(pWs, &(WsConfig.Pd[0]));
  2489. if(pWD->lpfnExtRegDelete && pExtObject)
  2490. {
  2491. //Try Deleting the Extension entries in the registy
  2492. if(ERROR_SUCCESS != (pWD->lpfnExtRegDelete)(pWs,pExtObject))
  2493. hResult = CFGBKEND_EXTDELETE_FAILED;
  2494. //Delete the extension object. It will not be used further.
  2495. if(pWD->lpfnExtDeleteObject)
  2496. (pWD->lpfnExtDeleteObject)(pExtObject);
  2497. }
  2498. }
  2499. //Delete registy key
  2500. Status = RegWinStationDeleteW(NULL,pWs);
  2501. if (Status)
  2502. return Status;
  2503. //update our list of winstation objects.
  2504. PWS pObject;
  2505. int Size = 0,Index = 0;
  2506. /*
  2507. * Traverse the WD list
  2508. */
  2509. for (Index = 0, Size = m_WSArray.GetSize(); Index < Size; Index ++)
  2510. {
  2511. pObject = (PWS)m_WSArray[Index];
  2512. if ( !lstrcmpi( pObject->Name, pWs ) )
  2513. {
  2514. m_WSArray.RemoveAt(Index,1);
  2515. delete pObject;
  2516. break;
  2517. }
  2518. }
  2519. return hResult;
  2520. }
  2521. //----------------------------------------------------------------------
  2522. // good to call when you've updated the winstation security descriptor
  2523. //----------------------------------------------------------------------
  2524. STDMETHODIMP CCfgComp::ForceUpdate( void )
  2525. {
  2526. if( !m_bInitialized )
  2527. {
  2528. ODS( L"CFGBKEND : CCfgComp::ForceUpdate return NOT_INIT\n" );
  2529. return CFGBKEND_E_NOT_INITIALIZED;
  2530. }
  2531. //Check if the caller has write permissions.
  2532. if(!m_bAdmin)
  2533. {
  2534. ODS( L"CFGBKEND : CCfgComp::ForceUpdate -- not admin\n" );
  2535. return E_ACCESSDENIED;
  2536. }
  2537. if( _WinStationReadRegistry( SERVERNAME_CURRENT ) )
  2538. {
  2539. return S_OK;
  2540. }
  2541. ODS( L"CFGBKEND : ForceUpdate failed Winstation not updated\n" );
  2542. return E_FAIL;
  2543. }
  2544. //----------------------------------------------------------------------
  2545. // Must delete the array completely first.
  2546. //----------------------------------------------------------------------
  2547. STDMETHODIMP CCfgComp::Refresh( void )
  2548. {
  2549. //Check if the caller has write permissions.
  2550. /* bugid 364103
  2551. if(!m_bAdmin)
  2552. {
  2553. return E_ACCESSDENIED;
  2554. }
  2555. */
  2556. HRESULT hr = FillWdArray();
  2557. if( SUCCEEDED( hr) )
  2558. {
  2559. hr = FillWsArray();
  2560. }
  2561. return hr;
  2562. }
  2563. //----------------------------------------------------------------------
  2564. // Obtain Winstation SDCLASS type
  2565. // m_WDArray must already be initialized
  2566. //----------------------------------------------------------------------
  2567. STDMETHODIMP CCfgComp::GetTransportType( WCHAR *wszDriverName , WCHAR *wszTransportType , DWORD *sdtype )
  2568. {
  2569. _ASSERTE( wszDriverName != NULL || wszTransportType != NULL || sdtype != NULL );
  2570. if( wszDriverName == NULL || wszTransportType == NULL || sdtype == NULL )
  2571. {
  2572. return E_INVALIDARG;
  2573. }
  2574. *sdtype = SdNone;
  2575. PWD pWd = GetWdObject( wszDriverName );
  2576. if( pWd != NULL )
  2577. {
  2578. BOOL bFound = FALSE;
  2579. for( int i = 0; i < pWd->PDConfigArray.GetSize( ) ; ++i )
  2580. {
  2581. if( lstrcmpi( wszTransportType , ( ( PDCONFIG3W *)pWd->PDConfigArray[ i ] )->Data.PdName ) == 0 )
  2582. {
  2583. bFound = TRUE;
  2584. break;
  2585. }
  2586. }
  2587. if( bFound )
  2588. {
  2589. *sdtype = ( ( PDCONFIG3W * )pWd->PDConfigArray[ i ] )->Data.SdClass;
  2590. return S_OK;
  2591. }
  2592. }
  2593. return E_FAIL;
  2594. }
  2595. //----------------------------------------------------------------------
  2596. // Async's are unique if device name protocol type vary from other
  2597. // winstations.
  2598. //----------------------------------------------------------------------
  2599. STDMETHODIMP CCfgComp::IsAsyncUnique( WCHAR *wszDeviceName , WCHAR *wszProtocolType , BOOL *pbUnique )
  2600. {
  2601. _ASSERTE( wszDecoratedName != NULL || wszProtocolType != NULL || pbUnique != NULL );
  2602. if( wszDeviceName == NULL || wszProtocolType == NULL || pbUnique == NULL )
  2603. {
  2604. return E_INVALIDARG;
  2605. }
  2606. *pbUnique = TRUE;
  2607. // Traverse the WinStationList.
  2608. for( int i = 0; i < m_WSArray.GetSize(); i++ )
  2609. {
  2610. if( lstrcmpi( wszProtocolType , ( ( WS * )( m_WSArray[ i ] ) )->wdName ) == 0 )
  2611. {
  2612. if( SdAsync == ( ( WS *)( m_WSArray[i] ) )->PdClass )
  2613. {
  2614. if( !lstrcmpi( wszDeviceName , ( ( WS * )( m_WSArray[ i ] ) )->DeviceName ) == 0 )
  2615. {
  2616. *pbUnique = FALSE;
  2617. break;
  2618. }
  2619. }
  2620. }
  2621. }
  2622. return S_OK;
  2623. }
  2624. //----------------------------------------------------------------------
  2625. // Pull async configuration from the registry
  2626. //----------------------------------------------------------------------
  2627. STDMETHODIMP CCfgComp::GetAsyncConfig( WCHAR *wszName , NameType nt , PASYNCCONFIGW pAsync )
  2628. {
  2629. if( wszName == NULL || pAsync == NULL )
  2630. {
  2631. ODS( L"CFGBKEND: Invalid arg @ GetAsyncConfig\n" );
  2632. return E_INVALIDARG;
  2633. }
  2634. WINSTATIONCONFIG2W WSConfig2;
  2635. ULONG ulLength = 0;
  2636. if( nt == WsName )
  2637. {
  2638. //Read the information from the registry.
  2639. if( RegWinStationQueryW( NULL , wszName , &WSConfig2 , sizeof( WINSTATIONCONFIG2W) , &ulLength ) != ERROR_SUCCESS )
  2640. {
  2641. ODS( L"CFGBKEND: RegWinStationQueryW failed @ GetAsyncConfig\n " );
  2642. return E_FAIL;
  2643. }
  2644. *pAsync = WSConfig2.Pd[0].Params.Async;
  2645. }
  2646. else if( nt == WdName )
  2647. {
  2648. PWD pObject = GetWdObject( wszName );
  2649. if( pObject == NULL )
  2650. {
  2651. return E_UNEXPECTED;
  2652. }
  2653. *pAsync = pObject->wd2.Async;
  2654. }
  2655. else
  2656. {
  2657. return E_INVALIDARG;
  2658. }
  2659. return S_OK;
  2660. }
  2661. //----------------------------------------------------------------------
  2662. // Push async config back in to the registry
  2663. //----------------------------------------------------------------------
  2664. STDMETHODIMP CCfgComp::SetAsyncConfig( WCHAR *wszName , NameType nt , PASYNCCONFIGW pAsync , PDWORD pdwStatus )
  2665. {
  2666. *pdwStatus = 0;
  2667. if( wszName == NULL || pAsync == NULL )
  2668. {
  2669. ODS( L"CFGBKEND: Invalid arg @ SetAsyncConfig\n" );
  2670. *pdwStatus = ERROR_INVALID_PARAMETER;
  2671. return E_INVALIDARG;
  2672. }
  2673. WINSTATIONCONFIG2W WSConfig2;
  2674. // WDCONFIG2W wdConfig2;
  2675. ULONG ulLength = 0;
  2676. if( nt == WsName )
  2677. {
  2678. //Read the information from the registry.
  2679. CDCONFIG cdConfig;
  2680. ZeroMemory( ( PVOID )&cdConfig , sizeof( CDCONFIG ) );
  2681. if( ( *pdwStatus = RegWinStationQueryW( NULL , wszName , &WSConfig2 , sizeof( WINSTATIONCONFIG2W) , &ulLength ) ) != ERROR_SUCCESS )
  2682. {
  2683. ODS( L"CFGBKEND: RegWinStationQueryW failed @ SetAsyncConfig\n" );
  2684. return E_FAIL;
  2685. }
  2686. pAsync->fConnectionDriver = *( pAsync->ModemName ) ? TRUE : FALSE;
  2687. SetupAsyncCdConfig( pAsync , &cdConfig );
  2688. WSConfig2.Pd[0].Params.Async = *pAsync;
  2689. WSConfig2.Cd = cdConfig;
  2690. if( ( *pdwStatus = RegWinStationCreateW( NULL , wszName , FALSE , &WSConfig2 , sizeof( WINSTATIONCONFIG2W ) ) ) != ERROR_SUCCESS )
  2691. {
  2692. ODS( L"CFGBKEND: RegWinStationCreateW failed @ SetAsyncConfig\n" );
  2693. return E_FAIL;
  2694. }
  2695. }
  2696. /*else if( nt == WdName )
  2697. {
  2698. PWD pObject = GetWdObject( wszName );
  2699. if( pObject == NULL )
  2700. {
  2701. ODS( L"CFGBKEND: Failed to obtain WD @ SetAsyncConfig\n" );
  2702. *pdwStatus = ERROR_INVALID_NAME;
  2703. return E_FAIL;
  2704. }
  2705. if( ( *pdwStatus = RegWdQueryW( NULL , pObject->wdKey , &wdConfig2 , sizeof( WDCONFIG2W ) , &ulLength ) ) != ERROR_SUCCESS )
  2706. {
  2707. ODS( L"CFGBKEND: RegWdQueryW failed @ SetAsyncConfig driver name is " );
  2708. ODS( pObject->wdKey );
  2709. ODS( L"\n" );
  2710. return E_FAIL;
  2711. }
  2712. wdConfig2.Async = *pAsync;
  2713. if( ( *pdwStatus = RegWdCreateW( NULL , pObject->wdKey , FALSE , &wdConfig2 , sizeof( WDCONFIG2W ) ) ) != ERROR_SUCCESS )
  2714. {
  2715. ODS( L"CFGBKEND: RegWdCreateW failed @ SetAsyncConfig\n" );
  2716. return E_FAIL;
  2717. }
  2718. }*/
  2719. else
  2720. {
  2721. *pdwStatus = ERROR_INVALID_PARAMETER;
  2722. return E_INVALIDARG;
  2723. }
  2724. return S_OK;
  2725. }
  2726. //----------------------------------------------------------------------
  2727. // GetDeviceList expects the name of the WD
  2728. // the return is a BLOB PDPARAMs containing ASYNCCONFG's
  2729. //----------------------------------------------------------------------
  2730. STDMETHODIMP CCfgComp::GetDeviceList( WCHAR *wszName , NameType Type , ULONG *pulItems , LPBYTE *ppBuffer )
  2731. {
  2732. PWD pObject = NULL;
  2733. if( wszName == NULL || pulItems == NULL )
  2734. {
  2735. ODS( L"CFGBKEND : @GetDeviceList - Driver or WinSta Name invalid\n" );
  2736. return E_INVALIDARG;
  2737. }
  2738. if( Type == WsName )
  2739. {
  2740. PWS pWS = GetWSObject( wszName );
  2741. if( NULL == pWS )
  2742. {
  2743. ODS( L"CFGBKEND : @GetDeviceList - No winsta object found\n" );
  2744. return E_INVALIDARG;
  2745. }
  2746. pObject = GetWdObject( pWS->wdName );
  2747. if( NULL == pObject )
  2748. {
  2749. ODS( L"CFGBKEND : @GetDeviceList - No WD object found\n" );
  2750. return E_FAIL;
  2751. }
  2752. }
  2753. else
  2754. {
  2755. pObject = GetWdObject( wszName );
  2756. }
  2757. if( pObject == NULL )
  2758. {
  2759. ODS( wszName ); ODS( L" - @GetDeviceList - driver object not found\n" );
  2760. return E_UNEXPECTED;
  2761. }
  2762. PDCONFIG3W *pPdConfig3 = NULL;
  2763. int nItems = ( pObject->PDConfigArray ).GetSize( );
  2764. for( int i = 0; i < nItems ; i++)
  2765. {
  2766. if( SdAsync == ( ( PDCONFIG3W * )pObject->PDConfigArray[i] )->Data.SdClass )
  2767. {
  2768. pPdConfig3 = ( PDCONFIG3W * )pObject->PDConfigArray[i];
  2769. break;
  2770. }
  2771. }
  2772. if( pPdConfig3 == NULL )
  2773. {
  2774. ODS( L"@GetDeviceList - PDCONFIG3 not found for ASYNC\n" );
  2775. return E_UNEXPECTED;
  2776. }
  2777. // Get the list of PDPARAMS -- last param if true queries registry for com devices
  2778. // if false uses DosDevices to obtain list
  2779. ODS( L"CFGBKEND : Calling WinEnumerateDevices\n" );
  2780. LPBYTE lpBuffer = ( LPBYTE )WinEnumerateDevices( NULL , pPdConfig3 , pulItems , FALSE );
  2781. if( lpBuffer == NULL )
  2782. {
  2783. ODS( L"CFGBKEND : WinEnumerateDevices failed @ CCfgComp::GetDeviceList\n" );
  2784. return E_OUTOFMEMORY;
  2785. }
  2786. // don't forget to free with LocalFree
  2787. *ppBuffer = lpBuffer;
  2788. return S_OK;
  2789. }
  2790. //----------------------------------------------------------------------
  2791. // GetConnType retreives the name of the connection type for an Async
  2792. // device. The list of resource ids is match the order of the
  2793. // CONNECTCONFIG enum data type.
  2794. //----------------------------------------------------------------------
  2795. STDMETHODIMP CCfgComp::GetConnTypeName( int idxItem , WCHAR *rgwszConnectName )
  2796. {
  2797. int rgIds[] = { IDS_CONNECT_CTS , IDS_CONNECT_DSR , IDS_CONNECT_RI ,
  2798. IDS_CONNECT_DCD , IDS_CONNECT_FIRST_CHARACTER ,
  2799. IDS_CONNECT_ALWAYS , -1 };
  2800. _ASSERTE( rgwszConnectName != NULL );
  2801. _ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
  2802. if( rgIds[ idxItem ] == -1 )
  2803. {
  2804. return S_FALSE;
  2805. }
  2806. if( !GetResourceStrings( rgIds , idxItem , rgwszConnectName ) )
  2807. {
  2808. ODS( L"Error happen in CCfgComp::GetConnTypeName\n" );
  2809. return E_FAIL;
  2810. }
  2811. return S_OK;
  2812. }
  2813. //----------------------------------------------------------------------
  2814. // GetModemCallbackString
  2815. //----------------------------------------------------------------------
  2816. STDMETHODIMP CCfgComp::GetModemCallbackString( int idxItem , WCHAR *rgwszModemCallBackString )
  2817. {
  2818. int rgIds[] = { IDS_MODEM_CALLBACK_DISABLED , IDS_MODEM_CALLBACK_ROVING , IDS_MODEM_CALLBACK_FIXED , -1 };
  2819. _ASSERTE( rgwszModemCallBackString != NULL );
  2820. _ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
  2821. if( rgIds[ idxItem ] == -1 )
  2822. {
  2823. return S_FALSE;
  2824. }
  2825. if( !GetResourceStrings( rgIds , idxItem , rgwszModemCallBackString ) )
  2826. {
  2827. ODS( L"Error happen in CCfgComp::GetConnTypeName\n" );
  2828. return E_FAIL;
  2829. }
  2830. return S_OK;
  2831. }
  2832. //----------------------------------------------------------------------
  2833. // Returns the name of hardware flow control receive string
  2834. //----------------------------------------------------------------------
  2835. STDMETHODIMP CCfgComp::GetHWReceiveName( int idxItem , WCHAR *rgwszHWRName )
  2836. {
  2837. int rgIds[] = { IDS_ASYNC_ADVANCED_HWRX_NOTHING ,
  2838. IDS_ASYNC_ADVANCED_HWRX_TURN_OFF_RTS ,
  2839. IDS_ASYNC_ADVANCED_HWRX_TURN_OFF_DTR , -1
  2840. };
  2841. _ASSERTE( rgwszHWRName != NULL );
  2842. _ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
  2843. if( rgIds[ idxItem ] == -1 )
  2844. {
  2845. return S_FALSE;
  2846. }
  2847. if( !GetResourceStrings( rgIds , idxItem , rgwszHWRName ) )
  2848. {
  2849. ODS( L"Error happen in CCfgComp::GetHWReceiveName\n" );
  2850. return E_FAIL;
  2851. }
  2852. return S_OK;
  2853. }
  2854. //----------------------------------------------------------------------
  2855. // returns the name of hardware flow control transmit string
  2856. //----------------------------------------------------------------------
  2857. STDMETHODIMP CCfgComp::GetHWTransmitName( int idxItem , WCHAR *rgwzHWTName )
  2858. {
  2859. int rgIds[] = { IDS_ASYNC_ADVANCED_HWTX_ALWAYS ,
  2860. IDS_ASYNC_ADVANCED_HWTX_WHEN_CTS_IS_ON,
  2861. IDS_ASYNC_ADVANCED_HWTX_WHEN_DSR_IS_ON,
  2862. -1
  2863. };
  2864. _ASSERTE( rgwszHWRName != NULL );
  2865. _ASSERTE( idxItem >= 0 && idxItem < ARRAYSIZE( rgIds ) );
  2866. if( rgIds[ idxItem ] == -1 )
  2867. {
  2868. return S_FALSE;
  2869. }
  2870. if( !GetResourceStrings( rgIds , idxItem , rgwzHWTName ) )
  2871. {
  2872. ODS( L"Error happen in CCfgComp::GetHWReceiveName\n" );
  2873. return E_FAIL;
  2874. }
  2875. return S_OK;
  2876. }
  2877. //----------------------------------------------------------------------
  2878. // Internal method call -- helper function.
  2879. //----------------------------------------------------------------------
  2880. BOOL CCfgComp::GetResourceStrings( int *prgIds , int iItem , WCHAR *rgwszList )
  2881. {
  2882. _ASSERTE( rgwszList != NULL );
  2883. if( rgwszList == NULL )
  2884. {
  2885. ODS( L"rgwszList is NULL @ CCfgComp::GetResourceStrings\n" );
  2886. return FALSE;
  2887. }
  2888. TCHAR tchConType[ 80 ];
  2889. if( LoadString( _Module.GetResourceInstance( ) , prgIds[ iItem ] , tchConType , sizeof( tchConType ) / sizeof( TCHAR ) ) == 0 )
  2890. {
  2891. ODS( L"String resource not found @ CCfgComp::GetResourceStrings\n" );
  2892. return FALSE;
  2893. }
  2894. // copy enough characters
  2895. lstrcpyn( rgwszList , tchConType , sizeof( tchConType ) / sizeof(TCHAR) );
  2896. return TRUE;
  2897. }
  2898. //----------------------------------------------------------------------
  2899. HRESULT CCfgComp::GetCaps( WCHAR *szWdName , ULONG *pMask )
  2900. {
  2901. if( szWdName == NULL || pMask == NULL )
  2902. {
  2903. ODS( L"CCfgComp::GetCaps returned INVALIDARG\n" );
  2904. return E_INVALIDARG;
  2905. }
  2906. PWD pObject = GetWdObject( szWdName );
  2907. if( pObject == NULL )
  2908. {
  2909. return E_UNEXPECTED;
  2910. }
  2911. if( pObject->lpfnGetCaps != NULL )
  2912. {
  2913. *pMask = ( pObject->lpfnGetCaps )( );
  2914. }
  2915. return S_OK;
  2916. }
  2917. //----------------------------------------------------------------------
  2918. HRESULT CCfgComp::QueryLoggedOnCount( WCHAR *pWSName , PLONG pCount )
  2919. {
  2920. ODS( L"CFGBKEND : CCfgComp::QueryLoggedOnCount\n" );
  2921. *pCount = 0;
  2922. ULONG Entries = 0;
  2923. TCHAR *p;
  2924. PLOGONID pLogonId;
  2925. if(FALSE == WinStationEnumerate( NULL , &pLogonId, &Entries))
  2926. {
  2927. return E_FAIL;
  2928. }
  2929. if( pLogonId )
  2930. {
  2931. for( ULONG i = 0; i < Entries; i++ )
  2932. {
  2933. /*
  2934. * Check active, connected, and shadowing WinStations, and increment
  2935. * the logged on count if the specified name matches the 'root'
  2936. * name of current winstation.
  2937. */
  2938. if( ( pLogonId[i].State == State_Active ) || ( pLogonId[i].State == State_Connected ) || ( pLogonId[i].State == State_Shadow ) )
  2939. {
  2940. // remove appended connection number
  2941. p = _tcschr( pLogonId[i].WinStationName , TEXT('#') );
  2942. if( p != NULL )
  2943. {
  2944. *p = TEXT('\0');
  2945. }
  2946. if( !lstrcmpi( pWSName, pLogonId[i].WinStationName ) )
  2947. {
  2948. *pCount += 1 ;
  2949. }
  2950. }
  2951. }
  2952. WinStationFreeMemory(pLogonId);
  2953. }
  2954. return S_OK;
  2955. } // end QueryLoggedOnCount
  2956. /*
  2957. //-----------------------------------------------------------------------------
  2958. // returns the number of configured winstations
  2959. //-----------------------------------------------------------------------------
  2960. STDMETHODIMP CCfgComp::GetNumofWinStations( PULONG nWinsta )
  2961. {
  2962. if( nWinsta == NULL )
  2963. {
  2964. ODS( L"CFGBKEND : GetNumofWinStations - INVALID ARG\n" );
  2965. return E_INVALIDARG;
  2966. }
  2967. *nWinsta = ( ULONG )m_WSArray.GetSize();
  2968. return S_OK;
  2969. }
  2970. */
  2971. //-----------------------------------------------------------------------------
  2972. // returns the number of configured winstations
  2973. //-----------------------------------------------------------------------------
  2974. STDMETHODIMP CCfgComp::GetNumofWinStations(WCHAR * WdName,WCHAR * PdName, PULONG nWinsta )
  2975. {
  2976. if( nWinsta == NULL || NULL == WdName || NULL == PdName )
  2977. {
  2978. ODS( L"CFGBKEND : GetNumofWinStations - INVALID ARG\n" );
  2979. return E_INVALIDARG;
  2980. }
  2981. ULONG lCount = 0;
  2982. for( int i = 0; i < m_WSArray.GetSize(); i++ )
  2983. {
  2984. if(lstrcmpi(WdName,( ( WS *)( m_WSArray[i] ) )->wdName) == 0 )
  2985. {
  2986. if(lstrcmpi( PdName , ( ( WS * )( m_WSArray[ i ] ) )->pdName ) == 0 )
  2987. {
  2988. lCount++;
  2989. }
  2990. }
  2991. }
  2992. *nWinsta = lCount;
  2993. return S_OK;
  2994. }
  2995. //-----------------------------------------------------------------------------
  2996. STDMETHODIMP_(BOOL) CCfgComp::IsAsyncDeviceAvailable(LPCTSTR pDeviceName)
  2997. {
  2998. /*
  2999. * If this is an async WinStation, the device is the same as the
  3000. * one we're checking, but this is not the current WinStation being
  3001. * edited, return FALSE.
  3002. * THIS NEEDS TO BE REVIEWED - alhen
  3003. */
  3004. //return TRUE;
  3005. if( pDeviceName != NULL )
  3006. {
  3007. for( int i = 0; i < m_WSArray.GetSize(); i++ )
  3008. {
  3009. if( SdAsync == ( ( WS *)( m_WSArray[i] ) )->PdClass )
  3010. {
  3011. if( lstrcmpi( pDeviceName , ( ( WS * )( m_WSArray[ i ] ) )->DeviceName ) == 0 )
  3012. {
  3013. return FALSE;
  3014. }
  3015. }
  3016. }
  3017. }
  3018. return TRUE;
  3019. }
  3020. #if 0 // removed for final
  3021. //-----------------------------------------------------------------------------
  3022. STDMETHODIMP CCfgComp::GetCachedSessions(DWORD * pCachedSessions)
  3023. {
  3024. HKEY Handle = NULL;
  3025. DWORD ValueBuffer = 0;
  3026. DWORD ValueType = 0;
  3027. LONG Status = 0;
  3028. DWORD ValueSize = sizeof(ValueBuffer);
  3029. if(NULL == pCachedSessions)
  3030. {
  3031. return E_INVALIDARG;
  3032. }
  3033. *pCachedSessions = 0;
  3034. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3035. KEY_READ, &Handle );
  3036. if ( Status == ERROR_SUCCESS )
  3037. {
  3038. Status = RegQueryValueEx( Handle,
  3039. REG_CITRIX_IDLEWINSTATIONPOOLCOUNT,
  3040. NULL,
  3041. &ValueType,
  3042. (LPBYTE) &ValueBuffer,
  3043. &ValueSize );
  3044. if ( Status == ERROR_SUCCESS )
  3045. {
  3046. if(ValueType == REG_DWORD)
  3047. {
  3048. *pCachedSessions = ValueBuffer;
  3049. }
  3050. else
  3051. {
  3052. Status = E_FAIL;
  3053. }
  3054. }
  3055. }
  3056. if(Handle)
  3057. {
  3058. RegCloseKey(Handle);
  3059. }
  3060. return Status;
  3061. }
  3062. //-----------------------------------------------------------------------------
  3063. STDMETHODIMP CCfgComp::SetCachedSessions(DWORD dCachedSessions)
  3064. {
  3065. // TODO: Add your implementation code here
  3066. LONG Status = 0;
  3067. HKEY Handle = NULL;
  3068. if(RegServerAccessCheck(KEY_ALL_ACCESS))
  3069. {
  3070. return E_ACCESSDENIED;
  3071. }
  3072. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3073. KEY_READ | KEY_SET_VALUE, &Handle );
  3074. if ( Status == ERROR_SUCCESS )
  3075. {
  3076. Status = RegSetValueEx(Handle,REG_CITRIX_IDLEWINSTATIONPOOLCOUNT,
  3077. 0,REG_DWORD,(const BYTE *)&dCachedSessions,
  3078. sizeof(dCachedSessions));
  3079. }
  3080. if(Handle)
  3081. {
  3082. RegCloseKey(Handle);
  3083. }
  3084. return Status;
  3085. }
  3086. #endif // removed
  3087. //-----------------------------------------------------------------------------
  3088. STDMETHODIMP CCfgComp::GetDelDirsOnExit(BOOL * pDelDirsOnExit)
  3089. {
  3090. HKEY Handle = NULL;
  3091. DWORD ValueBuffer = 0;
  3092. DWORD ValueType = 0;
  3093. LONG Status = 0;
  3094. DWORD ValueSize = sizeof(ValueBuffer);
  3095. if(NULL == pDelDirsOnExit)
  3096. {
  3097. return E_INVALIDARG;
  3098. }
  3099. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3100. KEY_READ, &Handle );
  3101. if ( Status == ERROR_SUCCESS )
  3102. {
  3103. Status = RegQueryValueEx( Handle,
  3104. REG_CITRIX_DELETETEMPDIRSONEXIT,
  3105. NULL,
  3106. &ValueType,
  3107. (LPBYTE) &ValueBuffer,
  3108. &ValueSize );
  3109. if ( Status == ERROR_SUCCESS )
  3110. {
  3111. if(ValueType == REG_DWORD)
  3112. {
  3113. if(ValueBuffer)
  3114. {
  3115. *pDelDirsOnExit = TRUE;
  3116. }
  3117. else
  3118. {
  3119. *pDelDirsOnExit = FALSE;
  3120. }
  3121. }
  3122. else
  3123. {
  3124. Status = E_FAIL;
  3125. }
  3126. }
  3127. }
  3128. if(Handle)
  3129. {
  3130. RegCloseKey(Handle);
  3131. }
  3132. return Status;
  3133. }
  3134. //-----------------------------------------------------------------------------
  3135. STDMETHODIMP CCfgComp::SetDelDirsOnExit(BOOL bDelDirsOnExit)
  3136. {
  3137. LONG Status = 0;
  3138. HKEY Handle = NULL;
  3139. /* admin only
  3140. if(RegServerAccessCheck(KEY_ALL_ACCESS))
  3141. {
  3142. return E_ACCESSDENIED;
  3143. }
  3144. */
  3145. if( !m_bAdmin )
  3146. {
  3147. ODS( L"CCfgComp::SetDelDirsOnExit not admin\n" );
  3148. return E_ACCESSDENIED;
  3149. }
  3150. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3151. KEY_READ | KEY_SET_VALUE, &Handle );
  3152. if ( Status == ERROR_SUCCESS )
  3153. {
  3154. Status = RegSetValueEx(Handle,REG_CITRIX_DELETETEMPDIRSONEXIT,
  3155. 0,REG_DWORD,(const BYTE *)&bDelDirsOnExit,
  3156. sizeof(bDelDirsOnExit));
  3157. }
  3158. if(Handle)
  3159. {
  3160. RegCloseKey(Handle);
  3161. }
  3162. return Status;
  3163. }
  3164. //-----------------------------------------------------------------------------
  3165. STDMETHODIMP CCfgComp::GetUseTempDirPerSession(BOOL * pbTempDir)
  3166. {
  3167. HKEY Handle = NULL;
  3168. DWORD ValueBuffer = 0;
  3169. DWORD ValueType = 0;
  3170. LONG Status = 0;
  3171. DWORD ValueSize = sizeof(ValueBuffer);
  3172. if(NULL == pbTempDir)
  3173. {
  3174. return E_INVALIDARG;
  3175. }
  3176. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3177. KEY_READ, &Handle );
  3178. if ( Status == ERROR_SUCCESS )
  3179. {
  3180. Status = RegQueryValueEx( Handle,
  3181. REG_TERMSRV_PERSESSIONTEMPDIR,
  3182. NULL,
  3183. &ValueType,
  3184. (LPBYTE) &ValueBuffer,
  3185. &ValueSize );
  3186. if ( Status == ERROR_SUCCESS )
  3187. {
  3188. if(ValueType == REG_DWORD)
  3189. {
  3190. if(ValueBuffer)
  3191. {
  3192. *pbTempDir = TRUE;
  3193. }
  3194. else
  3195. {
  3196. *pbTempDir = FALSE;
  3197. }
  3198. }
  3199. else
  3200. {
  3201. Status = E_FAIL;
  3202. }
  3203. }
  3204. }
  3205. if(Handle)
  3206. {
  3207. RegCloseKey(Handle);
  3208. }
  3209. return Status;
  3210. }
  3211. //-----------------------------------------------------------------------------
  3212. STDMETHODIMP CCfgComp::SetUseTempDirPerSession(BOOL bTempDirPerSession)
  3213. {
  3214. LONG Status = 0;
  3215. HKEY Handle = NULL;
  3216. /* admin only bugid294645
  3217. if(RegServerAccessCheck(KEY_ALL_ACCESS))
  3218. {
  3219. return E_ACCESSDENIED;
  3220. }
  3221. */
  3222. if( !m_bAdmin )
  3223. {
  3224. ODS( L"CCfgComp::SetUseTempDirPerSession not admin\n" );
  3225. return E_ACCESSDENIED;
  3226. }
  3227. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3228. KEY_READ | KEY_SET_VALUE, &Handle );
  3229. if ( Status == ERROR_SUCCESS )
  3230. {
  3231. Status = RegSetValueEx(Handle,REG_TERMSRV_PERSESSIONTEMPDIR,
  3232. 0,REG_DWORD,(const BYTE *)&bTempDirPerSession,
  3233. sizeof(bTempDirPerSession));
  3234. }
  3235. if(Handle)
  3236. {
  3237. RegCloseKey(Handle);
  3238. }
  3239. return Status;
  3240. }
  3241. //-----------------------------------------------------------------------------
  3242. STDMETHODIMP CCfgComp::GetInternetConLic( BOOL *pbInternetConLic , PDWORD pdwStatus )
  3243. {
  3244. // shouldn't be called on post-Win2000 machines
  3245. _ASSERTE( FALSE );
  3246. UNREFERENCED_PARAMETER(pbInternetConLic);
  3247. if( pdwStatus == NULL )
  3248. {
  3249. return E_INVALIDARG;
  3250. }
  3251. *pdwStatus = ERROR_NOT_SUPPORTED;
  3252. return E_FAIL;
  3253. }
  3254. //-----------------------------------------------------------------------------
  3255. STDMETHODIMP CCfgComp::SetInternetConLic( BOOL bInternetConLic , PDWORD pdwStatus )
  3256. {
  3257. // shouldn't be called on post-Win2000 machines
  3258. _ASSERTE( FALSE );
  3259. UNREFERENCED_PARAMETER(bInternetConLic);
  3260. if( pdwStatus == NULL )
  3261. {
  3262. return E_INVALIDARG;
  3263. }
  3264. *pdwStatus = ERROR_NOT_SUPPORTED;
  3265. return E_FAIL;
  3266. }
  3267. //-----------------------------------------------------------------------------
  3268. STDMETHODIMP CCfgComp::GetLicensingMode( ULONG * pulMode , PDWORD pdwStatus )
  3269. {
  3270. BOOL fRet;
  3271. HRESULT hr = S_OK;
  3272. if( NULL == pulMode || pdwStatus == NULL )
  3273. {
  3274. return E_INVALIDARG;
  3275. }
  3276. HANDLE hServer = ServerLicensingOpen(NULL);
  3277. if (NULL == hServer)
  3278. {
  3279. *pdwStatus = GetLastError();
  3280. return E_FAIL;
  3281. }
  3282. fRet = ServerLicensingGetPolicy(
  3283. hServer,
  3284. pulMode
  3285. );
  3286. if (fRet)
  3287. {
  3288. *pdwStatus = ERROR_SUCCESS;
  3289. }
  3290. else
  3291. {
  3292. *pdwStatus = GetLastError();
  3293. hr = E_FAIL;
  3294. }
  3295. ServerLicensingClose(hServer);
  3296. return hr;
  3297. }
  3298. //-----------------------------------------------------------------------------
  3299. STDMETHODIMP CCfgComp::GetLicensingModeInfo( ULONG ulMode , WCHAR **pwszName, WCHAR **pwszDescription, PDWORD pdwStatus )
  3300. {
  3301. #define MAX_LICENSING_STRING_LEN 1024
  3302. UINT nNameResource, nDescResource;
  3303. int nRet;
  3304. if( NULL == pwszName || NULL == pwszDescription || pdwStatus == NULL )
  3305. {
  3306. return E_INVALIDARG;
  3307. }
  3308. *pdwStatus = ERROR_SUCCESS;
  3309. *pwszName = NULL;
  3310. *pwszDescription = NULL;
  3311. switch (ulMode)
  3312. {
  3313. case 1:
  3314. nNameResource = IDS_LICENSING_RA_NAME;
  3315. nDescResource = IDS_LICENSING_RA_DESC;
  3316. break;
  3317. case 2:
  3318. nNameResource = IDS_LICENSING_PERSEAT_NAME;
  3319. nDescResource = IDS_LICENSING_PERSEAT_DESC;
  3320. break;
  3321. case 4:
  3322. nNameResource = IDS_LICENSING_PERUSER_NAME;
  3323. nDescResource = IDS_LICENSING_PERUSER_DESC;
  3324. break;
  3325. default:
  3326. return E_INVALIDARG;
  3327. break;
  3328. }
  3329. *pwszName = (WCHAR *) CoTaskMemAlloc((MAX_LICENSING_STRING_LEN+1)*sizeof(WCHAR));
  3330. if (NULL == *pwszName)
  3331. {
  3332. *pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
  3333. goto return_failure;
  3334. }
  3335. *pwszDescription = (WCHAR *) CoTaskMemAlloc((MAX_LICENSING_STRING_LEN+1)*sizeof(WCHAR));
  3336. if (NULL == *pwszDescription)
  3337. {
  3338. *pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
  3339. goto return_failure;
  3340. }
  3341. nRet = LoadString(g_hInstance,
  3342. nNameResource,
  3343. *pwszName,
  3344. MAX_LICENSING_STRING_LEN+1);
  3345. if (0 == nRet)
  3346. {
  3347. *pdwStatus = GetLastError();
  3348. goto return_failure;
  3349. }
  3350. nRet = LoadString(g_hInstance,
  3351. nDescResource,
  3352. *pwszDescription,
  3353. MAX_LICENSING_STRING_LEN+1);
  3354. if (0 == nRet)
  3355. {
  3356. *pdwStatus = GetLastError();
  3357. goto return_failure;
  3358. }
  3359. return S_OK;
  3360. return_failure:
  3361. if (NULL != *pwszName)
  3362. {
  3363. CoTaskMemFree(*pwszName);
  3364. *pwszName = NULL;
  3365. }
  3366. if (NULL != *pwszDescription)
  3367. {
  3368. CoTaskMemFree(*pwszDescription);
  3369. *pwszDescription = NULL;
  3370. }
  3371. return E_FAIL;
  3372. }
  3373. //-----------------------------------------------------------------------------
  3374. STDMETHODIMP CCfgComp::GetLicensingModeList( ULONG *pcModes , ULONG **prgulModes, PDWORD pdwStatus )
  3375. {
  3376. ULONG *rgulModes = NULL;
  3377. BOOL fRet;
  3378. HRESULT hr = S_OK;
  3379. if( NULL == pcModes || NULL == prgulModes || pdwStatus == NULL )
  3380. {
  3381. return E_INVALIDARG;
  3382. }
  3383. HANDLE hServer = ServerLicensingOpen(NULL);
  3384. if (NULL == hServer)
  3385. {
  3386. *pdwStatus = GetLastError();
  3387. return E_FAIL;
  3388. }
  3389. fRet = ServerLicensingGetAvailablePolicyIds(
  3390. hServer,
  3391. &rgulModes,
  3392. pcModes
  3393. );
  3394. if (fRet)
  3395. {
  3396. *pdwStatus = ERROR_SUCCESS;
  3397. *prgulModes = (ULONG *) CoTaskMemAlloc((*pcModes)*sizeof(ULONG));
  3398. if (NULL != *prgulModes)
  3399. {
  3400. memcpy(*prgulModes,rgulModes,(*pcModes)*sizeof(ULONG));
  3401. }
  3402. else
  3403. {
  3404. *pdwStatus = ERROR_NOT_ENOUGH_MEMORY;
  3405. hr = E_FAIL;
  3406. }
  3407. LocalFree(rgulModes);
  3408. }
  3409. else
  3410. {
  3411. *pdwStatus = GetLastError();
  3412. hr = E_FAIL;
  3413. }
  3414. return hr;
  3415. }
  3416. //-----------------------------------------------------------------------------
  3417. STDMETHODIMP CCfgComp::SetLicensingMode( ULONG ulMode , PDWORD pdwStatus, PDWORD pdwNewStatus )
  3418. {
  3419. if( pdwStatus == NULL || pdwNewStatus == NULL )
  3420. {
  3421. return E_INVALIDARG;
  3422. }
  3423. HANDLE hServer = ServerLicensingOpen(NULL);
  3424. if (NULL == hServer)
  3425. {
  3426. *pdwStatus = GetLastError();
  3427. return E_FAIL;
  3428. }
  3429. *pdwStatus = ServerLicensingSetPolicy(hServer,
  3430. ulMode,
  3431. pdwNewStatus);
  3432. ServerLicensingClose(hServer);
  3433. return ((*pdwStatus == ERROR_SUCCESS) && (*pdwNewStatus == ERROR_SUCCESS)) ? S_OK : E_FAIL;
  3434. }
  3435. //-----------------------------------------------------------------------------
  3436. // pUserPerm == TRUE if security is relaxed
  3437. // FALSE for tight security
  3438. //-----------------------------------------------------------------------------
  3439. STDMETHODIMP CCfgComp::SetUserPerm( BOOL bUserPerm , PDWORD pdwStatus )
  3440. {
  3441. if( !m_bAdmin )
  3442. {
  3443. ODS( L"CFGBKEND:SetUserPerm not admin\n" );
  3444. return E_ACCESSDENIED;
  3445. }
  3446. if( pdwStatus == NULL )
  3447. {
  3448. ODS( L"CFGBKEND-SetUserPerm invalid arg\n" );
  3449. return E_INVALIDARG;
  3450. }
  3451. HKEY hKey;
  3452. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  3453. REG_CONTROL_TSERVER,
  3454. 0 ,
  3455. KEY_READ | KEY_SET_VALUE,
  3456. &hKey );
  3457. if( *pdwStatus != ERROR_SUCCESS )
  3458. {
  3459. DBGMSG( L"CFGBKEND-SetUserPerm RegOpenKeyEx failed 0x%x\n", *pdwStatus );
  3460. return E_FAIL;
  3461. }
  3462. *pdwStatus = RegSetValueEx( hKey ,
  3463. L"TSUserEnabled" ,
  3464. 0 ,
  3465. REG_DWORD ,
  3466. ( const PBYTE )&bUserPerm ,
  3467. sizeof( BOOL ) );
  3468. if( *pdwStatus != ERROR_SUCCESS )
  3469. {
  3470. DBGMSG( L"CFGBKEND-SetUserPerm RegSetValueEx failed 0x%x\n" , *pdwStatus );
  3471. return E_FAIL;
  3472. }
  3473. RegCloseKey( hKey );
  3474. return S_OK;
  3475. }
  3476. //-----------------------------------------------------------------------------
  3477. // pUserPerm == TRUE if security is relaxed
  3478. // FALSE for tight security
  3479. //-----------------------------------------------------------------------------
  3480. STDMETHODIMP CCfgComp::GetUserPerm( BOOL *pbUserPerm , PDWORD pdwStatus )
  3481. {
  3482. HKEY hKey;
  3483. DWORD dwSize = sizeof( DWORD );
  3484. DWORD dwValue;
  3485. if( pbUserPerm == NULL || pdwStatus == NULL )
  3486. {
  3487. ODS( L"CFGBKEND-GetUserPerm invalid arg\n" );
  3488. return E_INVALIDARG;
  3489. }
  3490. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  3491. REG_CONTROL_TSERVER,
  3492. 0 ,
  3493. KEY_READ ,
  3494. &hKey );
  3495. if( *pdwStatus != ERROR_SUCCESS )
  3496. {
  3497. DBGMSG( L"CFGBKEND-GetUserPerm RegOpenKeyEx failed 0x%x\n", *pdwStatus );
  3498. return E_FAIL;
  3499. }
  3500. *pdwStatus = RegQueryValueEx( hKey,
  3501. L"TSUserEnabled",
  3502. NULL,
  3503. NULL,
  3504. ( LPBYTE )&dwValue,
  3505. &dwSize );
  3506. if( *pdwStatus != ERROR_SUCCESS )
  3507. {
  3508. DBGMSG( L"CFGBKEND-GetUserPerm RegQueryValueEx failed 0x%x\n", *pdwStatus );
  3509. // not a true failure this means the key does not exist
  3510. // set to one for relaxed security
  3511. dwValue = 1;
  3512. *pdwStatus = S_OK;
  3513. }
  3514. RegCloseKey( hKey );
  3515. *pbUserPerm = !( ( BOOL )( dwValue == 0 ) );
  3516. return S_OK;
  3517. }
  3518. #if 1
  3519. //-----------------------------------------------------------------------------
  3520. //Private function
  3521. //-----------------------------------------------------------------------------
  3522. void CCfgComp::GetPdConfig( WDNAME WdKey,WINSTATIONCONFIG2W& WsConfig)
  3523. {
  3524. LONG Status;
  3525. PDCONFIG3 PdConfig;PDCONFIG3 PdSelected;PDCONFIG3 PdConfig2;
  3526. ULONG Index = 0, Entries, ByteCount = sizeof(PDNAME);
  3527. PDNAME PdKey;
  3528. // BOOL bFound = FALSE;
  3529. ULONG ByteCount2 = sizeof(PDNAME);
  3530. ULONG Index1 = 1; // start off with one since WsConfig.Pd[0] is already populated
  3531. do
  3532. {
  3533. Entries = 1;
  3534. // outer loop searches for keys in /Wds / ( wdname ) /Tds
  3535. Status = RegPdEnumerate(NULL,WdKey,TRUE,&Index,&Entries,PdKey,&ByteCount);
  3536. if(Status != ERROR_SUCCESS)
  3537. {
  3538. break;
  3539. }
  3540. Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
  3541. if(Status != ERROR_SUCCESS)
  3542. {
  3543. break;
  3544. }
  3545. if(0 == lstrcmpi(WsConfig.Pd[0].Create.PdName, PdConfig.Data.PdName))
  3546. {
  3547. PdSelected = PdConfig;
  3548. // bFound = TRUE;
  3549. //
  3550. ULONG Index2 = 0;
  3551. do
  3552. {
  3553. // innerloop forces the search in Wds/ (wdname )/ Pds
  3554. // Index must now be set to zero so that we get the first item
  3555. Status = RegPdEnumerate(NULL,WdKey,FALSE,&Index2,&Entries,PdKey,&ByteCount2);
  3556. if(Status != ERROR_SUCCESS)
  3557. {
  3558. break;
  3559. }
  3560. Status = RegPdQuery( NULL,WdKey,FALSE,PdKey,&PdConfig2,sizeof(PdConfig),&ByteCount2);
  3561. if(Status != ERROR_SUCCESS)
  3562. {
  3563. break;
  3564. }
  3565. for( UINT i = 0; i < PdSelected.RequiredPdCount ; i++)
  3566. {
  3567. if(0 == lstrcmpi(PdSelected.RequiredPds[i],PdConfig2.Data.PdName))
  3568. {
  3569. WsConfig.Pd[Index1].Create = PdConfig2.Data;
  3570. WsConfig.Pd[Index1].Params.SdClass = PdConfig2.Data.SdClass;
  3571. Index1++;
  3572. if(Index1 > MAX_PDCONFIG)
  3573. {
  3574. break;
  3575. }
  3576. }
  3577. }
  3578. }while(1);
  3579. }
  3580. /*
  3581. if(bFound)
  3582. {
  3583. break;
  3584. }
  3585. */
  3586. }while(1);
  3587. return;
  3588. }
  3589. #endif
  3590. #if 0
  3591. //-----------------------------------------------------------------------------
  3592. //Private function
  3593. //-----------------------------------------------------------------------------
  3594. void CCfgComp::GetPdConfig( WDNAME WdKey,WINSTATIONCONFIG2W& WsConfig)
  3595. {
  3596. LONG Status;
  3597. PDCONFIG3 PdConfig;
  3598. PDCONFIG3 PdSelected;
  3599. PDCONFIG3 PdConfig2;
  3600. ULONG Index = 0, Entries = 1, ByteCount = sizeof(PDNAME);
  3601. PDNAME PdKey;
  3602. BOOL bFound = FALSE;
  3603. ULONG ByteCount2 = sizeof(PDNAME);
  3604. ULONG Index1 = 1;
  3605. do
  3606. {
  3607. Status = RegPdEnumerate(NULL,WdKey,TRUE,&Index,&Entries,PdKey,&ByteCount);
  3608. if(Status != ERROR_SUCCESS)
  3609. {
  3610. break;
  3611. }
  3612. // we could speed this up by enumerating only for the protocol type
  3613. /*
  3614. Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
  3615. if(Status != ERROR_SUCCESS)
  3616. {
  3617. break;
  3618. }
  3619. */
  3620. DBGMSG( L"CFGBKEND: PdKey is at first %ws\n", PdKey );
  3621. DBGMSG( L"CFGBKEND: WsConfig.Pd[0].Create.PdName is %ws\n", WsConfig.Pd[0].Create.PdName );
  3622. if( 0 == lstrcmpi(WsConfig.Pd[0].Create.PdName, PdKey ) ) //PdConfig.Data.PdName))
  3623. {
  3624. Status = RegPdQuery( NULL,WdKey,TRUE,PdKey,&PdConfig,sizeof(PdConfig),&ByteCount );
  3625. if(Status != ERROR_SUCCESS)
  3626. {
  3627. break;
  3628. }
  3629. PdSelected = PdConfig;
  3630. bFound = TRUE;
  3631. // why didn't we reset Index to zero?
  3632. Index = 0;
  3633. // why didn't we reset Entries back to one?
  3634. Entries = 1;
  3635. do
  3636. {
  3637. DBGMSG( L"CFGBKEND: WdKey is %ws\n" , WdKey );
  3638. DBGMSG( L"CFGBKEND: PdKey before Enum is %ws\n", PdKey );
  3639. Status = RegPdEnumerate(NULL,WdKey,FALSE,&Index,&Entries,PdKey,&ByteCount2);
  3640. if(Status != ERROR_SUCCESS)
  3641. {
  3642. break;
  3643. }
  3644. DBGMSG( L"CFGBKEND: PdKey is %ws\n", PdKey );
  3645. Status = RegPdQuery( NULL,WdKey,FALSE,PdKey,&PdConfig2,sizeof(PdConfig),&ByteCount2);
  3646. if(Status != ERROR_SUCCESS)
  3647. {
  3648. ODS(L"RegPdQuery failed\n" );
  3649. break;
  3650. }
  3651. ODS(L"RegPdQuery ok\n" );
  3652. for( UINT i = 0; i < PdSelected.RequiredPdCount ; i++)
  3653. {
  3654. DBGMSG( L"CFGBKEND: Required pd name %s\n", PdConfig2.Data.PdName );
  3655. DBGMSG( L"CFGBKEND: ReqName is list is %s\n", PdSelected.RequiredPds[i] );
  3656. if( 0 == lstrcmpi( PdSelected.RequiredPds[i] , PdConfig2.Data.PdName ) )
  3657. {
  3658. DBGMSG( L"CFGBKEND: Copying pdconfig2 for pd name %s\n" , PdConfig2.Data.PdName );
  3659. WsConfig.Pd[Index1].Create = PdConfig2.Data;
  3660. WsConfig.Pd[Index1].Params.SdClass = PdConfig2.Data.SdClass;
  3661. Index1++;
  3662. if(Index1 > MAX_PDCONFIG)
  3663. {
  3664. break;
  3665. }
  3666. }
  3667. }
  3668. }while(1);
  3669. }
  3670. if(bFound)
  3671. {
  3672. break;
  3673. }
  3674. }while(1);
  3675. return;
  3676. }
  3677. #endif
  3678. #if 0 // removed for final
  3679. //-----------------------------------------------------------------------------
  3680. //Private function
  3681. //-----------------------------------------------------------------------------
  3682. BOOL CCfgComp::CompareSD(PSECURITY_DESCRIPTOR pSd1,PSECURITY_DESCRIPTOR pSd2)
  3683. {
  3684. DWORD dwErr;
  3685. ULONG index1 = 0;
  3686. //int index2 = 0;
  3687. ULONG cAce1 = 0;
  3688. EXPLICIT_ACCESS *pAce1 = NULL;
  3689. ULONG cAce2 = 0;
  3690. EXPLICIT_ACCESS *pAce2 = NULL;
  3691. BOOL bMatch = TRUE;
  3692. if (!IsValidSecurityDescriptor(pSd1) || !IsValidSecurityDescriptor(pSd2))
  3693. {
  3694. return FALSE;
  3695. }
  3696. dwErr = LookupSecurityDescriptorParts(
  3697. NULL,
  3698. NULL,
  3699. &cAce1,
  3700. &pAce1,
  3701. NULL,
  3702. NULL,
  3703. pSd1);
  3704. if (ERROR_SUCCESS != dwErr)
  3705. {
  3706. return FALSE;
  3707. }
  3708. dwErr = LookupSecurityDescriptorParts(
  3709. NULL,
  3710. NULL,
  3711. &cAce2,
  3712. &pAce2,
  3713. NULL,
  3714. NULL,
  3715. pSd2);
  3716. if (ERROR_SUCCESS != dwErr)
  3717. {
  3718. bMatch = FALSE;
  3719. goto cleanup;
  3720. }
  3721. if(cAce1 != cAce2)
  3722. {
  3723. bMatch = FALSE;
  3724. goto cleanup;
  3725. }
  3726. for(index1 = 0; index1 < cAce1; index1++)
  3727. {
  3728. //for(index2 = 0; index2 < cAce1; index2++)
  3729. {
  3730. if ( _tcscmp(GetTrusteeName(&pAce1[index1].Trustee),GetTrusteeName(&pAce2[index1].Trustee)) ||
  3731. (pAce1[index1].grfAccessPermissions != pAce2[index1].grfAccessPermissions)||
  3732. (pAce1[index1].grfAccessMode != pAce2[index1].grfAccessMode ))
  3733. {
  3734. bMatch = FALSE;
  3735. break;
  3736. }
  3737. }
  3738. }
  3739. cleanup:
  3740. if(pAce1)
  3741. {
  3742. LocalFree(pAce1);
  3743. }
  3744. if(pAce2)
  3745. {
  3746. LocalFree(pAce2);
  3747. }
  3748. return bMatch;
  3749. }
  3750. #endif
  3751. //-----------------------------------------------------------------------------
  3752. BOOL CCfgComp::RegServerAccessCheck(REGSAM samDesired)
  3753. {
  3754. LONG Status = 0;
  3755. HKEY Handle = NULL;
  3756. /*
  3757. * Attempt to open the registry
  3758. * at the requested access level.
  3759. */
  3760. if ( (Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REG_CONTROL_TSERVER, 0,
  3761. samDesired, &Handle )) == ERROR_SUCCESS )
  3762. {
  3763. RegCloseKey( Handle );
  3764. }
  3765. return( Status );
  3766. }
  3767. #if 0 // removed for final release
  3768. //-----------------------------------------------------------------------------
  3769. STDMETHODIMP CCfgComp::GetDefaultSecurity(ULONG * pDefaultSecurity)
  3770. {
  3771. HRESULT hResult = S_OK;
  3772. //Check the parameters
  3773. if(NULL == pDefaultSecurity)
  3774. {
  3775. return E_INVALIDARG;
  3776. }
  3777. *pDefaultSecurity = 0;
  3778. PSECURITY_DESCRIPTOR pDefaultDescriptor = NULL;
  3779. PSECURITY_DESCRIPTOR pTempDescriptor = NULL;
  3780. pDefaultDescriptor = ReadSecurityDescriptor(0);
  3781. if(NULL == pDefaultDescriptor)
  3782. {
  3783. *pDefaultSecurity = 0;
  3784. return hResult;
  3785. }
  3786. for(int i = 0; i < NUM_DEFAULT_SECURITY; i++)
  3787. {
  3788. pTempDescriptor = ReadSecurityDescriptor(i+1);
  3789. if(NULL == pTempDescriptor)
  3790. {
  3791. continue;
  3792. }
  3793. if(TRUE == CompareSD(pDefaultDescriptor,pTempDescriptor))
  3794. {
  3795. *pDefaultSecurity = i+1;
  3796. break;
  3797. }
  3798. else
  3799. {
  3800. LocalFree(pTempDescriptor);
  3801. pTempDescriptor = NULL;
  3802. }
  3803. }
  3804. if(pDefaultDescriptor)
  3805. {
  3806. LocalFree(pDefaultDescriptor);
  3807. }
  3808. if(pTempDescriptor)
  3809. {
  3810. LocalFree(pTempDescriptor);
  3811. }
  3812. return hResult;
  3813. }
  3814. //-----------------------------------------------------------------------------
  3815. STDMETHODIMP CCfgComp::SetDefaultSecurity(ULONG Offset)
  3816. {
  3817. HRESULT hResult;
  3818. if( !m_bAdmin )
  3819. {
  3820. return E_ACCESSDENIED;
  3821. }
  3822. if(0 == Offset)
  3823. {
  3824. return E_INVALIDARG;
  3825. }
  3826. PSECURITY_DESCRIPTOR pTempDescriptor = NULL;
  3827. pTempDescriptor = ReadSecurityDescriptor(Offset);
  3828. if(NULL == pTempDescriptor)
  3829. {
  3830. return E_FAIL;
  3831. }
  3832. hResult = SetDefaultSecurityDescriptor( pTempDescriptor );
  3833. if( pTempDescriptor != NULL )
  3834. {
  3835. LocalFree(pTempDescriptor);
  3836. }
  3837. return hResult;
  3838. }
  3839. //-----------------------------------------------------------------------------
  3840. PSECURITY_DESCRIPTOR CCfgComp::ReadSecurityDescriptor(ULONG index)
  3841. {
  3842. PBYTE pData = NULL;
  3843. TCHAR * pValue = NULL;
  3844. HLOCAL hLocal;
  3845. HKEY Handle = NULL;
  3846. DWORD ValueType = 0;
  3847. DWORD ValueSize=0;
  3848. LONG Status = 0;
  3849. switch(index)
  3850. {
  3851. case 0:
  3852. pValue = REG_DEF_SECURITY;
  3853. break;
  3854. case 1:
  3855. pValue = REG_REMOTE_SECURITY;
  3856. break;
  3857. case 2:
  3858. pValue = REG_APPL_SECURITY;
  3859. break;
  3860. case 3:
  3861. pValue = REG_ANON_SECURITY;
  3862. break;
  3863. default:
  3864. return NULL;
  3865. }
  3866. if(NULL == pValue)
  3867. {
  3868. return NULL;
  3869. }
  3870. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  3871. KEY_READ, &Handle );
  3872. if ( Status == ERROR_SUCCESS )
  3873. {
  3874. Status = RegQueryValueEx( Handle,
  3875. pValue,
  3876. NULL,
  3877. &ValueType,
  3878. NULL,
  3879. &ValueSize );
  3880. if(Status != ERROR_SUCCESS)
  3881. {
  3882. return NULL;
  3883. }
  3884. hLocal = LocalAlloc(LMEM_FIXED, ValueSize);
  3885. if(NULL == hLocal)
  3886. {
  3887. return pData;
  3888. }
  3889. pData = (LPBYTE)LocalLock(hLocal);
  3890. if(NULL == pData)
  3891. {
  3892. return NULL;
  3893. }
  3894. Status = RegQueryValueEx( Handle,
  3895. pValue,
  3896. NULL,
  3897. &ValueType,
  3898. pData,
  3899. &ValueSize );
  3900. if(Status != ERROR_SUCCESS)
  3901. {
  3902. RegCloseKey(Handle);
  3903. LocalFree(pData);
  3904. return NULL;
  3905. }
  3906. }
  3907. if(Handle)
  3908. {
  3909. RegCloseKey(Handle);
  3910. }
  3911. return (PSECURITY_DESCRIPTOR)pData;
  3912. }
  3913. //-----------------------------------------------------------------------------
  3914. HRESULT CCfgComp::SetDefaultSecurityDescriptor(PSECURITY_DESCRIPTOR pSecurity)
  3915. {
  3916. if(NULL == pSecurity)
  3917. {
  3918. return E_INVALIDARG;
  3919. }
  3920. if(ValidateSecurityDescriptor(pSecurity)!=ERROR_SUCCESS)
  3921. {
  3922. return E_INVALIDARG;
  3923. }
  3924. HKEY Handle = NULL;
  3925. LONG Status = 0;
  3926. ULONG Size = 0;
  3927. Size = GetSecurityDescriptorLength(pSecurity);
  3928. Status = RegOpenKeyEx( HKEY_LOCAL_MACHINE, WINSTATION_REG_NAME, 0,
  3929. KEY_READ |KEY_SET_VALUE , &Handle );
  3930. if ( Status == ERROR_SUCCESS )
  3931. {
  3932. Status = RegSetValueEx(Handle,
  3933. REG_DEF_SECURITY,
  3934. 0,
  3935. REG_BINARY,
  3936. (BYTE *)pSecurity,
  3937. Size);
  3938. if(Status != ERROR_SUCCESS)
  3939. {
  3940. return E_FAIL;
  3941. }
  3942. }
  3943. if( Handle )
  3944. {
  3945. RegCloseKey(Handle);
  3946. }
  3947. if( !_WinStationReInitializeSecurity( SERVERNAME_CURRENT ) )
  3948. {
  3949. ODS( L"CFGBKEND: _WinStationReInitializeSecurity failed\n" );
  3950. return E_FAIL;
  3951. }
  3952. return S_OK;
  3953. }
  3954. #endif //
  3955. //-----------------------------------------------------------------------------
  3956. STDMETHODIMP CCfgComp::SetActiveDesktopState( /* in */ BOOL bActivate , /* out */ PDWORD pdwStatus )
  3957. {
  3958. // HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoActiveDesktop
  3959. if( !m_bAdmin )
  3960. {
  3961. ODS( L"CFGBKEND : SetActiveDesktopState caller does not have admin rights\n" );
  3962. *pdwStatus = ERROR_ACCESS_DENIED;
  3963. return E_ACCESSDENIED;
  3964. }
  3965. // try to open key
  3966. HKEY hKey;
  3967. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  3968. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer" ) ,
  3969. 0,
  3970. KEY_READ | KEY_WRITE ,
  3971. &hKey );
  3972. if( *pdwStatus != ERROR_SUCCESS )
  3973. {
  3974. if( bActivate )
  3975. {
  3976. ODS( L"CFGBKEND : SetActiveDesktopState -- RegOpenEx unable to open key\n" );
  3977. return E_FAIL;
  3978. }
  3979. else
  3980. {
  3981. // the key doesn't exist but we were trying to disable anyway donot pro
  3982. // we should assert( 0 ) here because we should not be disabling what
  3983. // could not have been enabled
  3984. return S_FALSE;
  3985. }
  3986. }
  3987. if( !bActivate )
  3988. {
  3989. DWORD dwValue = 1;
  3990. *pdwStatus = RegSetValueEx( hKey ,
  3991. TEXT( "NoActiveDesktop" ),
  3992. NULL,
  3993. REG_DWORD,
  3994. ( LPBYTE )&dwValue ,
  3995. sizeof( DWORD ) );
  3996. }
  3997. else
  3998. {
  3999. *pdwStatus = RegDeleteValue( hKey , TEXT( "NoActiveDesktop" ) );
  4000. }
  4001. RegCloseKey( hKey );
  4002. if( *pdwStatus != NO_ERROR )
  4003. {
  4004. ODS( L"CFGBKEND : SetActiveDesktopState returned error\n" );
  4005. return E_FAIL;
  4006. }
  4007. return S_OK;
  4008. }
  4009. //-----------------------------------------------------------------------------
  4010. STDMETHODIMP CCfgComp::GetActiveDesktopState( /* out */ PBOOL pbActive , /* out */PDWORD pdwStatus)
  4011. {
  4012. if( pbActive == NULL )
  4013. {
  4014. ODS( L"CFGBKEND : GetActiveDesktop -- invaild arg\n" );
  4015. *pdwStatus = ERROR_FILE_NOT_FOUND;
  4016. return E_INVALIDARG;
  4017. }
  4018. // try to open key
  4019. HKEY hKey;
  4020. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4021. TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer" ) ,
  4022. 0,
  4023. KEY_READ ,
  4024. &hKey );
  4025. if( *pdwStatus != ERROR_SUCCESS )
  4026. {
  4027. ODS( L"CFGBKEND : GetActiveDesktopState -- RegOpenEx unable to open key\n" );
  4028. return E_FAIL;
  4029. }
  4030. DWORD dwData = 0;
  4031. DWORD dwSize = sizeof( DWORD );
  4032. *pdwStatus = RegQueryValueEx( hKey ,
  4033. TEXT( "NoActiveDesktop" ) ,
  4034. NULL ,
  4035. NULL ,
  4036. ( LPBYTE )&dwData ,
  4037. &dwSize );
  4038. // Status of this key is enabled if the key does not exist
  4039. if( *pdwStatus == ERROR_SUCCESS )
  4040. {
  4041. *pbActive = !( BOOL )dwData;
  4042. }
  4043. RegCloseKey( hKey );
  4044. if( *pdwStatus != ERROR_SUCCESS )
  4045. {
  4046. DBGMSG( L"CFGBKEND : GetActiveDesktopState -- error ret 0x%x\n" , *pdwStatus );
  4047. if( *pdwStatus == ERROR_FILE_NOT_FOUND )
  4048. {
  4049. *pbActive = TRUE;
  4050. return S_FALSE;
  4051. }
  4052. return E_FAIL;
  4053. }
  4054. return S_OK;
  4055. }
  4056. //-----------------------------------------------------------------------------
  4057. STDMETHODIMP CCfgComp::GetTermSrvMode( /* out */ PDWORD pdwMode , PDWORD pdwStatus )
  4058. {
  4059. ODS( L"CFGBKEND : GetTermSrvMode\n" );
  4060. if( pdwMode == NULL || pdwStatus == NULL )
  4061. {
  4062. return E_INVALIDARG;
  4063. }
  4064. HKEY hKey;
  4065. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4066. REG_CONTROL_TSERVER,
  4067. 0,
  4068. KEY_READ ,
  4069. &hKey );
  4070. if( *pdwStatus != ERROR_SUCCESS )
  4071. {
  4072. ODS( L"CFGBKEND : GetTermSrvMode -- RegOpenEx unable to open key\n" );
  4073. return E_FAIL;
  4074. }
  4075. DWORD dwData = 0;
  4076. DWORD dwSize = sizeof( DWORD );
  4077. *pdwStatus = RegQueryValueEx( hKey ,
  4078. TEXT( "TSAppCompat" ) ,
  4079. NULL ,
  4080. NULL ,
  4081. ( LPBYTE )&dwData ,
  4082. &dwSize );
  4083. if( *pdwStatus != ERROR_SUCCESS )
  4084. {
  4085. ODS( L"CFGBKEND : GetTermSrvMode -- RegQueryValueEx failed\n" );
  4086. *pdwMode = 1; // for application server
  4087. }
  4088. else
  4089. {
  4090. *pdwMode = dwData;
  4091. }
  4092. RegCloseKey( hKey );
  4093. return S_OK;
  4094. }
  4095. //-----------------------------------------------------------------------------
  4096. STDMETHODIMP CCfgComp::GetSalemHelpMode( BOOL *pVal, PDWORD pdwStatus)
  4097. {
  4098. HKEY hKey;
  4099. ODS( L"CFGBKEND : GetSalemHelpMode\n" );
  4100. if( pVal == NULL || pdwStatus == NULL )
  4101. {
  4102. return E_INVALIDARG;
  4103. }
  4104. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4105. REG_CONTROL_GETHELP,
  4106. 0,
  4107. KEY_READ ,
  4108. &hKey );
  4109. if( *pdwStatus != ERROR_SUCCESS )
  4110. {
  4111. ODS( L"CFGBKEND : GetSalemHelpMode -- RegOpenEx unable to open key\n" );
  4112. *pVal = 1; // default to help is available
  4113. // don't want to fail caller so return S_OK
  4114. return S_OK;
  4115. }
  4116. DWORD dwData = 0;
  4117. DWORD dwSize = sizeof( DWORD );
  4118. *pdwStatus = RegQueryValueEx( hKey ,
  4119. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  4120. NULL ,
  4121. NULL ,
  4122. ( LPBYTE )&dwData ,
  4123. &dwSize );
  4124. if( *pdwStatus != ERROR_SUCCESS )
  4125. {
  4126. ODS( L"CFGBKEND : GetSalemHelpMode -- RegQueryValueEx failed\n" );
  4127. *pVal = 1; // assume help is available
  4128. }
  4129. else
  4130. {
  4131. *pVal = dwData;
  4132. }
  4133. RegCloseKey( hKey );
  4134. return S_OK;
  4135. }
  4136. //-----------------------------------------------------------------------------
  4137. STDMETHODIMP CCfgComp::SetSalemHelpMode( BOOL val, PDWORD pdwStatus )
  4138. {
  4139. HKEY hKey;
  4140. ODS( L"CFGBKEND : SetSalemHelpMode\n" );
  4141. if( pdwStatus == NULL )
  4142. {
  4143. return E_INVALIDARG;
  4144. }
  4145. *pdwStatus = RegCreateKeyEx(
  4146. HKEY_LOCAL_MACHINE,
  4147. REG_CONTROL_GETHELP,
  4148. 0,
  4149. NULL,
  4150. REG_OPTION_NON_VOLATILE,
  4151. KEY_ALL_ACCESS,
  4152. NULL,
  4153. &hKey,
  4154. NULL
  4155. );
  4156. if( ERROR_SUCCESS != *pdwStatus )
  4157. {
  4158. ODS( L"CFGBKEND : SetSalemHelpMode -- RegCreateKeyEx failed\n" );
  4159. return E_FAIL;
  4160. }
  4161. DWORD dwValue;
  4162. dwValue = (val) ? 1 : 0;
  4163. *pdwStatus = RegSetValueEx(
  4164. hKey,
  4165. POLICY_TS_REMDSK_ALLOWTOGETHELP,
  4166. 0,
  4167. REG_DWORD,
  4168. (LPBYTE) &dwValue,
  4169. sizeof(DWORD)
  4170. );
  4171. RegCloseKey(hKey);
  4172. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4173. }
  4174. //-----------------------------------------------------------------------------
  4175. HRESULT CCfgComp::GetSingleSessionState( BOOL *pVal, PDWORD pdwStatus )
  4176. {
  4177. HKEY hKey;
  4178. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
  4179. ODS( L"CFGBKEND : GetSingleSessionState\n" );
  4180. if( pVal == NULL || pdwStatus == NULL )
  4181. {
  4182. return E_INVALIDARG;
  4183. }
  4184. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4185. tchRegPath ,
  4186. 0,
  4187. KEY_READ ,
  4188. &hKey );
  4189. if( *pdwStatus != ERROR_SUCCESS )
  4190. {
  4191. ODS( L"CFGBKEND : GetSingleSessionState -- RegOpenKeyEx unable to open key\n" );
  4192. return S_OK;
  4193. }
  4194. DWORD dwData = 0;
  4195. DWORD dwSize = sizeof( DWORD );
  4196. *pdwStatus = RegQueryValueEx( hKey ,
  4197. L"fSingleSessionPerUser",
  4198. NULL ,
  4199. NULL ,
  4200. ( LPBYTE )&dwData ,
  4201. &dwSize );
  4202. if( *pdwStatus == ERROR_SUCCESS )
  4203. {
  4204. *pVal = dwData;
  4205. }
  4206. else
  4207. {
  4208. ODS( L"CFGBKEND : GetSingleSessionState -- RegQueryValueEx failed\n" );
  4209. }
  4210. RegCloseKey( hKey );
  4211. return S_OK;
  4212. }
  4213. //----------------------------------------------------------------------------
  4214. HRESULT CCfgComp::SetSingleSessionState( BOOL val, PDWORD pdwStatus )
  4215. {
  4216. HKEY hKey;
  4217. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
  4218. ODS( L"CFGBKEND : SetSingleSessionState\n" );
  4219. if( pdwStatus == NULL )
  4220. {
  4221. return E_INVALIDARG;
  4222. }
  4223. *pdwStatus = RegCreateKeyEx(
  4224. HKEY_LOCAL_MACHINE,
  4225. tchRegPath,
  4226. 0,
  4227. NULL,
  4228. REG_OPTION_NON_VOLATILE,
  4229. KEY_ALL_ACCESS,
  4230. NULL,
  4231. &hKey,
  4232. NULL
  4233. );
  4234. if( ERROR_SUCCESS != *pdwStatus )
  4235. {
  4236. ODS( L"CFGBKEND : SetSingleSessionState -- RegCreateKeyEx failed\n" );
  4237. if (ERROR_ACCESS_DENIED == *pdwStatus)
  4238. return E_ACCESSDENIED;
  4239. else
  4240. return E_FAIL;
  4241. }
  4242. DWORD dwValue;
  4243. dwValue = (val) ? 1 : 0;
  4244. *pdwStatus = RegSetValueEx(
  4245. hKey,
  4246. L"fSingleSessionPerUser",
  4247. 0,
  4248. REG_DWORD,
  4249. (LPBYTE) &dwValue,
  4250. sizeof(DWORD)
  4251. );
  4252. if( ERROR_SUCCESS != *pdwStatus )
  4253. {
  4254. ODS( L"CFGBKEND : SetSingleSessionState -- RegSetValueEx failed\n" );
  4255. if (ERROR_ACCESS_DENIED == *pdwStatus)
  4256. return E_ACCESSDENIED;
  4257. else
  4258. return E_FAIL;
  4259. }
  4260. RegCloseKey(hKey);
  4261. UpdateSessionDirectory(pdwStatus);
  4262. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4263. }
  4264. //-----------------------------------------------------------------------------
  4265. HRESULT CCfgComp::GetDisableForcibleLogoff( BOOL *pVal, PDWORD pdwStatus )
  4266. {
  4267. HKEY hKey = NULL;
  4268. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
  4269. ODS( L"CFGBKEND : GetDisableForcibleLogoff\n" );
  4270. if( pVal == NULL || pdwStatus == NULL )
  4271. {
  4272. return E_INVALIDARG;
  4273. }
  4274. *pVal = 0;
  4275. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4276. tchRegPath ,
  4277. 0,
  4278. KEY_READ ,
  4279. &hKey );
  4280. if( *pdwStatus != ERROR_SUCCESS )
  4281. {
  4282. ODS( L"CFGBKEND : GetSingleSessionState -- RegOpenKeyEx unable to open key\n" );
  4283. return S_OK;
  4284. }
  4285. DWORD dwData = 0;
  4286. DWORD dwSize = sizeof( DWORD );
  4287. *pdwStatus = RegQueryValueEx( hKey ,
  4288. L"fDisableForcibleLogoff",
  4289. NULL ,
  4290. NULL ,
  4291. ( LPBYTE )&dwData ,
  4292. &dwSize );
  4293. if( *pdwStatus == ERROR_SUCCESS )
  4294. {
  4295. *pVal = dwData;
  4296. }
  4297. else
  4298. {
  4299. ODS( L"CFGBKEND : GetDisableForcibleLogoff -- RegQueryValueEx failed\n" );
  4300. }
  4301. if(hKey)
  4302. {
  4303. RegCloseKey( hKey );
  4304. }
  4305. return S_OK;
  4306. }
  4307. //----------------------------------------------------------------------------
  4308. HRESULT CCfgComp::SetDisableForcibleLogoff( BOOL val, PDWORD pdwStatus )
  4309. {
  4310. HKEY hKey = NULL;
  4311. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server" );
  4312. ODS( L"CFGBKEND : SetDisableForceLogoff\n" );
  4313. if( pdwStatus == NULL )
  4314. {
  4315. return E_INVALIDARG;
  4316. }
  4317. *pdwStatus = RegCreateKeyEx(
  4318. HKEY_LOCAL_MACHINE,
  4319. tchRegPath,
  4320. 0,
  4321. NULL,
  4322. REG_OPTION_NON_VOLATILE,
  4323. KEY_ALL_ACCESS,
  4324. NULL,
  4325. &hKey,
  4326. NULL
  4327. );
  4328. if( ERROR_SUCCESS != *pdwStatus )
  4329. {
  4330. ODS( L"CFGBKEND : SetDisableForceLogoff -- RegCreateKeyEx failed\n" );
  4331. if (ERROR_ACCESS_DENIED == *pdwStatus)
  4332. return E_ACCESSDENIED;
  4333. else
  4334. return E_FAIL;
  4335. }
  4336. DWORD dwValue;
  4337. dwValue = (val) ? 1 : 0;
  4338. *pdwStatus = RegSetValueEx(
  4339. hKey,
  4340. L"fDisableForcibleLogoff",
  4341. 0,
  4342. REG_DWORD,
  4343. (LPBYTE) &dwValue,
  4344. sizeof(DWORD)
  4345. );
  4346. if( ERROR_SUCCESS != *pdwStatus )
  4347. {
  4348. ODS( L"CFGBKEND : SetDisableForceLogoff -- RegSetValueEx failed\n" );
  4349. if (ERROR_ACCESS_DENIED == *pdwStatus)
  4350. return E_ACCESSDENIED;
  4351. else
  4352. return E_FAIL;
  4353. }
  4354. if(hKey)
  4355. {
  4356. RegCloseKey(hKey);
  4357. }
  4358. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4359. }
  4360. //-----------------------------------------------------------------------------
  4361. HRESULT CCfgComp::GetColorDepth ( PWINSTATIONNAME pWs, BOOL *pVal, PDWORD pdwStatus )
  4362. {
  4363. HKEY hKey;
  4364. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
  4365. // make sure winstation name isn't longer than it should be
  4366. if (lstrlen(pWs) > WINSTATIONNAME_LENGTH)
  4367. {
  4368. return E_INVALIDARG;
  4369. }
  4370. if(pWs != NULL)
  4371. {
  4372. lstrcat( tchRegPath , pWs );
  4373. }
  4374. ODS( L"CFGBKEND : GetColorDepth\n" );
  4375. if( pVal == NULL || pdwStatus == NULL )
  4376. {
  4377. return E_INVALIDARG;
  4378. }
  4379. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4380. tchRegPath ,
  4381. 0,
  4382. KEY_READ ,
  4383. &hKey );
  4384. if( *pdwStatus != ERROR_SUCCESS )
  4385. {
  4386. ODS( L"CFGBKEND : GetColorDepth -- RegOpenKeyEx unable to open key\n" );
  4387. return E_FAIL;
  4388. }
  4389. DWORD dwData = 0;
  4390. DWORD dwSize = sizeof( DWORD );
  4391. *pdwStatus = RegQueryValueEx( hKey ,
  4392. L"fInheritColorDepth",
  4393. NULL ,
  4394. NULL ,
  4395. ( LPBYTE )&dwData ,
  4396. &dwSize );
  4397. if( *pdwStatus == ERROR_SUCCESS )
  4398. {
  4399. *pVal = dwData;
  4400. }
  4401. else
  4402. {
  4403. ODS( L"CFGBKEND : GetColorDepth -- RegQueryValueEx failed\n" );
  4404. }
  4405. RegCloseKey( hKey );
  4406. return S_OK;
  4407. }
  4408. //----------------------------------------------------------------------------
  4409. HRESULT CCfgComp::SetColorDepth( PWINSTATIONNAME pWs, BOOL val, PDWORD pdwStatus )
  4410. {
  4411. HKEY hKey;
  4412. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
  4413. // make sure winstation name isn't longer than it should be
  4414. if (lstrlen(pWs) > WINSTATIONNAME_LENGTH)
  4415. {
  4416. return E_INVALIDARG;
  4417. }
  4418. if(pWs != NULL)
  4419. {
  4420. lstrcat( tchRegPath , pWs );
  4421. }
  4422. ODS( L"CFGBKEND : SetColorDepth\n" );
  4423. if( pdwStatus == NULL )
  4424. {
  4425. return E_INVALIDARG;
  4426. }
  4427. *pdwStatus = RegCreateKeyEx(
  4428. HKEY_LOCAL_MACHINE,
  4429. tchRegPath ,
  4430. 0,
  4431. NULL,
  4432. REG_OPTION_NON_VOLATILE,
  4433. KEY_ALL_ACCESS,
  4434. NULL,
  4435. &hKey,
  4436. NULL
  4437. );
  4438. if( ERROR_SUCCESS != *pdwStatus )
  4439. {
  4440. ODS( L"CFGBKEND : SetColorDepth -- RegCreateKeyEx failed\n" );
  4441. return E_FAIL;
  4442. }
  4443. DWORD dwValue;
  4444. dwValue = (val) ? 1 : 0;
  4445. *pdwStatus = RegSetValueEx(
  4446. hKey,
  4447. L"fInheritColorDepth",
  4448. 0,
  4449. REG_DWORD,
  4450. (LPBYTE) &dwValue,
  4451. sizeof(DWORD)
  4452. );
  4453. RegCloseKey(hKey);
  4454. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4455. }
  4456. //-----------------------------------------------------------------------------
  4457. HRESULT CCfgComp::GetKeepAliveTimeout ( PWINSTATIONNAME pWs, BOOL *pVal, PDWORD pdwStatus )
  4458. {
  4459. HKEY hKey;
  4460. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
  4461. // make sure winstation name isn't longer than it should be
  4462. if (lstrlen(pWs) > WINSTATIONNAME_LENGTH)
  4463. {
  4464. return E_INVALIDARG;
  4465. }
  4466. if(pWs != NULL)
  4467. {
  4468. lstrcat( tchRegPath , pWs );
  4469. }
  4470. ODS( L"CFGBKEND : GetKeepAliveTimeout\n" );
  4471. if( pVal == NULL || pdwStatus == NULL )
  4472. {
  4473. return E_INVALIDARG;
  4474. }
  4475. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4476. tchRegPath ,
  4477. 0,
  4478. KEY_READ ,
  4479. &hKey );
  4480. if( *pdwStatus != ERROR_SUCCESS )
  4481. {
  4482. ODS( L"CFGBKEND : GetKeepAliveTimeout -- RegOpenKeyEx unable to open key\n" );
  4483. return E_FAIL;
  4484. }
  4485. DWORD dwData = 0;
  4486. DWORD dwSize = sizeof( DWORD );
  4487. *pdwStatus = RegQueryValueEx( hKey ,
  4488. L"KeepAliveTimeout",
  4489. NULL ,
  4490. NULL ,
  4491. ( LPBYTE )&dwData ,
  4492. &dwSize );
  4493. if( *pdwStatus == ERROR_SUCCESS )
  4494. {
  4495. *pVal = dwData;
  4496. }
  4497. else
  4498. {
  4499. ODS( L"CFGBKEND : GetKeepAliveTimeout -- RegQueryValueEx failed\n" );
  4500. }
  4501. RegCloseKey( hKey );
  4502. return S_OK;
  4503. }
  4504. //----------------------------------------------------------------------------
  4505. HRESULT CCfgComp::SetKeepAliveTimeout( PWINSTATIONNAME pWs, BOOL val, PDWORD pdwStatus )
  4506. {
  4507. HKEY hKey;
  4508. TCHAR tchRegPath[ MAX_PATH ] = TEXT( "system\\currentcontrolset\\control\\Terminal Server\\winstations\\" );
  4509. // make sure winstation name isn't longer than it should be
  4510. if (lstrlen(pWs) > WINSTATIONNAME_LENGTH)
  4511. {
  4512. return E_INVALIDARG;
  4513. }
  4514. if(pWs != NULL)
  4515. {
  4516. lstrcat( tchRegPath , pWs );
  4517. }
  4518. ODS( L"CFGBKEND : SetKeepAliveTimeout\n" );
  4519. if( pdwStatus == NULL )
  4520. {
  4521. return E_INVALIDARG;
  4522. }
  4523. *pdwStatus = RegCreateKeyEx(
  4524. HKEY_LOCAL_MACHINE,
  4525. tchRegPath ,
  4526. 0,
  4527. NULL,
  4528. REG_OPTION_NON_VOLATILE,
  4529. KEY_ALL_ACCESS,
  4530. NULL,
  4531. &hKey,
  4532. NULL
  4533. );
  4534. if( ERROR_SUCCESS != *pdwStatus )
  4535. {
  4536. ODS( L"CFGBKEND : SetKeepAliveTimeout -- RegCreateKeyEx failed\n" );
  4537. return E_FAIL;
  4538. }
  4539. DWORD dwValue;
  4540. dwValue = (val) ? 1 : 0;
  4541. *pdwStatus = RegSetValueEx(
  4542. hKey,
  4543. L"KeepAliveTimeout",
  4544. 0,
  4545. REG_DWORD,
  4546. (LPBYTE) &dwValue,
  4547. sizeof(DWORD)
  4548. );
  4549. RegCloseKey(hKey);
  4550. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4551. }
  4552. //-----------------------------------------------------------------------------
  4553. HRESULT CCfgComp::GetDenyTSConnections ( BOOL *pVal, PDWORD pdwStatus )
  4554. {
  4555. HKEY hKey;
  4556. ODS( L"CFGBKEND : GetDenyTSConnections\n" );
  4557. if( pVal == NULL || pdwStatus == NULL )
  4558. {
  4559. return E_INVALIDARG;
  4560. }
  4561. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4562. REG_CONTROL_TSERVER ,
  4563. 0,
  4564. KEY_READ ,
  4565. &hKey );
  4566. if( *pdwStatus != ERROR_SUCCESS )
  4567. {
  4568. ODS( L"CFGBKEND : GetDenyTSConnections -- RegOpenKeyEx unable to open key\n" );
  4569. return S_OK;
  4570. }
  4571. DWORD dwData = 0;
  4572. DWORD dwSize = sizeof( DWORD );
  4573. *pdwStatus = RegQueryValueEx( hKey ,
  4574. L"fDenyTSConnections",
  4575. NULL ,
  4576. NULL ,
  4577. ( LPBYTE )&dwData ,
  4578. &dwSize );
  4579. if( *pdwStatus == ERROR_SUCCESS )
  4580. {
  4581. *pVal = dwData;
  4582. }
  4583. else
  4584. {
  4585. ODS( L"CFGBKEND : GetDenyTSConnections -- RegQueryValueEx failed\n" );
  4586. }
  4587. RegCloseKey( hKey );
  4588. return S_OK;
  4589. }
  4590. //----------------------------------------------------------------------------
  4591. HRESULT CCfgComp::SetDenyTSConnections( BOOL val, PDWORD pdwStatus )
  4592. {
  4593. HKEY hKey;
  4594. ODS( L"CFGBKEND : SetDenyTSConnections\n" );
  4595. if( pdwStatus == NULL )
  4596. {
  4597. return E_INVALIDARG;
  4598. }
  4599. *pdwStatus = RegCreateKeyEx(
  4600. HKEY_LOCAL_MACHINE,
  4601. REG_CONTROL_TSERVER ,
  4602. 0,
  4603. NULL,
  4604. REG_OPTION_NON_VOLATILE,
  4605. KEY_ALL_ACCESS,
  4606. NULL,
  4607. &hKey,
  4608. NULL
  4609. );
  4610. if( ERROR_SUCCESS != *pdwStatus )
  4611. {
  4612. ODS( L"CFGBKEND : SetDenyTSConnections -- RegCreateKeyEx failed\n" );
  4613. return E_FAIL;
  4614. }
  4615. DWORD dwValue;
  4616. dwValue = (val) ? 1 : 0;
  4617. *pdwStatus = RegSetValueEx(
  4618. hKey,
  4619. L"fDenyTSConnections",
  4620. 0,
  4621. REG_DWORD,
  4622. (LPBYTE) &dwValue,
  4623. sizeof(DWORD)
  4624. );
  4625. RegCloseKey(hKey);
  4626. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4627. }
  4628. //-----------------------------------------------------------------------------
  4629. HRESULT CCfgComp::GetProfilePath ( BSTR *pbstrVal, PDWORD pdwStatus )
  4630. {
  4631. HKEY hKey;
  4632. DWORD dwSize = 0;
  4633. static TCHAR tchData[ MAX_PATH ] ;
  4634. dwSize = sizeof( tchData);
  4635. ODS( L"CFGBKEND : GetProfilePath\n" );
  4636. if( pdwStatus == NULL )
  4637. {
  4638. return E_INVALIDARG;
  4639. }
  4640. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4641. REG_CONTROL_TSERVER ,
  4642. 0,
  4643. KEY_READ ,
  4644. &hKey );
  4645. if( *pdwStatus != ERROR_SUCCESS )
  4646. {
  4647. ODS( L"CFGBKEND : GetProfilePath -- RegOpenKeyEx unable to open key\n" );
  4648. return E_FAIL;
  4649. }
  4650. dwSize = sizeof( tchData );
  4651. *pdwStatus = RegQueryValueEx( hKey ,
  4652. L"WFProfilePath",
  4653. NULL ,
  4654. NULL ,
  4655. (LPBYTE)&tchData ,
  4656. &dwSize );
  4657. if( *pdwStatus == ERROR_SUCCESS )
  4658. {
  4659. *pbstrVal = SysAllocString (tchData);
  4660. }
  4661. else
  4662. {
  4663. ODS( L"CFGBKEND : GetProfilePath -- RegQueryValueEx failed\n" );
  4664. }
  4665. RegCloseKey( hKey );
  4666. return S_OK;
  4667. }
  4668. //----------------------------------------------------------------------------
  4669. HRESULT CCfgComp::SetProfilePath( BSTR bstrVal, PDWORD pdwStatus )
  4670. {
  4671. HKEY hKey;
  4672. ODS( L"CFGBKEND : SetProfilePath\n" );
  4673. if( pdwStatus == NULL )
  4674. {
  4675. return E_INVALIDARG;
  4676. }
  4677. *pdwStatus = RegCreateKeyEx(
  4678. HKEY_LOCAL_MACHINE,
  4679. REG_CONTROL_TSERVER,
  4680. 0,
  4681. NULL,
  4682. REG_OPTION_NON_VOLATILE,
  4683. KEY_ALL_ACCESS,
  4684. NULL,
  4685. &hKey,
  4686. NULL
  4687. );
  4688. if( ERROR_SUCCESS != *pdwStatus )
  4689. {
  4690. ODS( L"CFGBKEND : SetProfilePath -- RegCreateKeyEx failed\n" );
  4691. return E_FAIL;
  4692. }
  4693. *pdwStatus = RegSetValueEx(
  4694. hKey,
  4695. L"WFProfilePath",
  4696. 0,
  4697. REG_SZ,
  4698. ( LPBYTE const )(bstrVal) ,
  4699. (lstrlen(bstrVal)+1)*sizeof(WCHAR)
  4700. );
  4701. ODS( L"CFGBKEND : SetProfilePath -- RegCreateKeyEx failed\n" );
  4702. if(bstrVal != NULL)
  4703. {
  4704. SysFreeString(bstrVal);
  4705. }
  4706. RegCloseKey(hKey);
  4707. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4708. }
  4709. //-----------------------------------------------------------------------------
  4710. HRESULT CCfgComp::GetHomeDir ( BSTR *pbstrVal, PDWORD pdwStatus )
  4711. {
  4712. HKEY hKey;
  4713. DWORD dwSize = 0;
  4714. static TCHAR tchData[ MAX_PATH ] ;
  4715. dwSize = sizeof( tchData);
  4716. ODS( L"CFGBKEND : GetHomeDir\n" );
  4717. if( pdwStatus == NULL )
  4718. {
  4719. return E_INVALIDARG;
  4720. }
  4721. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4722. REG_CONTROL_TSERVER ,
  4723. 0,
  4724. KEY_READ ,
  4725. &hKey );
  4726. if( *pdwStatus != ERROR_SUCCESS )
  4727. {
  4728. ODS( L"CFGBKEND : GetProfilePath -- RegOpenKeyEx unable to open key\n" );
  4729. return E_FAIL;
  4730. }
  4731. *pdwStatus = RegQueryValueEx( hKey ,
  4732. L"WFHomeDir",
  4733. NULL ,
  4734. NULL ,
  4735. (LPBYTE)&tchData ,
  4736. &dwSize );
  4737. if( *pdwStatus == ERROR_SUCCESS )
  4738. {
  4739. *pbstrVal = SysAllocString (tchData);
  4740. }
  4741. else
  4742. {
  4743. ODS( L"CFGBKEND : GetHomeDir -- RegQueryValueEx failed\n" );
  4744. }
  4745. RegCloseKey( hKey );
  4746. return S_OK;
  4747. }
  4748. //----------------------------------------------------------------------------
  4749. HRESULT CCfgComp::SetHomeDir( BSTR bstrVal, PDWORD pdwStatus )
  4750. {
  4751. HKEY hKey = NULL;
  4752. ODS( L"CFGBKEND : SetHomeDir\n" );
  4753. if( pdwStatus == NULL )
  4754. {
  4755. return E_INVALIDARG;
  4756. }
  4757. *pdwStatus = RegCreateKeyEx(
  4758. HKEY_LOCAL_MACHINE,
  4759. REG_CONTROL_TSERVER ,
  4760. 0,
  4761. NULL,
  4762. REG_OPTION_NON_VOLATILE,
  4763. KEY_ALL_ACCESS,
  4764. NULL,
  4765. &hKey,
  4766. NULL
  4767. );
  4768. if( ERROR_SUCCESS != *pdwStatus )
  4769. {
  4770. ODS( L"CFGBKEND : SetHomeDir -- RegCreateKeyEx failed\n" );
  4771. return E_FAIL;
  4772. }
  4773. *pdwStatus = RegSetValueEx(
  4774. hKey,
  4775. L"WFHomeDir",
  4776. 0,
  4777. REG_SZ,
  4778. ( LPBYTE const )(bstrVal) ,
  4779. (lstrlen(bstrVal)+1)*sizeof(WCHAR)
  4780. );
  4781. if(bstrVal != NULL)
  4782. {
  4783. SysFreeString(bstrVal);
  4784. }
  4785. if(hKey)
  4786. {
  4787. RegCloseKey(hKey);
  4788. }
  4789. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4790. }
  4791. //-----------------------------------------------------------------------------
  4792. HRESULT CCfgComp::GetTimeZoneRedirection ( BOOL *pVal, PDWORD pdwStatus )
  4793. {
  4794. HKEY hKey;
  4795. ODS( L"CFGBKEND : GetTimeZoneRedirection\n" );
  4796. if( pVal == NULL || pdwStatus == NULL )
  4797. {
  4798. return E_INVALIDARG;
  4799. }
  4800. *pVal = 0;
  4801. *pdwStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE ,
  4802. REG_CONTROL_TSERVER,
  4803. 0,
  4804. KEY_READ ,
  4805. &hKey );
  4806. if( *pdwStatus != ERROR_SUCCESS )
  4807. {
  4808. ODS( L"CFGBKEND : GetTimeZoneRedirection -- RegOpenKeyEx unable to open key\n" );
  4809. return S_OK;
  4810. }
  4811. DWORD dwData = 0;
  4812. DWORD dwSize = sizeof( DWORD );
  4813. *pdwStatus = RegQueryValueEx( hKey ,
  4814. L"fEnableTimeZoneRedirection",
  4815. NULL ,
  4816. NULL ,
  4817. ( LPBYTE )&dwData ,
  4818. &dwSize );
  4819. if( *pdwStatus == ERROR_SUCCESS )
  4820. {
  4821. *pVal = dwData;
  4822. }
  4823. else
  4824. {
  4825. ODS( L"CFGBKEND : GetTimeZoneRedirection -- RegQueryValueEx failed\n" );
  4826. }
  4827. RegCloseKey( hKey );
  4828. return S_OK;
  4829. }
  4830. //----------------------------------------------------------------------------
  4831. HRESULT CCfgComp::SetTimeZoneRedirection( BOOL val, PDWORD pdwStatus )
  4832. {
  4833. HKEY hKey;
  4834. ODS( L"CFGBKEND : SetTimeZoneRedirection\n" );
  4835. if( pdwStatus == NULL )
  4836. {
  4837. return E_INVALIDARG;
  4838. }
  4839. *pdwStatus = RegCreateKeyEx(
  4840. HKEY_LOCAL_MACHINE,
  4841. REG_CONTROL_TSERVER,
  4842. 0,
  4843. NULL,
  4844. REG_OPTION_NON_VOLATILE,
  4845. KEY_ALL_ACCESS,
  4846. NULL,
  4847. &hKey,
  4848. NULL
  4849. );
  4850. if( ERROR_SUCCESS != *pdwStatus )
  4851. {
  4852. ODS( L"CFGBKEND : SetTimeZoneRedirection -- RegCreateKeyEx failed\n" );
  4853. return E_FAIL;
  4854. }
  4855. DWORD dwValue;
  4856. dwValue = (val) ? 1 : 0;
  4857. *pdwStatus = RegSetValueEx(
  4858. hKey,
  4859. L"fEnableTimeZoneRedirection",
  4860. 0,
  4861. REG_DWORD,
  4862. (LPBYTE) &dwValue,
  4863. sizeof(DWORD)
  4864. );
  4865. RegCloseKey(hKey);
  4866. return (ERROR_SUCCESS == *pdwStatus ) ? S_OK : E_FAIL;
  4867. }
  4868. //-----------------------------------------------------------------------------
  4869. STDMETHODIMP CCfgComp::GetWdKey( WCHAR *wdname , WCHAR *wdkey )
  4870. {
  4871. if( wdname == NULL || wdkey == NULL )
  4872. {
  4873. return E_INVALIDARG;
  4874. }
  4875. PWD pWD = GetWdObject( wdname );
  4876. if(NULL == pWD)
  4877. {
  4878. return E_FAIL;
  4879. }
  4880. lstrcpy( wdkey , pWD->wdKey );
  4881. return S_OK;
  4882. }
  4883. /*=-----------------------------------------------------------------------------
  4884. pwszWinstaName -- name of winstation to modify.
  4885. pwszAccountName -- is the netbios name of the user we want to modify.
  4886. dwMask -- winstation specific access.
  4887. fDel -- TRUE to delete all DACL or SACL for the specifed
  4888. account if it exist, FALSE to add entry.
  4889. fAllow -- TRUE to allow, FALSE to deny, parameter ignored if
  4890. fDel is set to TRUE
  4891. fNew -- TRUE removes all existing entries for this account
  4892. FALSE no action taken, parameter ignored if fDel
  4893. is set to TRUE.
  4894. fAuditing -- TRUE, modify SACL, FALSE modify DACL.
  4895. pdwStatus -- status of operation
  4896. Remark:
  4897. fDel fNew Operation
  4898. ------- ------- ------------------------------------------
  4899. TRUE ignored Delete all entries for the specified user.
  4900. FALSE TRUE Delete all entries then add allow or deny
  4901. entry for the specified user.
  4902. FALSE FALSE Add allow or deny entry for the specified user,
  4903. no modify to existing entries.
  4904. =----------------------------------------------------------------------------*/
  4905. STDMETHODIMP CCfgComp::ModifyUserAccess( WCHAR *pwszWinstaName ,
  4906. WCHAR *pwszAccountName ,
  4907. DWORD dwMask ,
  4908. BOOL fDel ,
  4909. BOOL fAllow ,
  4910. BOOL fNew ,
  4911. BOOL fAuditing ,
  4912. PDWORD pdwStatus )
  4913. {
  4914. return ModifyWinstationSecurity( FALSE,
  4915. pwszWinstaName,
  4916. pwszAccountName,
  4917. dwMask,
  4918. fDel,
  4919. fAllow,
  4920. fNew,
  4921. fAuditing,
  4922. pdwStatus
  4923. );
  4924. }
  4925. //-----------------------------------------------------------------------------
  4926. STDMETHODIMP CCfgComp::ModifyDefaultSecurity( WCHAR *pwszWinstaName ,
  4927. WCHAR *pwszAccountName ,
  4928. DWORD dwMask ,
  4929. BOOL fDel ,
  4930. BOOL fAllow ,
  4931. BOOL fAuditing ,
  4932. PDWORD pdwStatus )
  4933. {
  4934. HRESULT hr = S_OK;
  4935. if( NULL == pwszWinstaName || 0 == lstrlen(pwszWinstaName) )
  4936. {
  4937. for( DWORD i = 0; i < g_numDefaultSecurity && SUCCEEDED(hr) ; i++ )
  4938. {
  4939. hr = ModifyWinstationSecurity(
  4940. TRUE,
  4941. g_pszDefaultSecurity[i],
  4942. pwszAccountName,
  4943. dwMask,
  4944. fDel,
  4945. fAllow,
  4946. FALSE, // never recreate default security
  4947. fAuditing,
  4948. pdwStatus
  4949. );
  4950. }
  4951. }
  4952. else
  4953. {
  4954. hr = ModifyWinstationSecurity(
  4955. TRUE,
  4956. pwszWinstaName,
  4957. pwszAccountName,
  4958. dwMask,
  4959. fDel,
  4960. fAllow,
  4961. FALSE, // never recreate default security
  4962. fAuditing,
  4963. pdwStatus
  4964. );
  4965. }
  4966. return hr;
  4967. }
  4968. DWORD
  4969. CCfgComp::GetUserSid(
  4970. LPCTSTR pwszAccountName,
  4971. PSID* ppUserSid
  4972. )
  4973. /*++
  4974. Abstract:
  4975. Retrieve User SID for user account.
  4976. Parameter:
  4977. pwszAccountName : Name of the account to retrieve SID.
  4978. ppUserSid : Pointer to PSID to receive SID for the account.
  4979. Returns:
  4980. ERROR_SUCCESS or Error Code
  4981. Note :
  4982. Retrieve only local account or domain account.
  4983. --*/
  4984. {
  4985. DWORD cbSid = 0;
  4986. DWORD cbDomain = 0;
  4987. PSID pSID = NULL;
  4988. LPTSTR pszDomain = NULL;
  4989. BOOL bStatus;
  4990. DWORD dwStatus = ERROR_SUCCESS;
  4991. SID_NAME_USE seUse;
  4992. bStatus = LookupAccountName(
  4993. NULL ,
  4994. pwszAccountName ,
  4995. NULL ,
  4996. &cbSid,
  4997. NULL ,
  4998. &cbDomain,
  4999. &seUse);
  5000. if( FALSE == bStatus )
  5001. {
  5002. dwStatus = GetLastError();
  5003. if( ERROR_INSUFFICIENT_BUFFER != dwStatus )
  5004. {
  5005. goto CLEANUPANDEXIT;
  5006. }
  5007. }
  5008. dwStatus = ERROR_SUCCESS;
  5009. pSID = ( PSID )LocalAlloc( LMEM_FIXED , cbSid );
  5010. pszDomain = ( LPTSTR )LocalAlloc( LMEM_FIXED , sizeof(WCHAR) * (cbDomain + 1) );
  5011. if( pSID == NULL || pszDomain == NULL )
  5012. {
  5013. dwStatus = GetLastError();
  5014. goto CLEANUPANDEXIT;
  5015. }
  5016. if( !LookupAccountName( NULL ,
  5017. pwszAccountName ,
  5018. pSID ,
  5019. &cbSid,
  5020. pszDomain ,
  5021. &cbDomain,
  5022. &seUse ) )
  5023. {
  5024. dwStatus = GetLastError();
  5025. }
  5026. else
  5027. {
  5028. *ppUserSid = pSID;
  5029. pSID = NULL;
  5030. }
  5031. CLEANUPANDEXIT:
  5032. if( NULL != pszDomain )
  5033. {
  5034. LocalFree( pszDomain );
  5035. }
  5036. if( NULL != pSID )
  5037. {
  5038. LocalFree( pSID );
  5039. }
  5040. return dwStatus;
  5041. }
  5042. DWORD
  5043. CCfgComp::RemoveUserEntriesInACL(
  5044. LPCTSTR pszUserName,
  5045. PACL pAcl,
  5046. PACL* ppNewAcl
  5047. )
  5048. /*++
  5049. Abstract :
  5050. Remote all DACL or SACL from ACL for the account.
  5051. Parameters:
  5052. pszUserName : Name of the user account to be removed from ACL list.
  5053. pAcl : Pointer to ACL.
  5054. ppNewAcl : Pointer to PACL to receive resulting ACL.
  5055. Returns:
  5056. ERROR_SUCCESS
  5057. ERROR_FILE_NOT_FOUND All ACL are flagged as INHERITED_ACE.
  5058. other error code
  5059. --*/
  5060. {
  5061. PSID pSystemAcctSid = NULL;
  5062. DWORD SidSize = 0;
  5063. DWORD index = 0;
  5064. DWORD dwStatus;
  5065. DWORD dwNumNewEntries = 0;
  5066. PSID pUserSid = NULL;
  5067. ULONG cbExplicitEntries = 0;
  5068. PEXPLICIT_ACCESS prgExplicitEntries = NULL;
  5069. PEXPLICIT_ACCESS prgExplicitEntriesNew = NULL;
  5070. ACL emptyACL;
  5071. //
  5072. // System account SID that we don't allow removing from our
  5073. // winstation security descriptor.
  5074. //
  5075. // Local System S-1-5-18
  5076. // Local Service S-1-5-19
  5077. // Network Service S-1-5-20
  5078. //
  5079. WELL_KNOWN_SID_TYPE RestrictedSid[] = {
  5080. WinLocalSystemSid,
  5081. WinLocalServiceSid,
  5082. WinNetworkServiceSid
  5083. };
  5084. DWORD numRestrictedSid = sizeof(RestrictedSid)/sizeof(RestrictedSid[0]);
  5085. //
  5086. // We can use this funtion since we don't use INHERITED_ACE
  5087. //
  5088. dwStatus = GetExplicitEntriesFromAcl(
  5089. pAcl ,
  5090. &cbExplicitEntries,
  5091. &prgExplicitEntries
  5092. );
  5093. if( ERROR_SUCCESS != dwStatus )
  5094. {
  5095. goto CLEANUPANDEXIT;
  5096. }
  5097. if( 0 == cbExplicitEntries )
  5098. {
  5099. dwStatus = ERROR_FILE_NOT_FOUND;
  5100. goto CLEANUPANDEXIT;
  5101. }
  5102. dwStatus = GetUserSid( pszUserName, &pUserSid );
  5103. if( ERROR_SUCCESS != dwStatus )
  5104. {
  5105. goto CLEANUPANDEXIT;
  5106. }
  5107. // Check if SID is one of system account, if so, reject removing it from
  5108. // our winstation security.
  5109. pSystemAcctSid = LocalAlloc( LPTR, SECURITY_MAX_SID_SIZE );
  5110. if( NULL == pSystemAcctSid )
  5111. {
  5112. dwStatus = GetLastError();
  5113. goto CLEANUPANDEXIT;
  5114. }
  5115. for( index = 0; index < numRestrictedSid; index++ )
  5116. {
  5117. SidSize = SECURITY_MAX_SID_SIZE;
  5118. if( !CreateWellKnownSid(RestrictedSid[index], NULL, pSystemAcctSid, &SidSize) )
  5119. {
  5120. dwStatus = GetLastError();
  5121. break;
  5122. }
  5123. if( EqualSid(pSystemAcctSid, pUserSid) )
  5124. {
  5125. dwStatus = ERROR_NOT_SUPPORTED;
  5126. break;
  5127. }
  5128. }
  5129. if( index < numRestrictedSid )
  5130. {
  5131. goto CLEANUPANDEXIT;
  5132. }
  5133. // create a big enough buffer
  5134. prgExplicitEntriesNew = ( PEXPLICIT_ACCESS )LocalAlloc( LMEM_FIXED , sizeof( EXPLICIT_ACCESS ) * cbExplicitEntries );
  5135. if( prgExplicitEntriesNew == NULL )
  5136. {
  5137. dwStatus = GetLastError();
  5138. goto CLEANUPANDEXIT;
  5139. }
  5140. for( ULONG idx = 0 ; idx < cbExplicitEntries; idx++ )
  5141. {
  5142. if( prgExplicitEntries[ idx ].Trustee.TrusteeForm == TRUSTEE_IS_SID )
  5143. {
  5144. if( !EqualSid( pUserSid, prgExplicitEntries[ idx ].Trustee.ptstrName ) )
  5145. {
  5146. // this one we can keep
  5147. // copy over EXPLICIT_ACCESS
  5148. prgExplicitEntriesNew[ dwNumNewEntries ].grfAccessPermissions = prgExplicitEntries[ idx ].grfAccessPermissions;
  5149. prgExplicitEntriesNew[ dwNumNewEntries ].grfAccessMode = prgExplicitEntries[ idx ].grfAccessMode;
  5150. prgExplicitEntriesNew[ dwNumNewEntries ].grfInheritance = prgExplicitEntries[ idx ].grfInheritance;
  5151. BuildTrusteeWithSid( &prgExplicitEntriesNew[ dwNumNewEntries ].Trustee , prgExplicitEntries[ idx ].Trustee.ptstrName );
  5152. dwNumNewEntries++;
  5153. }
  5154. }
  5155. }
  5156. if( !InitializeAcl( &emptyACL, sizeof(ACL), ACL_REVISION ) )
  5157. {
  5158. dwStatus = GetLastError();
  5159. goto CLEANUPANDEXIT;
  5160. }
  5161. //
  5162. // SetEntriesInAcl() make a copy of old ACL if count of explicit entries is 0, if
  5163. // we passed in NULL in third parameter, it will return NULL ACL which is same as
  5164. // everyone access refer to ds\security\ntmarta\newsrc\seia.cxx
  5165. // AccRewriteSetEntriesInAcl()
  5166. //
  5167. // Note: Actual bug in 728764 is the way we call BuildSecurityDescriptor() not here.
  5168. dwStatus = SetEntriesInAcl(
  5169. dwNumNewEntries,
  5170. prgExplicitEntriesNew,
  5171. &emptyACL,
  5172. ppNewAcl
  5173. );
  5174. CLEANUPANDEXIT:
  5175. if( pSystemAcctSid != NULL )
  5176. {
  5177. LocalFree( pSystemAcctSid );
  5178. }
  5179. if( pUserSid != NULL )
  5180. {
  5181. LocalFree( pUserSid );
  5182. }
  5183. if( prgExplicitEntriesNew != NULL )
  5184. {
  5185. LocalFree( prgExplicitEntriesNew );
  5186. }
  5187. if( NULL != prgExplicitEntries )
  5188. {
  5189. LocalFree( prgExplicitEntries );
  5190. }
  5191. return dwStatus;
  5192. }
  5193. PSECURITY_DESCRIPTOR
  5194. BuildSelfRelativeEmptyDACLSD()
  5195. /*++
  5196. Routine Description:
  5197. Build a Self-relative security descriptor with empty DACL.
  5198. Parameters:
  5199. None.
  5200. Return:
  5201. Pointer to SECURITY_DESCRIPTOR contains only empty DACL, no owner, group or
  5202. SACL or NULL if error, use GetLastError() to retrive the actual error code.
  5203. --*/
  5204. {
  5205. SECURITY_DESCRIPTOR EmptyDACLSD;
  5206. ACL EmptyACL;
  5207. DWORD cbSize = 0;
  5208. PSECURITY_DESCRIPTOR pSelfRelativeEmptySD = NULL;
  5209. DWORD dwStatus = ERROR_SUCCESS;
  5210. if( !InitializeSecurityDescriptor( &EmptyDACLSD, SECURITY_DESCRIPTOR_REVISION ) )
  5211. {
  5212. dwStatus = GetLastError();
  5213. goto CLEANUPANDEXIT;
  5214. }
  5215. if( !InitializeAcl( &EmptyACL, sizeof(ACL), ACL_REVISION ) )
  5216. {
  5217. dwStatus = GetLastError();
  5218. goto CLEANUPANDEXIT;
  5219. }
  5220. if( !SetSecurityDescriptorDacl( &EmptyDACLSD, TRUE, &EmptyACL, FALSE ) )
  5221. {
  5222. dwStatus = GetLastError();
  5223. goto CLEANUPANDEXIT;
  5224. }
  5225. if( !IsValidSecurityDescriptor(&EmptyDACLSD) )
  5226. {
  5227. SetLastError( ERROR_INTERNAL_ERROR );
  5228. dwStatus = ERROR_INTERNAL_ERROR;
  5229. goto CLEANUPANDEXIT;
  5230. }
  5231. if( !MakeSelfRelativeSD( &EmptyDACLSD, NULL, &cbSize ) )
  5232. {
  5233. if( cbSize == 0 )
  5234. {
  5235. dwStatus = GetLastError();
  5236. goto CLEANUPANDEXIT;
  5237. }
  5238. }
  5239. pSelfRelativeEmptySD = (PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, cbSize );
  5240. if( NULL == pSelfRelativeEmptySD )
  5241. {
  5242. dwStatus = GetLastError();
  5243. goto CLEANUPANDEXIT;
  5244. }
  5245. if( !MakeSelfRelativeSD( &EmptyDACLSD, pSelfRelativeEmptySD, &cbSize ) )
  5246. {
  5247. dwStatus = GetLastError();
  5248. }
  5249. CLEANUPANDEXIT:
  5250. if( ERROR_SUCCESS != dwStatus )
  5251. {
  5252. if( pSelfRelativeEmptySD != NULL )
  5253. {
  5254. LocalFree(pSelfRelativeEmptySD);
  5255. pSelfRelativeEmptySD = NULL;
  5256. }
  5257. }
  5258. return pSelfRelativeEmptySD;
  5259. }
  5260. HRESULT
  5261. CCfgComp::ModifyWinstationSecurity(
  5262. BOOL bDefaultSecurity,
  5263. WCHAR *pwszWinstaName ,
  5264. WCHAR *pwszAccountName ,
  5265. DWORD dwMask ,
  5266. BOOL fDel , // delete existing ACL entries for user passed in
  5267. BOOL fAllow , // Grant/Deny ACL
  5268. BOOL fNew , // New entries
  5269. BOOL fAuditing ,
  5270. PDWORD pdwStatus
  5271. )
  5272. /*++
  5273. Abstract :
  5274. Modify specific winstation security.
  5275. Parameters:
  5276. bDefaultSecurity : TRUE to modify default security, FALSE otherwise. Current
  5277. default security are ConsoleSecurity and DefaultSecurity.
  5278. pwszWinstaName : Name of the winstation or default security to be modified, if
  5279. bDefaultSecurity is TRUE, valid winstation name are ConsoleSecurity
  5280. and DefaultSecurity.
  5281. pwszAccountName : is the netbios name of the user we want to modify.
  5282. dwMask : winstation specific access.
  5283. fDel : TRUE to delete all DACL or SACL for the specifed
  5284. account if it exist, FALSE to add entry.
  5285. fAllow : TRUE to allow, FALSE to deny, parameter ignored if
  5286. fDel is set to TRUE
  5287. fNew : TRUE removes all existing entries for this account
  5288. FALSE no action taken, parameter ignored if fDel
  5289. is set to TRUE.
  5290. fAuditing : TRUE, modify SACL, FALSE modify DACL.
  5291. pdwStatus : Return status of operation
  5292. Returns:
  5293. S_OK, E_FAIL, E_INVALIDARG, win32 status code is returned via *pdwStatus.
  5294. Remark:
  5295. fDel fNew Operation
  5296. ------- ------- ------------------------------------------
  5297. TRUE ignored Delete all entries for the specified user.
  5298. FALSE TRUE Delete all entries then add allow or deny
  5299. entry for the specified user.
  5300. FALSE FALSE Add allow or deny entry for the specified user,
  5301. no modify to existing entries.
  5302. --*/
  5303. {
  5304. EXPLICIT_ACCESS ea;
  5305. HRESULT hr;
  5306. PACL pNewAcl = NULL;
  5307. PACL pAcl = NULL;
  5308. BOOL bOwnerDefaulted = FALSE;
  5309. BOOL bDaclDefaulted = FALSE;
  5310. BOOL bDaclPresent = FALSE;
  5311. BOOL bSaclPresent = FALSE;
  5312. BOOL bSaclDefaulted = FALSE;
  5313. PSECURITY_DESCRIPTOR pSD;
  5314. LONG lSize = 0;
  5315. DWORD dwSDLen = 0;
  5316. PACL pSacl = NULL;
  5317. PACL pDacl = NULL;
  5318. PSECURITY_DESCRIPTOR pNewSD = NULL;
  5319. if( pwszAccountName == NULL || pdwStatus == NULL )
  5320. {
  5321. ODS( L"CCfgComp::ModifyUserAccess -- invalid arg\n" );
  5322. return E_INVALIDARG;
  5323. }
  5324. *pdwStatus = 0;
  5325. if( TRUE == bDefaultSecurity )
  5326. {
  5327. if( FALSE == ValidDefaultSecurity( pwszWinstaName ) )
  5328. {
  5329. *pdwStatus = ERROR_INVALID_PARAMETER;
  5330. return E_INVALIDARG;
  5331. }
  5332. }
  5333. else if( pwszWinstaName == NULL )
  5334. {
  5335. *pdwStatus = ERROR_INVALID_PARAMETER;
  5336. return E_INVALIDARG;
  5337. }
  5338. hr = GetWinStationSecurity( bDefaultSecurity, pwszWinstaName , &pSD );
  5339. if( SUCCEEDED( hr ) )
  5340. {
  5341. if( pSD != NULL )
  5342. {
  5343. lSize = GetSecurityDescriptorLength(pSD);
  5344. }
  5345. else
  5346. {
  5347. hr = E_FAIL;
  5348. *pdwStatus = ERROR_INTERNAL_ERROR;
  5349. }
  5350. }
  5351. else
  5352. {
  5353. *pdwStatus = ERROR_INTERNAL_ERROR;
  5354. return hr;
  5355. }
  5356. if( fAuditing )
  5357. {
  5358. if( pSD != NULL && !GetSecurityDescriptorSacl( pSD ,
  5359. &bSaclPresent,
  5360. &pAcl,
  5361. &bSaclDefaulted ) )
  5362. {
  5363. *pdwStatus = GetLastError( ) ;
  5364. hr = E_FAIL;
  5365. }
  5366. }
  5367. else
  5368. {
  5369. if( pSD != NULL && !GetSecurityDescriptorDacl( pSD ,
  5370. &bDaclPresent,
  5371. &pAcl,
  5372. &bDaclDefaulted ) )
  5373. {
  5374. *pdwStatus = GetLastError( ) ;
  5375. hr = E_FAIL;
  5376. }
  5377. }
  5378. // remove all entries for this user
  5379. if( SUCCEEDED( hr ) )
  5380. {
  5381. if( fNew || fDel )
  5382. {
  5383. // SetEntriesInAcl() does not remove DENY_ACCESS ACL,
  5384. // pAcl will point to DACL or SACL depends on fAuditing
  5385. // flag.
  5386. *pdwStatus = RemoveUserEntriesInACL(
  5387. pwszAccountName,
  5388. pAcl,
  5389. &pNewAcl
  5390. );
  5391. if( *pdwStatus == ERROR_SUCCESS)
  5392. {
  5393. // DO NOTHING.
  5394. }
  5395. else if( *pdwStatus == ERROR_FILE_NOT_FOUND )
  5396. {
  5397. pNewAcl = pAcl;
  5398. *pdwStatus = ERROR_SUCCESS;
  5399. }
  5400. else
  5401. {
  5402. hr = E_FAIL;
  5403. }
  5404. }
  5405. }
  5406. if( SUCCEEDED(hr) && !fDel )
  5407. {
  5408. // auditing is requested build SACL
  5409. if( fAuditing )
  5410. {
  5411. BuildExplicitAccessWithName( &ea ,
  5412. pwszAccountName ,
  5413. dwMask ,
  5414. fAllow ? SET_AUDIT_SUCCESS : SET_AUDIT_FAILURE ,
  5415. NO_INHERITANCE );
  5416. *pdwStatus = SetEntriesInAcl( 1 , &ea , pAcl , &pNewAcl );
  5417. if( *pdwStatus != ERROR_SUCCESS )
  5418. {
  5419. hr = E_FAIL;
  5420. }
  5421. }
  5422. else
  5423. {
  5424. BuildExplicitAccessWithName( &ea ,
  5425. pwszAccountName ,
  5426. dwMask ,
  5427. fAllow ? GRANT_ACCESS : DENY_ACCESS ,
  5428. NO_INHERITANCE );
  5429. *pdwStatus = SetEntriesInAcl( 1 , &ea , pAcl , &pNewAcl );
  5430. if( *pdwStatus != ERROR_SUCCESS )
  5431. {
  5432. hr = E_FAIL;
  5433. }
  5434. }
  5435. }
  5436. // re-build SD.
  5437. ULONG cbExplicitEntriesDACL = 0;
  5438. PEXPLICIT_ACCESS prgExplicitEntriesDACL = NULL;
  5439. ULONG cbExplicitEntriesSACL = 0;
  5440. PEXPLICIT_ACCESS prgExplicitEntriesSACL = NULL;
  5441. if( SUCCEEDED( hr ) )
  5442. {
  5443. if( fAuditing )
  5444. {
  5445. if( GetExplicitEntriesFromAcl( pNewAcl ,
  5446. &cbExplicitEntriesSACL ,
  5447. &prgExplicitEntriesSACL ) != ERROR_SUCCESS )
  5448. {
  5449. ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
  5450. *pdwStatus = GetLastError();
  5451. hr = E_FAIL;
  5452. }
  5453. if( !GetSecurityDescriptorDacl( pSD , &bDaclPresent , &pDacl , &bDaclDefaulted ) )
  5454. {
  5455. ODS( L"CFGBKEND! GetSecurityDescriptorDacl failed\n" );
  5456. *pdwStatus = GetLastError();
  5457. hr = E_FAIL;
  5458. }
  5459. else
  5460. {
  5461. if( GetExplicitEntriesFromAcl( pDacl ,
  5462. &cbExplicitEntriesDACL ,
  5463. &prgExplicitEntriesDACL ) != ERROR_SUCCESS )
  5464. {
  5465. ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
  5466. *pdwStatus = GetLastError();
  5467. hr = E_FAIL;
  5468. }
  5469. }
  5470. }
  5471. else
  5472. {
  5473. if( GetExplicitEntriesFromAcl( pNewAcl ,
  5474. &cbExplicitEntriesDACL ,
  5475. &prgExplicitEntriesDACL ) != ERROR_SUCCESS )
  5476. {
  5477. ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
  5478. *pdwStatus = GetLastError();
  5479. hr = E_FAIL;
  5480. }
  5481. if( !GetSecurityDescriptorSacl( pSD , &bSaclPresent , &pSacl , &bSaclDefaulted ) )
  5482. {
  5483. ODS( L"CFGBKEND! GetSecurityDescriptorSacl failed\n" );
  5484. *pdwStatus = GetLastError();
  5485. hr = E_FAIL;
  5486. }
  5487. else
  5488. {
  5489. if( GetExplicitEntriesFromAcl( pSacl ,
  5490. &cbExplicitEntriesSACL ,
  5491. &prgExplicitEntriesSACL ) != ERROR_SUCCESS )
  5492. {
  5493. ODS( L"CFGBKEND! GetExplicitEntriesFromAcl failed\n" );
  5494. *pdwStatus = GetLastError();
  5495. hr = E_FAIL;
  5496. }
  5497. }
  5498. }
  5499. if( SUCCEEDED(hr) )
  5500. {
  5501. TRUSTEE trustmeOwner;
  5502. PSID pOwner;
  5503. if( !GetSecurityDescriptorOwner( pSD , &pOwner , &bOwnerDefaulted ) )
  5504. {
  5505. ODS( L"CFGBKEND! GetSecurityDescriptorOwner failed\n" );
  5506. *pdwStatus = GetLastError();
  5507. hr = E_FAIL;
  5508. }
  5509. if( SUCCEEDED( hr ) )
  5510. {
  5511. PSECURITY_DESCRIPTOR pOldSd = NULL;
  5512. BuildTrusteeWithSid( &trustmeOwner , pOwner );
  5513. if( cbExplicitEntriesDACL == 0 )
  5514. {
  5515. // refer to MSDN on pOldSd parameter and when it can't/can be NULL
  5516. // calling SetSecurityDescriptorDacl() with Empty DACL after
  5517. // BuildSecurityDescriptor() result in 0x519 error, so go with long
  5518. // way of creating a self-relatvie SD containing empty DACL.
  5519. pOldSd = BuildSelfRelativeEmptyDACLSD();
  5520. if( NULL == pOldSd )
  5521. {
  5522. *pdwStatus = GetLastError();
  5523. hr = HRESULT_FROM_WIN32( *pdwStatus );
  5524. }
  5525. }
  5526. if( SUCCEEDED(hr) )
  5527. {
  5528. // refer to MSDN on pOldSd parameter and when it can't/can be NULL
  5529. // calling SetSecurityDescriptorDacl() with Empty DACL after
  5530. // BuildSecurityDescriptor() result in 0x519 error, so go with long
  5531. // way of creating a self-relatvie SD containing empty DACL.
  5532. *pdwStatus = BuildSecurityDescriptor( &trustmeOwner ,
  5533. &trustmeOwner ,
  5534. cbExplicitEntriesDACL ,
  5535. prgExplicitEntriesDACL,
  5536. cbExplicitEntriesSACL,
  5537. prgExplicitEntriesSACL,
  5538. pOldSd,
  5539. &dwSDLen ,
  5540. &pNewSD );
  5541. hr = HRESULT_FROM_WIN32( *pdwStatus );
  5542. }
  5543. if( NULL != pOldSd )
  5544. {
  5545. LocalFree( pOldSd );
  5546. }
  5547. }
  5548. if( SUCCEEDED( hr ) )
  5549. {
  5550. hr = SetSecurityDescriptor( bDefaultSecurity, pwszWinstaName , dwSDLen , pNewSD );
  5551. if( pNewSD != NULL )
  5552. {
  5553. LocalFree( pNewSD );
  5554. }
  5555. }
  5556. }
  5557. }
  5558. if( NULL != prgExplicitEntriesDACL )
  5559. {
  5560. LocalFree( prgExplicitEntriesDACL );
  5561. }
  5562. if( NULL != prgExplicitEntriesSACL )
  5563. {
  5564. LocalFree( prgExplicitEntriesSACL );
  5565. }
  5566. if( pSD != NULL )
  5567. {
  5568. LocalFree( pSD );
  5569. }
  5570. //
  5571. // pNewAcl might point to pAcl, check RemoteUserEntriesInAcl() on above.
  5572. //
  5573. if( pNewAcl != NULL && pNewAcl != pAcl )
  5574. {
  5575. LocalFree( pNewAcl );
  5576. }
  5577. return hr;
  5578. }
  5579. /*=----------------------------------------------------------------------------------------------------------------
  5580. GetUserPermList
  5581. [ in ] pwszWinstaName Name of winstation
  5582. [ out] pcbItems The number of items in the user permission list
  5583. [ out] ppUserPermList structure defined in idldefs.h
  5584. =----------------------------------------------------------------------------------------------------------------*/
  5585. STDMETHODIMP CCfgComp::GetUserPermList( WCHAR *pwszWinstaName , PDWORD pcbItems , PUSERPERMLIST *ppUserPermList , BOOL fAudit )
  5586. {
  5587. HRESULT hr;
  5588. PSECURITY_DESCRIPTOR pSD = NULL;
  5589. BOOL bAclDefaulted;
  5590. BOOL bAclPresent;
  5591. PACL pAcl = NULL;
  5592. LONG lSize;
  5593. ULONG cbExplicitEntries = 0;
  5594. PEXPLICIT_ACCESS prgExplicitEntries = NULL;
  5595. hr = GetSecurityDescriptor( pwszWinstaName , &lSize , &pSD );
  5596. if( SUCCEEDED( hr ) )
  5597. {
  5598. if( fAudit )
  5599. {
  5600. if( !GetSecurityDescriptorSacl( pSD ,
  5601. &bAclPresent,
  5602. &pAcl,
  5603. &bAclDefaulted ) )
  5604. {
  5605. ODS( L"CFGBKEND!GetUserPermList GetSecurityDescriptorSacl failed\n" );
  5606. hr = E_FAIL;
  5607. }
  5608. }
  5609. else if( !GetSecurityDescriptorDacl( pSD ,
  5610. &bAclPresent,
  5611. &pAcl,
  5612. &bAclDefaulted ) )
  5613. {
  5614. ODS( L"CFGBKEND!GetUserPermList GetSecurityDescriptorDacl failed\n" );
  5615. hr = E_FAIL;
  5616. }
  5617. }
  5618. if( SUCCEEDED( hr ) )
  5619. {
  5620. if( GetExplicitEntriesFromAcl( pAcl ,
  5621. &cbExplicitEntries ,
  5622. &prgExplicitEntries ) != ERROR_SUCCESS )
  5623. {
  5624. ODS( L"CFGBKEND!GetUserPermList GetExplicitEntriesFromAcl failed\n" );
  5625. hr = E_FAIL;
  5626. }
  5627. *pcbItems = cbExplicitEntries;
  5628. }
  5629. if( SUCCEEDED( hr ) )
  5630. {
  5631. *ppUserPermList = ( PUSERPERMLIST )CoTaskMemAlloc( sizeof( USERPERMLIST ) * cbExplicitEntries );
  5632. if( *ppUserPermList != NULL )
  5633. {
  5634. for( ULONG i = 0; i < cbExplicitEntries; ++i )
  5635. {
  5636. ( *ppUserPermList )[ i ].Name[ 0 ] = 0;
  5637. ( *ppUserPermList )[ i ].Sid[ 0 ] = 0;
  5638. if( prgExplicitEntries[ i ].Trustee.TrusteeForm == TRUSTEE_IS_SID )
  5639. {
  5640. WCHAR szDomain[ 120 ];
  5641. WCHAR szUser[ 128 ];
  5642. DWORD dwSizeofName = sizeof( szUser ) / sizeof( WCHAR );
  5643. DWORD dwSizeofDomain = sizeof( szDomain ) / sizeof( WCHAR );
  5644. SID_NAME_USE snu;
  5645. if( LookupAccountSid( NULL ,
  5646. prgExplicitEntries[ i ].Trustee.ptstrName ,
  5647. szUser ,
  5648. &dwSizeofName ,
  5649. szDomain ,
  5650. &dwSizeofDomain ,
  5651. &snu ) )
  5652. {
  5653. if( dwSizeofDomain > 0 )
  5654. {
  5655. lstrcpy( ( *ppUserPermList )[ i ].Name , szDomain );
  5656. lstrcat( ( *ppUserPermList )[ i ].Name , L"\\" );
  5657. }
  5658. lstrcat( ( *ppUserPermList )[ i ].Name , szUser );
  5659. LPTSTR pszSid = NULL;
  5660. if( ConvertSidToStringSid( prgExplicitEntries[ i ].Trustee.ptstrName , &pszSid ) )
  5661. {
  5662. if( pszSid != NULL )
  5663. {
  5664. lstrcpyn( ( *ppUserPermList )[ i ].Sid , pszSid , 256 );
  5665. LocalFree( pszSid );
  5666. }
  5667. }
  5668. }
  5669. }
  5670. else if( prgExplicitEntries[ i ].Trustee.TrusteeForm == TRUSTEE_IS_NAME )
  5671. {
  5672. lstrcpy( ( *ppUserPermList )[ i ].Name , GetTrusteeName( &prgExplicitEntries[ i ].Trustee ) );
  5673. // todo reverse lookup for sid
  5674. // not sure if we'll ever need this
  5675. }
  5676. ( *ppUserPermList )[ i ].Mask = prgExplicitEntries[ i ].grfAccessPermissions;
  5677. ( *ppUserPermList )[ i ].Type = prgExplicitEntries[ i ].grfAccessMode;
  5678. }
  5679. }
  5680. else
  5681. {
  5682. ODS( L"CFGBKEND!GetUserPermList no mem for UserPermList\n" );
  5683. hr = E_OUTOFMEMORY;
  5684. }
  5685. }
  5686. if( prgExplicitEntries != NULL )
  5687. {
  5688. LocalFree( prgExplicitEntries );
  5689. }
  5690. if( pSD != NULL )
  5691. {
  5692. LocalFree( pSD );
  5693. }
  5694. return hr;
  5695. }
  5696. //-----------------------------------------------------------------------------
  5697. HRESULT CCfgComp::UpdateSessionDirectory( PDWORD pdwStatus )
  5698. {
  5699. HRESULT hr = S_OK;
  5700. if( !_WinStationUpdateSettings( SERVERNAME_CURRENT,
  5701. WINSTACFG_SESSDIR ,
  5702. 0 ) )
  5703. {
  5704. hr = E_FAIL;
  5705. }
  5706. *pdwStatus = GetLastError( );
  5707. return hr;
  5708. }
  5709. //-----------------------------------------------------------------------------
  5710. /*****************************************************************************
  5711. *
  5712. * TestUserForAdmin
  5713. *
  5714. * Returns whether the current thread is running under admin
  5715. * security.
  5716. *
  5717. * ENTRY:
  5718. * Param1 (input/output)
  5719. * Comments
  5720. *
  5721. * EXIT:
  5722. * STATUS_SUCCESS - no error
  5723. *
  5724. * alhen
  5725. *
  5726. * Code is from
  5727. * HOWTO: Determine if Running In User Context of Local Admin Acct
  5728. * Last reviewed: March 4, 1998
  5729. * Article ID: Q118626
  5730. *
  5731. * corrected by alhen "common coding errors"
  5732. *
  5733. *
  5734. ****************************************************************************/
  5735. BOOL TestUserForAdmin( )
  5736. {
  5737. PSID psidAdministrators = NULL;
  5738. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  5739. BOOL bSuccess;
  5740. BOOL bIsMember = FALSE;
  5741. bSuccess = AllocateAndInitializeSid( &siaNtAuthority , 2 ,
  5742. SECURITY_BUILTIN_DOMAIN_RID,
  5743. DOMAIN_ALIAS_RID_ADMINS,
  5744. 0, 0, 0, 0, 0, 0,
  5745. &psidAdministrators );
  5746. if( bSuccess )
  5747. {
  5748. CheckTokenMembership( NULL , psidAdministrators , &bIsMember );
  5749. FreeSid( psidAdministrators );
  5750. }
  5751. return bIsMember;
  5752. }