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.

3418 lines
84 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996-1998
  5. //
  6. // File: tlsapi.cpp
  7. //
  8. // Contents:
  9. //
  10. // History: 12-09-97 HueiWang Created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <windows.h>
  14. #include <wincrypt.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <tchar.h>
  18. #include <rpc.h>
  19. #include <ntsecapi.h>
  20. #include <lmcons.h>
  21. #include <lmserver.h>
  22. #include <lmerr.h>
  23. #include <lmapibuf.h>
  24. #include <ntdsapi.h>
  25. #include <dsrole.h>
  26. #include <lmjoin.h>
  27. #include <winldap.h>
  28. #include <winsock2.h>
  29. #include <dsgetdc.h>
  30. //
  31. // Only include RNG functions from tssec
  32. //
  33. #define NO_INCLUDE_LICENSING 1
  34. #include <tssec.h>
  35. #include "lscommon.h"
  36. #include "tlsrpc.h"
  37. #include "tlsapi.h"
  38. #include "tlsapip.h"
  39. #include "secstore.h"
  40. #include "lscsp.h"
  41. #include "license.h"
  42. extern "C" DWORD WINAPI
  43. TLSConnect(
  44. handle_t binding,
  45. TLS_HANDLE *pphContext
  46. );
  47. extern "C" DWORD WINAPI
  48. TLSDisconnect(
  49. TLS_HANDLE* pphContext
  50. );
  51. extern "C" BOOL
  52. IsSystemService();
  53. #include <lmcons.h> // Netxxx API includes
  54. #include <lmserver.h>
  55. #include <lmerr.h>
  56. #include <lmapibuf.h>
  57. #define DISCOVERY_INTERVAL (60 * 60 * 1000)
  58. static HANDLE g_hCachingThreadExit = NULL;
  59. static HANDLE g_hImmediateDiscovery = NULL;
  60. static HANDLE g_hDiscoverySoon = NULL;
  61. static BOOL g_fOffSiteLicenseServer = FALSE;
  62. static PSEC_WINNT_AUTH_IDENTITY g_pRpcIdentity = NULL;
  63. #define REG_DOMAIN_SERVER_MULTI L"DomainLicenseServerMulti"
  64. #define TERMINAL_SERVICE_PARAM_DISCOVERY "SYSTEM\\CurrentControlSet\\Services\\TermService\\Parameters\\LicenseServers"
  65. // 2 second timeout
  66. #define SERVER_NP_TIMEOUT (2 * 1000)
  67. #define INSTALL_CERT_DELAY (5 * 1000)
  68. BOOL g_fInDomain = -1;
  69. LONG lLibUsage = 0;
  70. typedef struct {
  71. TLS_HANDLE *hBinding;
  72. DWORD dwTimeout; // In milliseconds - INFINITE for none
  73. LARGE_INTEGER timeInitial; // As returned by QueryPerformanceCounter
  74. } LS_ENUM_PARAM, *PLS_ENUM_PARAM;
  75. void * MIDL_user_allocate(size_t size)
  76. {
  77. return(HeapAlloc(GetProcessHeap(), 0, size));
  78. }
  79. void MIDL_user_free( void *pointer)
  80. {
  81. HeapFree(GetProcessHeap(), 0, pointer);
  82. }
  83. #ifdef PRIVATEDEBUG
  84. //
  85. // FUNCTIONS: StartTime()
  86. // EndTime()
  87. //
  88. // USAGE:
  89. // StartTime();
  90. // // Do some work.
  91. // mseconds = EndTime();
  92. //
  93. // RETURN VALUE:
  94. // Milliseconds between StartTime() and EndTime() calls.
  95. LARGE_INTEGER TimeT;
  96. void StartTimeT(void)
  97. {
  98. QueryPerformanceCounter(&TimeT);
  99. }
  100. ULONG EndTimeT()
  101. {
  102. LARGE_INTEGER liDiff;
  103. LARGE_INTEGER liFreq;
  104. QueryPerformanceCounter(&liDiff);
  105. liDiff.QuadPart -= TimeT.QuadPart;
  106. liDiff.QuadPart *= 1000; // Adjust to milliseconds, shouldn't overflow...
  107. (void)QueryPerformanceFrequency(&liFreq);
  108. return ((ULONG)(liDiff.QuadPart / liFreq.QuadPart));
  109. }
  110. #endif
  111. //+------------------------------------------------------------------------
  112. // Function: ConnectToLsServer()
  113. //
  114. // Description:
  115. //
  116. // Binding to sepecific hydra license server
  117. //
  118. // Arguments:
  119. //
  120. // szLsServer - Hydra License Server name
  121. //
  122. // Return Value:
  123. //
  124. // RPC binding handle or NULL if error, use GetLastError() to retrieve
  125. // error.
  126. //-------------------------------------------------------------------------
  127. static TLS_HANDLE WINAPI
  128. ConnectLsServer(
  129. LPTSTR szLsServer,
  130. LPTSTR szProtocol,
  131. LPTSTR szEndPoint,
  132. DWORD dwAuthLevel )
  133. {
  134. LPTSTR szBindingString;
  135. RPC_BINDING_HANDLE hBinding=NULL;
  136. RPC_STATUS status;
  137. TLS_HANDLE pContext=NULL;
  138. BOOL fSuccess;
  139. HKEY hKey = NULL;
  140. DWORD dwType;
  141. DWORD cbData;
  142. DWORD dwErr;
  143. DWORD dwNumRetries = 1; // default to one retry
  144. LPWSTR pszServerPrincipalName = NULL;
  145. #ifdef PRIVATEDEBUG
  146. if (NULL != szLsServer)
  147. wprintf(L"server=%s\n",szLsServer);
  148. #endif
  149. //
  150. // If this isn't local
  151. //
  152. if ((NULL != szLsServer) && (NULL != szEndPoint))
  153. {
  154. TCHAR szPipeName[MAX_PATH+1];
  155. if (lstrlen(szLsServer) > ((sizeof(szPipeName) / sizeof(TCHAR)) - 26))
  156. {
  157. #ifdef PRIVATEDEBUG
  158. wprintf(L"Server name too long\n");
  159. #endif
  160. return NULL;
  161. }
  162. //
  163. // First check if license server named pipe exists
  164. //
  165. wsprintf(szPipeName,TEXT("\\\\%s\\pipe\\%s"),szLsServer,TEXT(SZSERVICENAME));
  166. #ifdef PRIVATEDEBUG
  167. StartTimeT();
  168. #endif
  169. fSuccess = WaitNamedPipe(szPipeName,SERVER_NP_TIMEOUT);
  170. #ifdef PRIVATEDEBUG
  171. ULONG ulTime = EndTimeT();
  172. wprintf(L"WaitNamedPipe time == %lu\n",ulTime);
  173. #endif
  174. if (!fSuccess)
  175. {
  176. #ifdef PRIVATEDEBUG
  177. wprintf(L"WaitNamedPipe (%s) failed 0x%x\n",szPipeName,GetLastError());
  178. #endif
  179. return NULL;
  180. }
  181. }
  182. #ifdef PRIVATEDEBUG
  183. else
  184. wprintf(L"Not trying WaitNamedPipe\n");
  185. #endif
  186. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  187. TEXT(LSERVER_DISCOVERY_PARAMETER_KEY),
  188. 0,
  189. KEY_READ,
  190. &hKey);
  191. if (dwErr == ERROR_SUCCESS)
  192. {
  193. cbData = sizeof(dwNumRetries);
  194. dwErr = RegQueryValueEx(hKey,
  195. L"NumRetries",
  196. NULL,
  197. &dwType,
  198. (PBYTE)&dwNumRetries,
  199. &cbData);
  200. RegCloseKey(hKey);
  201. }
  202. status = RpcStringBindingCompose(0,
  203. szProtocol,
  204. szLsServer,
  205. szEndPoint,
  206. 0,
  207. &szBindingString);
  208. if(status!=RPC_S_OK)
  209. {
  210. #ifdef PRIVATEDEBUG
  211. wprintf(L"RpcStringBindingCompose failed 0x%x\n",status);
  212. #endif
  213. return NULL;
  214. }
  215. status=RpcBindingFromStringBinding( szBindingString, &hBinding);
  216. RpcStringFree( &szBindingString );
  217. if(status != RPC_S_OK)
  218. {
  219. #ifdef PRIVATEDEBUG
  220. wprintf(L"RpcBindingFromStringBinding failed 0x%x\n",status);
  221. #endif
  222. return NULL;
  223. }
  224. status = RpcMgmtSetComTimeout(hBinding,RPC_C_BINDING_MIN_TIMEOUT);
  225. if (status != RPC_S_OK)
  226. {
  227. #ifdef PRIVATEDEBUG
  228. wprintf(L"RpcMgmtSetComTimeout failed 0x%x\n",status);
  229. #endif
  230. return NULL;
  231. }
  232. BOOL fRetry = TRUE;
  233. //
  234. // Find the principle name
  235. //
  236. status = RpcMgmtInqServerPrincName(hBinding,
  237. RPC_C_AUTHN_GSS_NEGOTIATE,
  238. &pszServerPrincipalName);
  239. if(status == RPC_S_OK)
  240. {
  241. status=RpcBindingSetAuthInfo(hBinding,
  242. pszServerPrincipalName,
  243. dwAuthLevel,
  244. RPC_C_AUTHN_GSS_NEGOTIATE,
  245. g_pRpcIdentity,
  246. 0);
  247. RpcStringFree(&pszServerPrincipalName);
  248. }
  249. else
  250. goto Label;
  251. if(status == RPC_S_OK)
  252. {
  253. retry:
  254. // Obtain context handle from server
  255. status = TLSConnect( hBinding, &pContext );
  256. if(status != ERROR_SUCCESS)
  257. {
  258. pContext = NULL;
  259. if( status == RPC_S_UNKNOWN_AUTHN_SERVICE || status == ERROR_ACCESS_DENIED && fRetry)
  260. {
  261. Label:
  262. fRetry = FALSE;
  263. //Try again with no security set
  264. status = RpcBindingSetAuthInfo(hBinding,
  265. 0,
  266. dwAuthLevel,
  267. RPC_C_AUTHN_WINNT,
  268. g_pRpcIdentity,
  269. 0);
  270. if(status == RPC_S_OK)
  271. {
  272. // Obtain context handle from server
  273. status = TLSConnect( hBinding, &pContext );
  274. }
  275. }
  276. if((status == RPC_S_CALL_FAILED) || (status == RPC_S_CALL_FAILED_DNE))
  277. {
  278. //
  279. // Workaround for an RPC problem where the first RPC after
  280. // the LS starts, fails
  281. //
  282. if (dwNumRetries > 0)
  283. {
  284. dwNumRetries--;
  285. goto retry;
  286. }
  287. }
  288. }
  289. }
  290. //
  291. // Memory leak
  292. //
  293. if(hBinding != NULL)
  294. {
  295. RpcBindingFree(&hBinding);
  296. }
  297. SetLastError((status == RPC_S_OK) ? ERROR_SUCCESS : status);
  298. return pContext;
  299. }
  300. //+------------------------------------------------------------------------
  301. // Function: BindAnyServer()
  302. //
  303. // Description:
  304. //
  305. // Call back routine for TLSConnectToAnyLsServer()
  306. //
  307. // Arguments:
  308. //
  309. // See EnumerateTlsServer()
  310. //
  311. // Return Value:
  312. //
  313. // Always TRUE to terminate server enumeration
  314. //-------------------------------------------------------------------------
  315. static BOOL
  316. BindAnyServer(
  317. TLS_HANDLE hRpcBinding,
  318. LPCTSTR pszServerName,
  319. HANDLE dwUserData
  320. )
  321. /*++
  322. ++*/
  323. {
  324. PLS_ENUM_PARAM pParam = (PLS_ENUM_PARAM) dwUserData;
  325. TLS_HANDLE* hBinding = pParam->hBinding;
  326. RPC_STATUS rpcStatus;
  327. HKEY hKey = NULL;
  328. DWORD dwBuffer = 0;
  329. DWORD cbBuffer = sizeof (DWORD);
  330. DWORD dwErrCode = 0;
  331. // Skip Windows 2000 License servers
  332. if (hRpcBinding != NULL)
  333. {
  334. DWORD dwSupportFlags = 0;
  335. dwErrCode = TLSGetSupportFlags(
  336. hRpcBinding,
  337. &dwSupportFlags
  338. );
  339. if ((dwErrCode == RPC_S_OK) && !(dwSupportFlags & SUPPORT_WHISTLER_CAL))
  340. {
  341. return FALSE;
  342. }
  343. // If the call fails => Windows 2000 LS
  344. else if(dwErrCode != RPC_S_OK)
  345. {
  346. return FALSE;
  347. }
  348. *hBinding=hRpcBinding;
  349. return TRUE;
  350. }
  351. if (pParam->dwTimeout != INFINITE)
  352. {
  353. LARGE_INTEGER timeDiff;
  354. LARGE_INTEGER timeFreq;
  355. *hBinding=hRpcBinding;
  356. QueryPerformanceCounter(&timeDiff);
  357. timeDiff.QuadPart -= pParam->timeInitial.QuadPart;
  358. timeDiff.QuadPart *= 1000; // Adjust to milliseconds, shouldn't overflow
  359. (void)QueryPerformanceFrequency(&timeFreq);
  360. if (((ULONG)(timeDiff.QuadPart / timeFreq.QuadPart)) > pParam->dwTimeout)
  361. {
  362. #ifdef PRIVATEDEBUG
  363. wprintf(L"BindAnyServer timed out\n");
  364. #endif
  365. return TRUE;
  366. }
  367. }
  368. return FALSE;
  369. }
  370. void
  371. RandomizeArray(LPWSTR *rgwszServers, DWORD cServers)
  372. {
  373. DWORD i;
  374. LPWSTR wszServerTmp;
  375. int val;
  376. if (cServers < 2)
  377. return;
  378. srand(GetTickCount());
  379. for (i = 0; i < cServers; i++)
  380. {
  381. val = rand() % (cServers - i);
  382. if (val == 0)
  383. continue;
  384. //
  385. // Swap # i with # (val+i)
  386. //
  387. wszServerTmp = rgwszServers[i];
  388. rgwszServers[i] = rgwszServers[val+i];
  389. rgwszServers[val+i] = wszServerTmp;
  390. }
  391. }
  392. HRESULT
  393. GetLicenseServersFromReg(LPWSTR wszRegKey, LPWSTR *ppwszServerNames,DWORD *pcServers, LPWSTR **prgwszServers)
  394. {
  395. HRESULT hr = S_OK;
  396. HKEY hKey = NULL;
  397. DWORD dwType;
  398. DWORD cbData = 0;
  399. LPWSTR szServers=NULL, pchServer;
  400. DWORD dwErr;
  401. DWORD i,val;
  402. DWORD iLocalComputer = (DWORD)(-1);
  403. WCHAR szLocalComputerName[MAXCOMPUTERNAMELENGTH+1] = L"";
  404. DWORD cbLocalComputerName=MAXCOMPUTERNAMELENGTH+1;
  405. *ppwszServerNames = NULL;
  406. *prgwszServers = NULL;
  407. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  408. TEXT(LSERVER_DISCOVERY_PARAMETER_KEY),
  409. 0,
  410. KEY_READ,
  411. &hKey);
  412. if (dwErr != ERROR_SUCCESS)
  413. {
  414. hr = HRESULT_FROM_WIN32(dwErr);
  415. goto CleanErr;
  416. }
  417. dwErr = RegQueryValueEx(hKey,
  418. wszRegKey,
  419. NULL,
  420. &dwType,
  421. NULL,
  422. &cbData);
  423. if (dwErr != ERROR_SUCCESS)
  424. {
  425. hr = HRESULT_FROM_WIN32(dwErr);
  426. goto CleanErr;
  427. }
  428. if ((dwType != REG_MULTI_SZ) || (cbData < (2 * sizeof(WCHAR))))
  429. {
  430. hr = E_FAIL;
  431. goto CleanErr;
  432. }
  433. szServers = (LPWSTR) LocalAlloc(LPTR,cbData);
  434. if (NULL == szServers)
  435. {
  436. hr = E_OUTOFMEMORY;
  437. goto CleanErr;
  438. }
  439. dwErr = RegQueryValueEx(hKey,
  440. wszRegKey,
  441. NULL,
  442. &dwType,
  443. (PBYTE)szServers,
  444. &cbData);
  445. if (dwErr != ERROR_SUCCESS)
  446. {
  447. hr = HRESULT_FROM_WIN32(dwErr);
  448. goto CleanErr;
  449. }
  450. for (i = 0, pchServer = szServers; (pchServer != NULL) && (*pchServer != L'\0'); pchServer = wcschr(pchServer,L'\0')+1, i++)
  451. ;
  452. if (i == 0)
  453. {
  454. hr = E_FAIL;
  455. goto CleanErr;
  456. }
  457. *pcServers = i;
  458. *prgwszServers = (LPWSTR *)LocalAlloc(LPTR,sizeof(LPWSTR) * (*pcServers));
  459. if (*prgwszServers == NULL)
  460. {
  461. hr = E_OUTOFMEMORY;
  462. goto CleanErr;
  463. }
  464. // Don't treat error from this function as fatal
  465. GetComputerName(szLocalComputerName, &cbLocalComputerName);
  466. for (i = 0, pchServer = szServers; (i < (*pcServers)) && (pchServer != NULL) && (*pchServer != L'\0'); pchServer = wcschr(pchServer,L'\0')+1, i++) {
  467. (*prgwszServers)[i] = pchServer;
  468. if ((iLocalComputer == (DWORD)(-1)) && (wcscmp(pchServer,szLocalComputerName) == 0))
  469. {
  470. iLocalComputer = i;
  471. }
  472. }
  473. //
  474. // Put local computer at head of list
  475. //
  476. if (iLocalComputer != (DWORD)(-1))
  477. {
  478. if (iLocalComputer != 0)
  479. {
  480. //
  481. // Swap # iLocalComputer with # 0
  482. //
  483. pchServer = (*prgwszServers)[iLocalComputer];
  484. (*prgwszServers)[iLocalComputer] = (*prgwszServers)[0];
  485. (*prgwszServers)[0] = pchServer;
  486. }
  487. RandomizeArray((*prgwszServers)+1,(*pcServers) - 1);
  488. }
  489. else
  490. {
  491. RandomizeArray((*prgwszServers),*pcServers);
  492. }
  493. *ppwszServerNames = szServers;
  494. CleanErr:
  495. if (FAILED(hr))
  496. {
  497. if (NULL != szServers)
  498. {
  499. LocalFree(szServers);
  500. }
  501. if (NULL != *prgwszServers)
  502. {
  503. LocalFree(*prgwszServers);
  504. }
  505. }
  506. if (hKey != NULL)
  507. {
  508. RegCloseKey(hKey);
  509. }
  510. return hr;
  511. }
  512. HRESULT
  513. WriteLicenseServersToReg(LPWSTR wszRegKey, LPWSTR pwszServerNames,DWORD cchServers)
  514. {
  515. HRESULT hr = S_OK;
  516. HKEY hKey = NULL;
  517. DWORD dwType = REG_MULTI_SZ;
  518. DWORD dwErr;
  519. DWORD dwDisp;
  520. //
  521. // Delete the value
  522. //
  523. dwErr = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  524. TEXT(LSERVER_DISCOVERY_PARAMETER_KEY),
  525. 0,
  526. KEY_WRITE,
  527. &hKey);
  528. if (dwErr == ERROR_SUCCESS)
  529. {
  530. RegDeleteValue(hKey,wszRegKey);
  531. }
  532. if ((pwszServerNames == NULL) || (cchServers < 2))
  533. {
  534. hr = S_OK;
  535. goto CleanErr;
  536. }
  537. if(hKey != NULL)
  538. {
  539. RegCloseKey(hKey);
  540. hKey = NULL;
  541. }
  542. dwErr = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  543. TEXT(LSERVER_DISCOVERY_PARAMETER_KEY),
  544. 0,
  545. TEXT(""),
  546. REG_OPTION_NON_VOLATILE,
  547. KEY_WRITE,
  548. NULL,
  549. &hKey,
  550. &dwDisp);
  551. if (dwErr != ERROR_SUCCESS)
  552. {
  553. hr = HRESULT_FROM_WIN32(dwErr);
  554. goto CleanErr;
  555. }
  556. dwErr = RegSetValueEx(hKey,
  557. wszRegKey,
  558. 0,
  559. dwType,
  560. (CONST BYTE *)pwszServerNames,
  561. cchServers*sizeof(WCHAR));
  562. if (dwErr != ERROR_SUCCESS)
  563. {
  564. hr = HRESULT_FROM_WIN32(dwErr);
  565. goto CleanErr;
  566. }
  567. CleanErr:
  568. if (hKey != NULL)
  569. {
  570. RegCloseKey(hKey);
  571. }
  572. return hr;
  573. }
  574. //
  575. // Free pszDomain using NetApiBufferFree
  576. //
  577. DWORD WINAPI
  578. TLSInDomain(BOOL *pfInDomain, LPWSTR *pszDomain)
  579. {
  580. NET_API_STATUS dwErr;
  581. DSROLE_PRIMARY_DOMAIN_INFO_BASIC *pDomainInfo = NULL;
  582. PDOMAIN_CONTROLLER_INFO pdcInfo = NULL;
  583. if (pfInDomain == NULL)
  584. {
  585. return ERROR_INVALID_PARAMETER;
  586. }
  587. *pfInDomain = FALSE;
  588. //
  589. // Check if we're in a workgroup
  590. //
  591. dwErr = DsRoleGetPrimaryDomainInformation(NULL,
  592. DsRolePrimaryDomainInfoBasic,
  593. (PBYTE *) &pDomainInfo);
  594. if ((dwErr != NO_ERROR) || (pDomainInfo == NULL))
  595. {
  596. return dwErr;
  597. }
  598. switch (pDomainInfo->MachineRole)
  599. {
  600. case DsRole_RoleStandaloneWorkstation:
  601. case DsRole_RoleStandaloneServer:
  602. DsRoleFreeMemory(pDomainInfo);
  603. if (NULL != pszDomain)
  604. {
  605. NETSETUP_JOIN_STATUS BufferType;
  606. dwErr = NetGetJoinInformation(NULL,pszDomain,&BufferType);
  607. }
  608. return dwErr;
  609. break; // just in case
  610. }
  611. DsRoleFreeMemory(pDomainInfo);
  612. dwErr = DsGetDcName(NULL, // Computer Name
  613. NULL, // Domain Name
  614. NULL, // Domain GUID
  615. NULL, // Site Name
  616. DS_DIRECTORY_SERVICE_PREFERRED,
  617. &pdcInfo);
  618. if ((dwErr != NO_ERROR) || (pdcInfo == NULL))
  619. {
  620. if (dwErr == ERROR_NO_SUCH_DOMAIN)
  621. {
  622. *pfInDomain = FALSE;
  623. return NO_ERROR;
  624. }
  625. else
  626. {
  627. if (pdcInfo == NULL)
  628. dwErr = ERROR_INTERNAL_ERROR;
  629. return dwErr;
  630. }
  631. }
  632. if (pdcInfo->Flags & DS_DS_FLAG)
  633. {
  634. *pfInDomain = TRUE;
  635. }
  636. if (pszDomain != NULL)
  637. {
  638. dwErr = NetApiBufferAllocate((wcslen(pdcInfo->DomainName)+1) * sizeof(WCHAR),
  639. (LPVOID *)pszDomain);
  640. if ((NERR_Success == dwErr) && (NULL != *pszDomain))
  641. {
  642. wcscpy(*pszDomain,pdcInfo->DomainName);
  643. }
  644. }
  645. if (pdcInfo != NULL)
  646. NetApiBufferFree(pdcInfo);
  647. return dwErr;
  648. }
  649. /*++
  650. Function:
  651. LicenseServerCachingThread
  652. Description:
  653. This is the thread that does the license server caching.
  654. Arguments:
  655. lpParam - contains the exit event handle
  656. Returns:
  657. Always 1
  658. --*/
  659. DWORD WINAPI
  660. LicenseServerCachingThread(
  661. LPVOID lpParam )
  662. {
  663. DWORD
  664. dwWaitStatus;
  665. HANDLE
  666. hExit = (HANDLE)lpParam;
  667. DWORD
  668. dwDiscoveryInterval = DISCOVERY_INTERVAL;
  669. HANDLE
  670. rgWaitHandles[] = {hExit,g_hImmediateDiscovery,g_hDiscoverySoon};
  671. BOOL
  672. bFoundServer;
  673. BOOL
  674. bSkipOne = FALSE;
  675. HANDLE
  676. hEvent;
  677. //
  678. // Yield our time slice to other threads now, so that the terminal server
  679. // service can start up quickly. Refresh the license server cache when we
  680. // resume our time slice.
  681. //
  682. Sleep( 0 );
  683. while (1)
  684. {
  685. if (!bSkipOne)
  686. {
  687. bFoundServer = TLSRefreshLicenseServerCache(INFINITE);
  688. if ((!g_fOffSiteLicenseServer) && bFoundServer)
  689. {
  690. dwDiscoveryInterval = INFINITE;
  691. }
  692. }
  693. else
  694. {
  695. bSkipOne = FALSE;
  696. }
  697. dwWaitStatus = WaitForMultipleObjects(
  698. sizeof(rgWaitHandles) / sizeof(HANDLE),
  699. rgWaitHandles,
  700. FALSE, // wait for any one event
  701. dwDiscoveryInterval);
  702. if (WAIT_OBJECT_0 == dwWaitStatus)
  703. {
  704. // hExit was signalled
  705. goto done;
  706. }
  707. if ((WAIT_OBJECT_0+1) == dwWaitStatus)
  708. {
  709. // g_hImmediateDiscovery was signalled
  710. // reduce dwDiscoveryInterval
  711. dwDiscoveryInterval = DISCOVERY_INTERVAL;
  712. }
  713. if ((WAIT_OBJECT_0+2) == dwWaitStatus)
  714. {
  715. // g_hDiscoverySoon was signalled
  716. // reduce dwDiscoveryInterval, but wait one round
  717. dwDiscoveryInterval = DISCOVERY_INTERVAL;
  718. bSkipOne = TRUE;
  719. }
  720. // we timed out, or hImmediateDiscovery was signalled. Re-start
  721. // discovery
  722. }
  723. done:
  724. hEvent = g_hCachingThreadExit;
  725. g_hCachingThreadExit = NULL;
  726. CloseHandle(hEvent);
  727. hEvent = g_hImmediateDiscovery;
  728. g_hImmediateDiscovery = NULL;
  729. CloseHandle(hEvent);
  730. hEvent = g_hDiscoverySoon;
  731. g_hDiscoverySoon = NULL;
  732. CloseHandle(hEvent);
  733. return 1;
  734. }
  735. extern "C" void
  736. TLSShutdown()
  737. {
  738. if (0 < InterlockedDecrement(&lLibUsage))
  739. {
  740. //
  741. // Someone else is using it
  742. //
  743. return;
  744. }
  745. TLSStopDiscovery();
  746. if (NULL != g_pRpcIdentity)
  747. {
  748. PSEC_WINNT_AUTH_IDENTITY pRpcIdentity = g_pRpcIdentity;
  749. g_pRpcIdentity = NULL;
  750. if (NULL != pRpcIdentity->User)
  751. {
  752. LocalFree(pRpcIdentity->User);
  753. }
  754. LocalFree(pRpcIdentity);
  755. }
  756. //
  757. // Cleanup random number generator
  758. //
  759. TSRNG_Shutdown();
  760. LsCsp_Exit();
  761. }
  762. extern "C" DWORD WINAPI
  763. TLSInit()
  764. {
  765. LICENSE_STATUS status;
  766. BOOL fInDomain = FALSE;
  767. if (0 != InterlockedExchangeAdd(&lLibUsage,1))
  768. {
  769. //
  770. // Already been initialized
  771. //
  772. return ERROR_SUCCESS;
  773. }
  774. status = LsCsp_Initialize();
  775. if (LICENSE_STATUS_OK != status)
  776. {
  777. InterlockedDecrement(&lLibUsage);
  778. switch (status)
  779. {
  780. case LICENSE_STATUS_OUT_OF_MEMORY:
  781. return ERROR_NOT_ENOUGH_MEMORY;
  782. case LICENSE_STATUS_NO_CERTIFICATE:
  783. return SCARD_E_CERTIFICATE_UNAVAILABLE;
  784. case LICENSE_STATUS_INVALID_CERTIFICATE:
  785. return CERT_E_MALFORMED;
  786. default:
  787. return E_FAIL;
  788. }
  789. }
  790. if ((NO_ERROR == TLSInDomain(&fInDomain, NULL))
  791. && (fInDomain)
  792. && (IsSystemService()))
  793. {
  794. //
  795. // We're running as SYSTEM
  796. // Create an RPC identity for use as an RPC client
  797. //
  798. g_pRpcIdentity = (PSEC_WINNT_AUTH_IDENTITY) LocalAlloc(LPTR, sizeof(SEC_WINNT_AUTH_IDENTITY));
  799. if (NULL != g_pRpcIdentity)
  800. {
  801. g_pRpcIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  802. g_pRpcIdentity->UserLength = MAX_COMPUTERNAME_LENGTH + 2;
  803. g_pRpcIdentity->User = (WCHAR *) LocalAlloc(LPTR, g_pRpcIdentity->UserLength * sizeof(WCHAR));
  804. if (NULL != g_pRpcIdentity->User)
  805. {
  806. if (GetComputerNameEx(ComputerNamePhysicalNetBIOS,g_pRpcIdentity->User,&(g_pRpcIdentity->UserLength)))
  807. {
  808. if (g_pRpcIdentity->UserLength < MAX_COMPUTERNAME_LENGTH + 1)
  809. {
  810. g_pRpcIdentity->User[g_pRpcIdentity->UserLength++] = L'$';
  811. g_pRpcIdentity->User[g_pRpcIdentity->UserLength] = 0;
  812. }
  813. else
  814. {
  815. LocalFree(g_pRpcIdentity->User);
  816. LocalFree(g_pRpcIdentity);
  817. g_pRpcIdentity = NULL;
  818. InterlockedDecrement(&lLibUsage);
  819. return E_FAIL;
  820. }
  821. }
  822. else
  823. {
  824. LocalFree(g_pRpcIdentity->User);
  825. LocalFree(g_pRpcIdentity);
  826. g_pRpcIdentity = NULL;
  827. InterlockedDecrement(&lLibUsage);
  828. return GetLastError();
  829. }
  830. }
  831. else
  832. {
  833. LocalFree(g_pRpcIdentity);
  834. g_pRpcIdentity = NULL;
  835. InterlockedDecrement(&lLibUsage);
  836. return ERROR_NOT_ENOUGH_MEMORY;
  837. }
  838. }
  839. else
  840. {
  841. InterlockedDecrement(&lLibUsage);
  842. return ERROR_NOT_ENOUGH_MEMORY;
  843. }
  844. }
  845. //
  846. // Init random number generator
  847. //
  848. TSRNG_Initialize();
  849. return ERROR_SUCCESS;
  850. }
  851. extern "C" DWORD WINAPI
  852. TLSStartDiscovery()
  853. {
  854. HANDLE hCachingThread = NULL;
  855. HANDLE hEvent;
  856. if (NULL != g_hCachingThreadExit)
  857. {
  858. // already started
  859. return ERROR_SUCCESS;
  860. }
  861. //
  862. // Create the event to signal thread exit
  863. //
  864. g_hCachingThreadExit = CreateEvent( NULL, FALSE, FALSE, NULL );
  865. if( NULL == g_hCachingThreadExit )
  866. {
  867. return GetLastError();
  868. }
  869. g_hImmediateDiscovery = CreateEvent(NULL,FALSE,FALSE,NULL);
  870. if (NULL == g_hImmediateDiscovery)
  871. {
  872. hEvent = g_hCachingThreadExit;
  873. g_hCachingThreadExit = NULL;
  874. CloseHandle(hEvent);
  875. return GetLastError();
  876. }
  877. g_hDiscoverySoon = CreateEvent(NULL,FALSE,FALSE,NULL);
  878. if (NULL == g_hDiscoverySoon)
  879. {
  880. hEvent = g_hCachingThreadExit;
  881. g_hCachingThreadExit = NULL;
  882. CloseHandle(hEvent);
  883. hEvent = g_hImmediateDiscovery;
  884. g_hImmediateDiscovery = NULL;
  885. CloseHandle(hEvent);
  886. return GetLastError();
  887. }
  888. //
  889. // Create the caching thread
  890. //
  891. hCachingThread = CreateThread(
  892. NULL,
  893. 0,
  894. LicenseServerCachingThread,
  895. ( LPVOID )g_hCachingThreadExit,
  896. 0,
  897. NULL );
  898. if (hCachingThread == NULL)
  899. {
  900. hEvent = g_hCachingThreadExit;
  901. g_hCachingThreadExit = NULL;
  902. CloseHandle(hEvent);
  903. hEvent = g_hImmediateDiscovery;
  904. g_hImmediateDiscovery = NULL;
  905. CloseHandle(hEvent);
  906. hEvent = g_hDiscoverySoon;
  907. g_hDiscoverySoon = NULL;
  908. CloseHandle(hEvent);
  909. return GetLastError();
  910. }
  911. CloseHandle(hCachingThread);
  912. return ERROR_SUCCESS;
  913. }
  914. extern "C" DWORD WINAPI
  915. TLSStopDiscovery()
  916. {
  917. //
  918. // Signal the thread to exit
  919. //
  920. if (NULL != g_hCachingThreadExit)
  921. {
  922. SetEvent( g_hCachingThreadExit );
  923. }
  924. return ERROR_SUCCESS;
  925. }
  926. //
  927. // Number of DCs to allocate space for at a time
  928. //
  929. #define DC_LIST_CHUNK 10
  930. //+------------------------------------------------------------------------
  931. // Function:
  932. //
  933. // EnumerateLsServer()
  934. //
  935. // Description:
  936. //
  937. // Routine to enumerate all hydra license server in network
  938. //
  939. // Arguments:
  940. //
  941. // szScope - Scope limit, NULL if doen't care.
  942. // dwPlatformType - verify if license server have licenses for this platform,
  943. // LSKEYPACKPLATFORMTYPE_UNKNOWN if doesn't care.
  944. // fCallBack - call back routine when EnumerateServer() founds any server,
  945. // dwUserData - data to be pass to call back routine
  946. //
  947. // Return Value:
  948. //
  949. // RPC_S_OK or any RPC specific error code.
  950. //
  951. // NOTE:
  952. //
  953. // Enumeration terminate when either there is no more server or call back
  954. // routine return TRUE.
  955. //
  956. //-------------------------------------------------------------------------
  957. DWORD WINAPI
  958. EnumerateTlsServerInDomain(
  959. IN LPCTSTR szDomain,
  960. IN TLSENUMERATECALLBACK fCallBack,
  961. IN HANDLE dwUserData,
  962. IN DWORD dwTimeOut,
  963. IN BOOL fRegOnly,
  964. IN OUT BOOL *pfOffSite
  965. )
  966. /*++
  967. ++*/
  968. {
  969. DWORD entriesread = 0;
  970. BOOL bCancel=FALSE;
  971. DWORD dwErrCode;
  972. LPWSTR pwszServerTmp = NULL;
  973. LPWSTR pwszServer = NULL;
  974. HRESULT hr;
  975. LPWSTR pwszServers = NULL;
  976. LPWSTR pwszServersTmp = NULL;
  977. DWORD cchServers = 0;
  978. DWORD cchServer;
  979. LPWSTR *rgwszServers = NULL;
  980. LPWSTR *rgwszServersTmp;
  981. LPWSTR pwszServerNames = NULL;
  982. DWORD dwErr = ERROR_SUCCESS, i;
  983. HANDLE hDcOpen = NULL;
  984. LPWSTR szSiteName = NULL;
  985. BOOL fOffSiteIn;
  986. BOOL fFoundOne = FALSE;
  987. BOOL fFoundOneOffSite = FALSE;
  988. DWORD cChunks = 0;
  989. DWORD cServersOnSite = 0;
  990. if (fRegOnly)
  991. {
  992. //
  993. // check for a license server in the registry
  994. //
  995. hr = GetLicenseServersFromReg(REG_DOMAIN_SERVER_MULTI,&pwszServerNames,&entriesread,&rgwszServers);
  996. if (FAILED(hr))
  997. {
  998. dwErr = hr;
  999. goto Cleanup;
  1000. }
  1001. }
  1002. else
  1003. {
  1004. if (NULL == pfOffSite)
  1005. {
  1006. return ERROR_INVALID_PARAMETER;
  1007. }
  1008. fOffSiteIn = *pfOffSite;
  1009. *pfOffSite = FALSE;
  1010. dwErr = DsGetSiteName(NULL,&szSiteName);
  1011. if(dwErr != ERROR_SUCCESS)
  1012. {
  1013. #ifdef PRIVATEDEBUG
  1014. wprintf(L"DsGetSiteName failed %x\n",dwErr);
  1015. #endif
  1016. goto Cleanup;
  1017. }
  1018. dwErr = DsGetDcOpenW(szDomain,
  1019. fOffSiteIn ? DS_NOTIFY_AFTER_SITE_RECORDS: DS_ONLY_DO_SITE_NAME,
  1020. szSiteName,
  1021. NULL, // DomainGuid
  1022. NULL, // DnsForestName
  1023. 0, // Flags
  1024. &hDcOpen
  1025. );
  1026. if(dwErr != ERROR_SUCCESS)
  1027. {
  1028. #ifdef PRIVATEDEBUG
  1029. wprintf(L"DsGetDcOpen failed %x\n",dwErr);
  1030. #endif
  1031. goto Cleanup;
  1032. }
  1033. rgwszServers = (LPWSTR *) LocalAlloc(LPTR,
  1034. DC_LIST_CHUNK * sizeof(LPWSTR));
  1035. if (NULL == rgwszServers)
  1036. {
  1037. #ifdef PRIVATEDEBUG
  1038. wprintf(L"Out of memory\n");
  1039. #endif
  1040. dwErr = E_OUTOFMEMORY;
  1041. goto Cleanup;
  1042. }
  1043. cChunks = 1;
  1044. //
  1045. // Read the whole DC list
  1046. //
  1047. do
  1048. {
  1049. if (entriesread >= (cChunks * DC_LIST_CHUNK))
  1050. {
  1051. cChunks++;
  1052. rgwszServersTmp = (LPWSTR *)
  1053. LocalReAlloc(rgwszServers,
  1054. DC_LIST_CHUNK * sizeof(LPWSTR) * cChunks,
  1055. LHND);
  1056. if (NULL == rgwszServersTmp)
  1057. {
  1058. dwErr = E_OUTOFMEMORY;
  1059. goto Cleanup;
  1060. }
  1061. else
  1062. {
  1063. rgwszServers = rgwszServersTmp;
  1064. }
  1065. }
  1066. dwErr = DsGetDcNextW(hDcOpen,
  1067. NULL,
  1068. NULL,
  1069. rgwszServers+entriesread);
  1070. if (ERROR_FILEMARK_DETECTED == dwErr)
  1071. {
  1072. // Now going off-site; use NULL ptr marker
  1073. rgwszServers[entriesread] = NULL;
  1074. cServersOnSite = entriesread;
  1075. dwErr = ERROR_SUCCESS;
  1076. fFoundOneOffSite = TRUE;
  1077. }
  1078. entriesread++;
  1079. } while (ERROR_SUCCESS == dwErr);
  1080. // don't count the final error
  1081. entriesread--;
  1082. if (!fFoundOneOffSite)
  1083. cServersOnSite = entriesread;
  1084. // Now randomize the two portions of the array
  1085. RandomizeArray(rgwszServers,cServersOnSite);
  1086. if (fFoundOneOffSite)
  1087. {
  1088. RandomizeArray(rgwszServers+cServersOnSite+1,
  1089. entriesread - cServersOnSite - 1);
  1090. }
  1091. // Now allocate memory for registry entry
  1092. pwszServers = (LPWSTR) LocalAlloc(LPTR,2*sizeof(WCHAR));
  1093. if (NULL == pwszServers)
  1094. {
  1095. #ifdef PRIVATEDEBUG
  1096. wprintf(L"Out of memory\n");
  1097. #endif
  1098. dwErr = E_OUTOFMEMORY;
  1099. goto Cleanup;
  1100. }
  1101. cchServers = 2;
  1102. pwszServers[0] = pwszServers[1] = L'\0';
  1103. }
  1104. for(i=0; bCancel == FALSE; i++)
  1105. {
  1106. PCONTEXT_HANDLE pContext=NULL;
  1107. RPC_STATUS rpcStatus;
  1108. if (!fRegOnly)
  1109. {
  1110. if (fFoundOneOffSite && i == cServersOnSite)
  1111. {
  1112. if (fFoundOne)
  1113. break;
  1114. // Now going off-site
  1115. i++;
  1116. *pfOffSite = TRUE;
  1117. }
  1118. }
  1119. if (i >= entriesread)
  1120. break;
  1121. pwszServerTmp = rgwszServers[i];
  1122. bCancel=fCallBack(pContext, pwszServerTmp, dwUserData);
  1123. if(bCancel == TRUE)
  1124. continue;
  1125. if(!(pContext = TLSConnectToLsServer(pwszServerTmp)))
  1126. {
  1127. //
  1128. // could be access denied.
  1129. //
  1130. #ifdef PRIVATEDEBUG
  1131. wprintf(L"Can't connect to %s\n",pwszServerTmp);
  1132. #endif
  1133. continue;
  1134. }
  1135. #ifdef PRIVATEDEBUG
  1136. wprintf(L"!!!Connected to %s\n",pwszServerTmp);
  1137. #endif
  1138. do {
  1139. //
  1140. // Skip enterprise server
  1141. //
  1142. DWORD dwVersion;
  1143. rpcStatus = TLSGetVersion( pContext, &dwVersion );
  1144. if(rpcStatus != RPC_S_OK)
  1145. {
  1146. break;
  1147. }
  1148. #if ENFORCE_LICENSING
  1149. //
  1150. // W2K Beta 3 to RC1 upgrade, don't connect to any non-enforce
  1151. // server 5.2 or older
  1152. //
  1153. if(IS_ENFORCE_LSSERVER(dwVersion) == FALSE)
  1154. {
  1155. if( GET_LSSERVER_MAJOR_VERSION(dwVersion) <= 5 &&
  1156. GET_LSSERVER_MINOR_VERSION(dwVersion) <= 2 )
  1157. {
  1158. continue;
  1159. }
  1160. }
  1161. //
  1162. // Prevent beta <-> RTM server talking to each other
  1163. //
  1164. //
  1165. // TLSIsBetaNTServer() returns TRUE if eval NT
  1166. // IS_LSSERVER_RTM() returns TRUE if LS is an RTM.
  1167. //
  1168. if( TLSIsBetaNTServer() == IS_LSSERVER_RTM(dwVersion) )
  1169. {
  1170. continue;
  1171. }
  1172. #endif
  1173. if(dwVersion & TLS_VERSION_ENTERPRISE_BIT)
  1174. {
  1175. continue;
  1176. }
  1177. bCancel=fCallBack(pContext, pwszServerTmp, dwUserData);
  1178. if (!fRegOnly)
  1179. {
  1180. //
  1181. // Add to list of servers
  1182. //
  1183. cchServer = wcslen(pwszServerTmp);
  1184. pwszServersTmp = (LPWSTR) LocalReAlloc(pwszServers,(cchServers+cchServer+1)*sizeof(TCHAR),LHND);
  1185. if (NULL == pwszServersTmp)
  1186. {
  1187. break;
  1188. }
  1189. pwszServers = pwszServersTmp;
  1190. if (cchServers == 2)
  1191. {
  1192. wcscpy(pwszServers,pwszServerTmp);
  1193. cchServers += cchServer;
  1194. } else
  1195. {
  1196. wcscpy(pwszServers+cchServers-1,pwszServerTmp);
  1197. cchServers += cchServer + 1;
  1198. }
  1199. pwszServers[cchServers-1] = L'\0';
  1200. }
  1201. fFoundOne = TRUE;
  1202. } while (FALSE);
  1203. if(bCancel == FALSE && pContext != NULL)
  1204. {
  1205. TLSDisconnect(&pContext);
  1206. }
  1207. } // for loop
  1208. if (!fRegOnly)
  1209. {
  1210. WriteLicenseServersToReg(REG_DOMAIN_SERVER_MULTI,pwszServers,cchServers);
  1211. }
  1212. Cleanup:
  1213. if (NULL != hDcOpen)
  1214. DsGetDcCloseW(hDcOpen);
  1215. if (NULL != rgwszServers)
  1216. {
  1217. if (!fRegOnly)
  1218. {
  1219. for (i = 0; i < entriesread; i++)
  1220. {
  1221. if (NULL != rgwszServers[i])
  1222. {
  1223. NetApiBufferFree(rgwszServers[i]);
  1224. }
  1225. }
  1226. }
  1227. LocalFree(rgwszServers);
  1228. }
  1229. if (szSiteName)
  1230. NetApiBufferFree(szSiteName);
  1231. if (pwszServerNames)
  1232. LocalFree(pwszServerNames);
  1233. if (pwszServers)
  1234. LocalFree(pwszServers);
  1235. if (pwszServer)
  1236. LocalFree(pwszServer);
  1237. return dwErr;
  1238. }
  1239. DWORD WINAPI
  1240. EnumerateTlsServerInWorkGroup(
  1241. IN TLSENUMERATECALLBACK pfCallBack,
  1242. IN HANDLE dwUserData,
  1243. IN DWORD dwTimeOut,
  1244. IN BOOL fRegOnly
  1245. )
  1246. /*++
  1247. ++*/
  1248. {
  1249. DWORD dwStatus=ERROR_SUCCESS;
  1250. TCHAR szServerMailSlotName[MAX_PATH+1];
  1251. TCHAR szLocalMailSlotName[MAX_PATH+1];
  1252. HANDLE hClientSlot = INVALID_HANDLE_VALUE;
  1253. HANDLE hServerSlot = INVALID_HANDLE_VALUE;
  1254. TCHAR szDiscMsg[MAX_MAILSLOT_MSG_SIZE+1];
  1255. TCHAR szComputerName[MAXCOMPUTERNAMELENGTH+1];
  1256. TCHAR szRandomMailSlotName[MAXCOMPUTERNAMELENGTH+1];
  1257. DWORD cbComputerName=MAXCOMPUTERNAMELENGTH+1;
  1258. DWORD cbWritten=0;
  1259. DWORD cbRead=0;
  1260. BOOL bCancel = FALSE;
  1261. DWORD dwErrCode;
  1262. HRESULT hr;
  1263. LPWSTR pwszServers = NULL;
  1264. LPWSTR pwszServersTmp = NULL;
  1265. DWORD cchServers = 0;
  1266. DWORD cchServer;
  1267. LPWSTR *rgwszServers = NULL;
  1268. LPWSTR pwszServerNames = NULL;
  1269. DWORD cServers = 0;
  1270. DWORD i = 0;
  1271. LPWSTR pwszServerTmp = szComputerName;
  1272. if (!fRegOnly)
  1273. {
  1274. if(!GetComputerName(szComputerName, &cbComputerName))
  1275. {
  1276. dwStatus = GetLastError();
  1277. goto cleanup;
  1278. }
  1279. if (0 == (1 & GetSystemMetrics(SM_NETWORK)))
  1280. {
  1281. // No network; try local machine
  1282. #ifdef PRIVATEDEBUG
  1283. wprintf(L"No network, trying local computer=%s\n",szComputerName);
  1284. #endif
  1285. dwStatus = ERROR_SUCCESS;
  1286. goto TryServer;
  1287. }
  1288. wsprintf(
  1289. szRandomMailSlotName,
  1290. _TEXT("%08x"),
  1291. GetCurrentThreadId()
  1292. );
  1293. _stprintf(
  1294. szLocalMailSlotName,
  1295. _TEXT("\\\\.\\mailslot\\%s"),
  1296. szRandomMailSlotName
  1297. );
  1298. //
  1299. // Create local mail slot for server's response
  1300. //
  1301. hClientSlot=CreateMailslot(
  1302. szLocalMailSlotName,
  1303. 0,
  1304. (dwTimeOut == MAILSLOT_WAIT_FOREVER) ? 5 * 1000: dwTimeOut,
  1305. NULL
  1306. );
  1307. if(hClientSlot == INVALID_HANDLE_VALUE)
  1308. {
  1309. dwStatus = GetLastError();
  1310. goto cleanup;
  1311. }
  1312. //
  1313. // Open server's mail slot
  1314. //
  1315. _stprintf(
  1316. szServerMailSlotName,
  1317. _TEXT("\\\\%s\\mailslot\\%s"),
  1318. _TEXT("*"),
  1319. _TEXT(SERVERMAILSLOTNAME)
  1320. );
  1321. hServerSlot=CreateFile(
  1322. szServerMailSlotName,
  1323. GENERIC_WRITE, // only need write
  1324. FILE_SHARE_READ,
  1325. NULL,
  1326. OPEN_EXISTING,
  1327. FILE_ATTRIBUTE_NORMAL,
  1328. NULL
  1329. );
  1330. if(hServerSlot == INVALID_HANDLE_VALUE)
  1331. {
  1332. dwStatus = GetLastError();
  1333. goto cleanup;
  1334. }
  1335. //
  1336. // Formulate discovery message
  1337. //
  1338. _stprintf(
  1339. szDiscMsg,
  1340. _TEXT("%s %c%s%c %c%s%c"),
  1341. _TEXT(LSERVER_DISCOVERY),
  1342. _TEXT(LSERVER_OPEN_BLK),
  1343. szComputerName,
  1344. _TEXT(LSERVER_CLOSE_BLK),
  1345. _TEXT(LSERVER_OPEN_BLK),
  1346. szRandomMailSlotName,
  1347. _TEXT(LSERVER_CLOSE_BLK)
  1348. );
  1349. if (!WriteFile(hServerSlot, szDiscMsg, (_tcslen(szDiscMsg) + 1) * sizeof(TCHAR), &cbWritten, NULL) ||
  1350. (cbWritten != (_tcslen(szDiscMsg) + 1 ) * sizeof(TCHAR)))
  1351. {
  1352. dwStatus = GetLastError();
  1353. if (dwStatus == ERROR_NETWORK_UNREACHABLE)
  1354. {
  1355. // No network; try local machine
  1356. #ifdef PRIVATEDEBUG
  1357. wprintf(L"No network, trying local computer=%s\n",szComputerName);
  1358. #endif
  1359. dwStatus = ERROR_SUCCESS;
  1360. goto TryServer;
  1361. }
  1362. else
  1363. {
  1364. goto cleanup;
  1365. }
  1366. }
  1367. // Allocate for registry entry
  1368. pwszServers = (LPWSTR) LocalAlloc(LPTR,2*sizeof(WCHAR));
  1369. if (NULL == pwszServers)
  1370. {
  1371. #ifdef PRIVATEDEBUG
  1372. wprintf(L"Out of memory\n");
  1373. #endif
  1374. dwStatus = E_OUTOFMEMORY;
  1375. goto cleanup;
  1376. }
  1377. cchServers = 2;
  1378. pwszServers[0] = pwszServers[1] = L'\0';
  1379. } else
  1380. {
  1381. //
  1382. // check for a license server in the registry
  1383. //
  1384. hr = GetLicenseServersFromReg(REG_DOMAIN_SERVER_MULTI,&pwszServerNames,&cServers,&rgwszServers);
  1385. if (FAILED(hr))
  1386. {
  1387. dwStatus = hr;
  1388. goto cleanup;
  1389. }
  1390. }
  1391. do {
  1392. if(fRegOnly)
  1393. {
  1394. if (i >= cServers)
  1395. {
  1396. break;
  1397. }
  1398. pwszServerTmp = rgwszServers[i++];
  1399. } else
  1400. {
  1401. memset(szComputerName, 0, sizeof(szComputerName));
  1402. if(!ReadFile(hClientSlot, szComputerName, sizeof(szComputerName) - sizeof(TCHAR), &cbRead, NULL))
  1403. {
  1404. dwStatus=GetLastError();
  1405. break;
  1406. }
  1407. #ifdef PRIVATEDEBUG
  1408. wprintf(L"Trying server=%s\n",szComputerName);
  1409. #endif
  1410. }
  1411. TryServer:
  1412. bCancel=pfCallBack(NULL, pwszServerTmp, dwUserData);
  1413. if(bCancel == TRUE)
  1414. {
  1415. continue;
  1416. }
  1417. PCONTEXT_HANDLE pContext=NULL;
  1418. RPC_STATUS rpcStatus;
  1419. if(!(pContext = TLSConnectToLsServer(pwszServerTmp)))
  1420. {
  1421. //
  1422. // could be access denied.
  1423. //
  1424. continue;
  1425. }
  1426. do {
  1427. //
  1428. // Skip enterprise server
  1429. //
  1430. DWORD dwVersion;
  1431. rpcStatus = TLSGetVersion( pContext, &dwVersion );
  1432. if(rpcStatus != RPC_S_OK)
  1433. {
  1434. continue;
  1435. }
  1436. #if ENFORCE_LICENSING
  1437. //
  1438. // W2K Beta 3 to RC1 upgrade, don't connect to any non-enforce
  1439. // server 5.2 or older
  1440. //
  1441. if(IS_ENFORCE_LSSERVER(dwVersion) == FALSE)
  1442. {
  1443. if( GET_LSSERVER_MAJOR_VERSION(dwVersion) <= 5 &&
  1444. GET_LSSERVER_MINOR_VERSION(dwVersion) <= 2 )
  1445. {
  1446. continue;
  1447. }
  1448. }
  1449. //
  1450. // No Beta <--> RTM server.
  1451. //
  1452. //
  1453. // TLSIsBetaNTServer() returns TRUE if eval NT
  1454. // IS_LSSERVER_RTM() returns TRUE if LS is an RTM.
  1455. //
  1456. if( TLSIsBetaNTServer() == IS_LSSERVER_RTM(dwVersion) )
  1457. {
  1458. continue;
  1459. }
  1460. #endif
  1461. if(dwVersion & TLS_VERSION_ENTERPRISE_BIT)
  1462. {
  1463. continue;
  1464. }
  1465. bCancel=pfCallBack(pContext, pwszServerTmp, dwUserData);
  1466. if (!fRegOnly)
  1467. {
  1468. //
  1469. // Add to list of servers
  1470. //
  1471. cchServer = wcslen(pwszServerTmp);
  1472. pwszServersTmp = (LPWSTR) LocalReAlloc(pwszServers,(cchServers+cchServer+1)*sizeof(TCHAR),LHND);
  1473. if (NULL == pwszServersTmp)
  1474. {
  1475. continue;
  1476. }
  1477. pwszServers = pwszServersTmp;
  1478. if (cchServers == 2)
  1479. {
  1480. wcscpy(pwszServers,pwszServerTmp);
  1481. cchServers += cchServer;
  1482. } else
  1483. {
  1484. wcscpy(pwszServers+cchServers-1,pwszServerTmp);
  1485. cchServers += cchServer + 1;
  1486. }
  1487. pwszServers[cchServers-1] = L'\0';
  1488. }
  1489. } while (FALSE);
  1490. if(bCancel == FALSE && pContext != NULL)
  1491. {
  1492. TLSDisconnectFromServer(pContext);
  1493. }
  1494. } while(bCancel == FALSE);
  1495. if (!fRegOnly)
  1496. {
  1497. WriteLicenseServersToReg(REG_DOMAIN_SERVER_MULTI,pwszServers,cchServers);
  1498. }
  1499. cleanup:
  1500. if(hClientSlot != INVALID_HANDLE_VALUE)
  1501. {
  1502. CloseHandle(hClientSlot);
  1503. }
  1504. if(hServerSlot != INVALID_HANDLE_VALUE)
  1505. {
  1506. CloseHandle(hServerSlot);
  1507. }
  1508. if (pwszServerNames)
  1509. LocalFree(pwszServerNames);
  1510. if (pwszServers)
  1511. LocalFree(pwszServers);
  1512. if (rgwszServers)
  1513. LocalFree(rgwszServers);
  1514. return dwStatus;
  1515. }
  1516. DWORD
  1517. GetServersFromRegistry(
  1518. LPWSTR wszRegKey,
  1519. LPWSTR **prgszServers,
  1520. DWORD *pcCount
  1521. )
  1522. {
  1523. HKEY hParamKey = NULL;
  1524. DWORD dwValueType;
  1525. DWORD cbValue = 0, dwDisp;
  1526. LONG lReturn;
  1527. DWORD cbServer;
  1528. DWORD cServers;
  1529. DWORD cchServerMax;
  1530. LPWSTR *rgszServers;
  1531. DWORD i, j;
  1532. *prgszServers = NULL;
  1533. *pcCount = 0;
  1534. lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1535. wszRegKey,
  1536. 0,
  1537. KEY_READ,
  1538. &hParamKey );
  1539. if (ERROR_SUCCESS != lReturn)
  1540. return lReturn;
  1541. lReturn = RegQueryInfoKey(hParamKey,
  1542. NULL,
  1543. NULL,
  1544. NULL,
  1545. &cServers,
  1546. &cchServerMax,
  1547. NULL,
  1548. NULL,
  1549. NULL,
  1550. NULL,
  1551. NULL,
  1552. NULL);
  1553. if (ERROR_SUCCESS != lReturn)
  1554. {
  1555. RegCloseKey( hParamKey );
  1556. return lReturn;
  1557. }
  1558. if (0 == cServers)
  1559. {
  1560. RegCloseKey( hParamKey );
  1561. return ERROR_NO_MORE_ITEMS;
  1562. }
  1563. rgszServers = (LPWSTR *) LocalAlloc(LPTR,cServers*sizeof(LPWSTR));
  1564. if (NULL == rgszServers)
  1565. {
  1566. RegCloseKey( hParamKey );
  1567. return ERROR_NOT_ENOUGH_MEMORY;
  1568. }
  1569. // Add one for null terminator
  1570. cchServerMax++;
  1571. for (i = 0; i < cServers; i++)
  1572. {
  1573. rgszServers[i] = (LPWSTR) LocalAlloc(LPTR,cchServerMax * sizeof(WCHAR));
  1574. if (NULL == rgszServers[i])
  1575. {
  1576. for (j = 0; j < i; j++)
  1577. {
  1578. LocalFree(rgszServers[j]);
  1579. }
  1580. LocalFree(rgszServers);
  1581. RegCloseKey( hParamKey );
  1582. return ERROR_NOT_ENOUGH_MEMORY;
  1583. }
  1584. cbServer = cchServerMax * sizeof(WCHAR);
  1585. lReturn = RegEnumKeyEx(hParamKey,
  1586. i,
  1587. rgszServers[i],
  1588. &cbServer,
  1589. NULL,
  1590. NULL,
  1591. NULL,
  1592. NULL);
  1593. if (ERROR_SUCCESS != lReturn)
  1594. {
  1595. for (j = 0; j <= i; j++)
  1596. {
  1597. LocalFree(rgszServers[j]);
  1598. }
  1599. LocalFree(rgszServers);
  1600. RegCloseKey( hParamKey );
  1601. return lReturn;
  1602. }
  1603. }
  1604. *prgszServers = rgszServers;
  1605. *pcCount = cServers;
  1606. return ERROR_SUCCESS;
  1607. }
  1608. DWORD WINAPI
  1609. EnumerateTlsServerInRegistry(
  1610. IN TLSENUMERATECALLBACK pfCallBack,
  1611. IN HANDLE dwUserData,
  1612. IN DWORD dwTimeOut,
  1613. LPWSTR wszRegKey
  1614. )
  1615. /*++
  1616. ++*/
  1617. {
  1618. BOOL bCancel=FALSE;
  1619. DWORD dwIndex = 0;
  1620. DWORD cServers = 0;
  1621. LPWSTR *rgszServers = NULL;
  1622. DWORD lReturn;
  1623. lReturn = GetServersFromRegistry(wszRegKey,
  1624. &rgszServers,
  1625. &cServers
  1626. );
  1627. if (ERROR_SUCCESS != lReturn)
  1628. {
  1629. return lReturn;
  1630. }
  1631. RandomizeArray(rgszServers,cServers);
  1632. for (;dwIndex < cServers; dwIndex++)
  1633. {
  1634. PCONTEXT_HANDLE pContext=NULL;
  1635. RPC_STATUS rpcStatus;
  1636. bCancel=pfCallBack(pContext, rgszServers[dwIndex], dwUserData);
  1637. if(bCancel == TRUE)
  1638. continue;
  1639. if(!(pContext = TLSConnectToLsServer(rgszServers[dwIndex])))
  1640. {
  1641. //
  1642. // could be access denied, or the machine is gone
  1643. //
  1644. continue;
  1645. }
  1646. do {
  1647. //
  1648. // Skip enterprise server
  1649. //
  1650. DWORD dwVersion;
  1651. rpcStatus = TLSGetVersion( pContext, &dwVersion );
  1652. if(rpcStatus != RPC_S_OK)
  1653. {
  1654. break;
  1655. }
  1656. #if ENFORCE_LICENSING
  1657. //
  1658. // W2K Beta 3 to RC1 upgrade, don't connect to any non-enforce
  1659. // server 5.2 or older
  1660. //
  1661. if(IS_ENFORCE_LSSERVER(dwVersion) == FALSE)
  1662. {
  1663. if( GET_LSSERVER_MAJOR_VERSION(dwVersion) <= 5 &&
  1664. GET_LSSERVER_MINOR_VERSION(dwVersion) <= 2 )
  1665. {
  1666. // old License Server
  1667. continue;
  1668. }
  1669. }
  1670. //
  1671. // Prevent beta <-> RTM server talking to each other
  1672. //
  1673. //
  1674. // TLSIsBetaNTServer() returns TRUE if eval NT
  1675. // IS_LSSERVER_RTM() returns TRUE if LS is an RTM.
  1676. //
  1677. if( TLSIsBetaNTServer() == IS_LSSERVER_RTM(dwVersion) )
  1678. {
  1679. continue;
  1680. }
  1681. #endif
  1682. bCancel=pfCallBack(pContext, rgszServers[dwIndex], dwUserData);
  1683. } while (FALSE);
  1684. if(bCancel == FALSE && pContext != NULL)
  1685. {
  1686. TLSDisconnect(&pContext);
  1687. }
  1688. } // for loop
  1689. for (dwIndex = 0; dwIndex < cServers; dwIndex++)
  1690. {
  1691. LocalFree(rgszServers[dwIndex]);
  1692. }
  1693. LocalFree(rgszServers);
  1694. return ERROR_SUCCESS;
  1695. }
  1696. DWORD WINAPI
  1697. EnumerateTlsServer(
  1698. IN TLSENUMERATECALLBACK pfCallBack,
  1699. IN HANDLE dwUserData,
  1700. IN DWORD dwTimeOut,
  1701. IN BOOL fRegOnly
  1702. )
  1703. /*++
  1704. ++*/
  1705. {
  1706. DWORD dwErr;
  1707. LPWSTR szDomain = NULL;
  1708. BOOL fOffSite = FALSE; // don't try to go off-site
  1709. //
  1710. // First check for a registry bypass of discovery
  1711. //
  1712. dwErr = EnumerateTlsServerInRegistry(
  1713. pfCallBack,
  1714. dwUserData,
  1715. dwTimeOut,
  1716. TEXT(TERMINAL_SERVICE_PARAM_DISCOVERY)
  1717. );
  1718. if ((!fRegOnly) || (g_fInDomain == -1))
  1719. {
  1720. //
  1721. // Check even if set (for !fRegOnly), to get domain name
  1722. //
  1723. dwErr = TLSInDomain(&g_fInDomain, fRegOnly ? NULL : &szDomain);
  1724. if (dwErr != NO_ERROR)
  1725. return dwErr;
  1726. }
  1727. //
  1728. // Reading registry failed, use full discovery
  1729. //
  1730. if(g_fInDomain)
  1731. {
  1732. dwErr = EnumerateTlsServerInDomain(
  1733. szDomain,
  1734. pfCallBack,
  1735. dwUserData,
  1736. dwTimeOut,
  1737. fRegOnly,
  1738. &fOffSite
  1739. );
  1740. if ((dwErr == NO_ERROR) && !fRegOnly)
  1741. {
  1742. g_fOffSiteLicenseServer = fOffSite;
  1743. }
  1744. }
  1745. else
  1746. {
  1747. dwErr = EnumerateTlsServerInWorkGroup(
  1748. pfCallBack,
  1749. dwUserData,
  1750. dwTimeOut,
  1751. fRegOnly
  1752. );
  1753. }
  1754. if (NULL != szDomain)
  1755. {
  1756. NetApiBufferFree(szDomain);
  1757. }
  1758. if ((NULL != g_hImmediateDiscovery)
  1759. && (dwErr != NO_ERROR) && fRegOnly)
  1760. {
  1761. SetEvent(g_hImmediateDiscovery);
  1762. }
  1763. if ((NULL != g_hDiscoverySoon)
  1764. && (dwErr == NO_ERROR) && fOffSite && !fRegOnly)
  1765. {
  1766. SetEvent(g_hDiscoverySoon);
  1767. }
  1768. return dwErr;
  1769. }
  1770. TLS_HANDLE
  1771. ConnectAndCheckServer(LPWSTR szServer)
  1772. {
  1773. TLS_HANDLE hBinding;
  1774. DWORD dwVersion;
  1775. RPC_STATUS rpcStatus;
  1776. hBinding = TLSConnectToLsServer(szServer);
  1777. if(hBinding == NULL)
  1778. {
  1779. goto done;
  1780. }
  1781. // Skip Windows 2000 License servers
  1782. DWORD dwSupportFlags = 0;
  1783. DWORD dwErrCode = 0;
  1784. dwErrCode = TLSGetSupportFlags(
  1785. hBinding,
  1786. &dwSupportFlags
  1787. );
  1788. if ((dwErrCode == RPC_S_OK) && !(dwSupportFlags & SUPPORT_WHISTLER_CAL))
  1789. {
  1790. TLSDisconnect(&hBinding);
  1791. goto done;
  1792. }
  1793. // If the call fails => Windows 2000 LS
  1794. else if(dwErrCode != RPC_S_OK)
  1795. {
  1796. TLSDisconnect(&hBinding);
  1797. goto done;
  1798. }
  1799. rpcStatus = TLSGetVersion(
  1800. hBinding,
  1801. &dwVersion
  1802. );
  1803. if(rpcStatus != RPC_S_OK)
  1804. {
  1805. TLSDisconnect(&hBinding);
  1806. goto done;
  1807. }
  1808. if( TLSIsBetaNTServer() == IS_LSSERVER_RTM(dwVersion) )
  1809. {
  1810. TLSDisconnect(&hBinding);
  1811. goto done;
  1812. }
  1813. done:
  1814. return hBinding;
  1815. }
  1816. //+------------------------------------------------------------------------
  1817. // Function: TLSConnectToAnyLsServer()
  1818. //
  1819. // Description:
  1820. //
  1821. // Routine to bind to any license server
  1822. //
  1823. // Arguments:
  1824. // dwTimeout - INFINITE for going off-site
  1825. //
  1826. // Return Value:
  1827. //
  1828. // RPC binding handle or NULL if error, use GetLastError() to retrieve
  1829. // detail error.
  1830. //-------------------------------------------------------------------------
  1831. TLS_HANDLE WINAPI
  1832. TLSConnectToAnyLsServer(
  1833. DWORD dwTimeout
  1834. )
  1835. /*++
  1836. ++*/
  1837. {
  1838. TLS_HANDLE hBinding=NULL;
  1839. HRESULT hr = S_OK;
  1840. LPWSTR *rgszServers = NULL;
  1841. DWORD cServers = 0;
  1842. DWORD i;
  1843. DWORD dwErr;
  1844. BOOL fInDomain;
  1845. LPWSTR szDomain = NULL;
  1846. LPWSTR szServerFound = NULL;
  1847. BOOL fRegOnly = (dwTimeout != INFINITE);
  1848. LPWSTR pwszServerNames = NULL;
  1849. BOOL fFreeServerNames = TRUE;
  1850. // TODO: add error codes/handling to all of this
  1851. //
  1852. // First check for a registry bypass of discovery
  1853. //
  1854. dwErr = GetServersFromRegistry(
  1855. TEXT(TERMINAL_SERVICE_PARAM_DISCOVERY),
  1856. &rgszServers,
  1857. &cServers
  1858. );
  1859. if (ERROR_SUCCESS == dwErr)
  1860. {
  1861. RandomizeArray(rgszServers,cServers);
  1862. for (i = 0; i < cServers; i++)
  1863. {
  1864. hBinding = ConnectAndCheckServer(rgszServers[i]);
  1865. if (NULL != hBinding)
  1866. {
  1867. szServerFound = rgszServers[i];
  1868. goto found_one;
  1869. }
  1870. }
  1871. if(NULL != rgszServers)
  1872. {
  1873. for (i = 0; i < cServers; i++)
  1874. {
  1875. LocalFree(rgszServers[i]);
  1876. }
  1877. LocalFree(rgszServers);
  1878. rgszServers = NULL;
  1879. }
  1880. }
  1881. //
  1882. // Next try Site (Enterprise) license servers
  1883. //
  1884. if (!fRegOnly)
  1885. {
  1886. hr = GetAllEnterpriseServers(&rgszServers,&cServers);
  1887. if (SUCCEEDED(hr))
  1888. {
  1889. RandomizeArray(rgszServers,cServers);
  1890. }
  1891. }
  1892. else
  1893. {
  1894. // rgszServers[i] is an index into pwszServerNames; don't free
  1895. fFreeServerNames = FALSE;
  1896. hr = GetLicenseServersFromReg(ENTERPRISE_SERVER_MULTI,
  1897. &pwszServerNames,
  1898. &cServers,
  1899. &rgszServers);
  1900. }
  1901. if (SUCCEEDED(hr))
  1902. {
  1903. for (i = 0; i < cServers; i++)
  1904. {
  1905. hBinding = ConnectAndCheckServer(rgszServers[i]);
  1906. if (NULL != hBinding)
  1907. {
  1908. szServerFound = rgszServers[i];
  1909. goto found_one;
  1910. }
  1911. }
  1912. if(NULL != rgszServers)
  1913. {
  1914. if (fFreeServerNames)
  1915. {
  1916. for (i = 0; i < cServers; i++)
  1917. {
  1918. LocalFree(rgszServers[i]);
  1919. }
  1920. LocalFree(rgszServers);
  1921. }
  1922. rgszServers = NULL;
  1923. }
  1924. }
  1925. //
  1926. // No Site LS found, try Domain/Workgroup servers
  1927. //
  1928. dwErr = TLSInDomain(&fInDomain, &szDomain);
  1929. if (dwErr != NO_ERROR)
  1930. {
  1931. return NULL;
  1932. }
  1933. LS_ENUM_PARAM param;
  1934. param.hBinding = &hBinding;
  1935. param.dwTimeout = INFINITE;
  1936. QueryPerformanceCounter(&(param.timeInitial));
  1937. fFreeServerNames = TRUE;
  1938. if (fInDomain)
  1939. {
  1940. BOOL fOffSite = TRUE;
  1941. dwErr = EnumerateTlsServerInDomain(
  1942. szDomain,
  1943. BindAnyServer,
  1944. &param,
  1945. INFINITE,
  1946. fRegOnly,
  1947. &fOffSite
  1948. );
  1949. if (dwErr == NO_ERROR)
  1950. {
  1951. g_fOffSiteLicenseServer = fOffSite;
  1952. }
  1953. }
  1954. else
  1955. {
  1956. dwErr = EnumerateTlsServerInWorkGroup(
  1957. BindAnyServer,
  1958. &param,
  1959. MAILSLOT_WAIT_FOREVER,
  1960. fRegOnly
  1961. );
  1962. }
  1963. if (NULL != szDomain)
  1964. {
  1965. NetApiBufferFree(szDomain);
  1966. }
  1967. if (hBinding != NULL)
  1968. goto found_one;
  1969. if (NULL != pwszServerNames)
  1970. {
  1971. LocalFree(pwszServerNames);
  1972. }
  1973. if ((NULL != g_hImmediateDiscovery)
  1974. && fRegOnly)
  1975. {
  1976. SetEvent(g_hImmediateDiscovery);
  1977. }
  1978. else if ((NULL != g_hDiscoverySoon)
  1979. && !fRegOnly && g_fOffSiteLicenseServer)
  1980. {
  1981. SetEvent(g_hDiscoverySoon);
  1982. }
  1983. return NULL;
  1984. found_one:
  1985. if (NULL != pwszServerNames)
  1986. {
  1987. LocalFree(pwszServerNames);
  1988. }
  1989. if(NULL != rgszServers)
  1990. {
  1991. if (fFreeServerNames)
  1992. {
  1993. for (i = 0; i < cServers; i++)
  1994. {
  1995. LocalFree(rgszServers[i]);
  1996. }
  1997. }
  1998. LocalFree(rgszServers);
  1999. }
  2000. return hBinding;
  2001. }
  2002. BOOL
  2003. TLSRefreshLicenseServerCache(
  2004. IN DWORD dwTimeOut
  2005. )
  2006. /*++
  2007. Abstract:
  2008. Refresh license server cache in registry.
  2009. Parameter:
  2010. dwTimeOut : Reserverd, should pass in INIFINITE for now
  2011. Returns:
  2012. TRUE/FALSE
  2013. --*/
  2014. {
  2015. BOOL bFoundServer = FALSE;
  2016. TLS_HANDLE hBinding = NULL;
  2017. hBinding = TLSConnectToAnyLsServer(dwTimeOut);
  2018. if (NULL != hBinding)
  2019. {
  2020. bFoundServer = TRUE;
  2021. TLSDisconnect(&hBinding);
  2022. }
  2023. return bFoundServer;
  2024. }
  2025. LICENSE_STATUS
  2026. InstallCertificate(LPVOID lpParam)
  2027. {
  2028. Sleep(INSTALL_CERT_DELAY);
  2029. return LsCsp_InstallX509Certificate(NULL);
  2030. }
  2031. //-------------------------------------------------------------------------
  2032. TLS_HANDLE WINAPI
  2033. TLSConnectToLsServer(
  2034. LPTSTR pszLsServer
  2035. )
  2036. /*++
  2037. ++*/
  2038. {
  2039. TCHAR szMachineName[MAX_COMPUTERNAME_LENGTH + 1] ;
  2040. PCONTEXT_HANDLE pContext=NULL;
  2041. DWORD cbMachineName=MAX_COMPUTERNAME_LENGTH;
  2042. HANDLE hThread = NULL;
  2043. static BOOL fLSFound = FALSE;
  2044. memset(szMachineName, 0, sizeof(szMachineName));
  2045. GetComputerName(szMachineName, &cbMachineName);
  2046. if(pszLsServer == NULL || _tcsicmp(szMachineName, pszLsServer) == 0)
  2047. {
  2048. pContext=ConnectLsServer(
  2049. szMachineName,
  2050. _TEXT(RPC_PROTOSEQLPC),
  2051. NULL,
  2052. RPC_C_AUTHN_LEVEL_DEFAULT
  2053. );
  2054. if(GetLastError() >= LSERVER_ERROR_BASE)
  2055. {
  2056. return NULL;
  2057. }
  2058. // try to connect with TCP protocol, if local procedure failed
  2059. }
  2060. if(pContext == NULL)
  2061. {
  2062. pContext=ConnectLsServer(
  2063. pszLsServer,
  2064. _TEXT(RPC_PROTOSEQNP),
  2065. _TEXT(LSNAMEPIPE),
  2066. RPC_C_AUTHN_LEVEL_PKT_PRIVACY
  2067. );
  2068. }
  2069. if (!fLSFound && (NULL != pContext))
  2070. {
  2071. fLSFound = TRUE;
  2072. // Now that someone's connected, we can install a license
  2073. hThread = CreateThread(NULL,
  2074. 0,
  2075. InstallCertificate,
  2076. NULL,
  2077. 0,
  2078. NULL);
  2079. if (hThread != NULL)
  2080. {
  2081. CloseHandle(hThread);
  2082. }
  2083. else
  2084. {
  2085. // Can't create the thread; try again later
  2086. fLSFound = FALSE;
  2087. }
  2088. }
  2089. return (TLS_HANDLE) pContext;
  2090. }
  2091. //-------------------------------------------------------------------------
  2092. void WINAPI
  2093. TLSDisconnectFromServer(
  2094. TLS_HANDLE pHandle
  2095. )
  2096. /*++
  2097. ++*/
  2098. {
  2099. if(pHandle != NULL)
  2100. {
  2101. TLSDisconnect( &pHandle );
  2102. }
  2103. }
  2104. //----------------------------------------------------------------------------
  2105. DWORD WINAPI
  2106. TLSConnect(
  2107. handle_t binding,
  2108. TLS_HANDLE *ppHandle
  2109. )
  2110. /*++
  2111. ++*/
  2112. {
  2113. return TLSRpcConnect(binding, ppHandle);
  2114. }
  2115. //----------------------------------------------------------------------------
  2116. DWORD WINAPI
  2117. TLSDisconnect(
  2118. TLS_HANDLE* pphHandle
  2119. )
  2120. /*++
  2121. ++*/
  2122. {
  2123. RPC_STATUS rpc_status;
  2124. rpc_status = TLSRpcDisconnect( pphHandle );
  2125. if(rpc_status != RPC_S_OK)
  2126. {
  2127. RpcSmDestroyClientContext(pphHandle);
  2128. }
  2129. *pphHandle = NULL;
  2130. return ERROR_SUCCESS;
  2131. }
  2132. //-------------------------------------------------------------------------
  2133. DWORD WINAPI
  2134. TLSGetVersion (
  2135. IN TLS_HANDLE hHandle,
  2136. OUT PDWORD pdwVersion
  2137. )
  2138. /*++
  2139. ++*/
  2140. {
  2141. return TLSRpcGetVersion( hHandle, pdwVersion );
  2142. }
  2143. //----------------------------------------------------------------------------
  2144. DWORD WINAPI
  2145. TLSSendServerCertificate(
  2146. TLS_HANDLE hHandle,
  2147. DWORD cbCert,
  2148. PBYTE pbCert,
  2149. PDWORD pdwErrCode
  2150. )
  2151. /*++
  2152. ++*/
  2153. {
  2154. return TLSRpcSendServerCertificate(
  2155. hHandle,
  2156. cbCert,
  2157. pbCert,
  2158. pdwErrCode
  2159. );
  2160. }
  2161. //----------------------------------------------------------------------------
  2162. DWORD WINAPI
  2163. TLSGetServerName(
  2164. TLS_HANDLE hHandle,
  2165. LPTSTR szMachineName,
  2166. PDWORD pcbSize,
  2167. PDWORD pdwErrCode
  2168. )
  2169. /*++
  2170. ++*/
  2171. {
  2172. return TLSRpcGetServerName(
  2173. hHandle,
  2174. szMachineName,
  2175. pcbSize,
  2176. pdwErrCode
  2177. );
  2178. }
  2179. //----------------------------------------------------------------------------
  2180. DWORD WINAPI
  2181. TLSGetServerNameEx(
  2182. TLS_HANDLE hHandle,
  2183. LPTSTR szMachineName,
  2184. PDWORD pcbSize,
  2185. PDWORD pdwErrCode
  2186. )
  2187. /*++
  2188. ++*/
  2189. {
  2190. RPC_STATUS rpc_status;
  2191. rpc_status = TLSRpcGetServerNameEx(
  2192. hHandle,
  2193. szMachineName,
  2194. pcbSize,
  2195. pdwErrCode
  2196. );
  2197. if (rpc_status == RPC_S_PROCNUM_OUT_OF_RANGE)
  2198. {
  2199. rpc_status = TLSRpcGetServerName(
  2200. hHandle,
  2201. szMachineName,
  2202. pcbSize,
  2203. pdwErrCode
  2204. );
  2205. }
  2206. return rpc_status;
  2207. }
  2208. //----------------------------------------------------------------------------
  2209. DWORD WINAPI
  2210. TLSGetServerNameFixed(
  2211. TLS_HANDLE hHandle,
  2212. LPTSTR *pszMachineName,
  2213. PDWORD pdwErrCode
  2214. )
  2215. /*++
  2216. ++*/
  2217. {
  2218. return TLSRpcGetServerNameFixed(
  2219. hHandle,
  2220. pszMachineName,
  2221. pdwErrCode
  2222. );
  2223. }
  2224. //----------------------------------------------------------------------------
  2225. DWORD WINAPI
  2226. TLSGetServerScope(
  2227. TLS_HANDLE hHandle,
  2228. LPTSTR szScopeName,
  2229. PDWORD pcbSize,
  2230. PDWORD pdwErrCode)
  2231. /*++
  2232. ++*/
  2233. {
  2234. return TLSRpcGetServerScope(
  2235. hHandle,
  2236. szScopeName,
  2237. pcbSize,
  2238. pdwErrCode
  2239. );
  2240. }
  2241. //----------------------------------------------------------------------------
  2242. DWORD WINAPI
  2243. TLSGetServerScopeFixed(
  2244. TLS_HANDLE hHandle,
  2245. LPTSTR *pszScopeName,
  2246. PDWORD pdwErrCode)
  2247. /*++
  2248. ++*/
  2249. {
  2250. return TLSRpcGetServerScopeFixed(
  2251. hHandle,
  2252. pszScopeName,
  2253. pdwErrCode
  2254. );
  2255. }
  2256. //----------------------------------------------------------------------------
  2257. DWORD WINAPI
  2258. TLSIssuePlatformChallenge(
  2259. TLS_HANDLE hHandle,
  2260. DWORD dwClientInfo,
  2261. PCHALLENGE_CONTEXT pChallengeContext,
  2262. PDWORD pcbChallengeData,
  2263. PBYTE* pChallengeData,
  2264. PDWORD pdwErrCode
  2265. )
  2266. /*++
  2267. ++*/
  2268. {
  2269. return TLSRpcIssuePlatformChallenge(
  2270. hHandle,
  2271. dwClientInfo,
  2272. pChallengeContext,
  2273. pcbChallengeData,
  2274. pChallengeData,
  2275. pdwErrCode
  2276. );
  2277. }
  2278. //----------------------------------------------------------------------------
  2279. DWORD WINAPI
  2280. TLSIssueNewLicense(
  2281. TLS_HANDLE hHandle,
  2282. CHALLENGE_CONTEXT ChallengeContext,
  2283. LICENSEREQUEST *pRequest,
  2284. LPTSTR pMachineName,
  2285. LPTSTR pUserName,
  2286. DWORD cbChallengeResponse,
  2287. PBYTE pbChallengeResponse,
  2288. BOOL bAcceptTemporaryLicense,
  2289. PDWORD pcbLicense,
  2290. PBYTE* ppbLicense,
  2291. PDWORD pdwErrCode
  2292. )
  2293. /*++
  2294. ++*/
  2295. {
  2296. TLSLICENSEREQUEST rpcRequest;
  2297. RequestToTlsRequest( pRequest, &rpcRequest );
  2298. return TLSRpcRequestNewLicense(
  2299. hHandle,
  2300. ChallengeContext,
  2301. &rpcRequest,
  2302. pMachineName,
  2303. pUserName,
  2304. cbChallengeResponse,
  2305. pbChallengeResponse,
  2306. bAcceptTemporaryLicense,
  2307. pcbLicense,
  2308. ppbLicense,
  2309. pdwErrCode
  2310. );
  2311. }
  2312. //----------------------------------------------------------------------------
  2313. DWORD WINAPI
  2314. TLSIssueNewLicenseEx(
  2315. TLS_HANDLE hHandle,
  2316. PDWORD pSupportFlags,
  2317. CHALLENGE_CONTEXT ChallengeContext,
  2318. LICENSEREQUEST *pRequest,
  2319. LPTSTR pMachineName,
  2320. LPTSTR pUserName,
  2321. DWORD cbChallengeResponse,
  2322. PBYTE pbChallengeResponse,
  2323. BOOL bAcceptTemporaryLicense,
  2324. DWORD dwQuantity,
  2325. PDWORD pcbLicense,
  2326. PBYTE* ppbLicense,
  2327. PDWORD pdwErrCode
  2328. )
  2329. /*++
  2330. ++*/
  2331. {
  2332. DWORD dwStatus;
  2333. TLSLICENSEREQUEST rpcRequest;
  2334. RequestToTlsRequest( pRequest, &rpcRequest );
  2335. dwStatus = TLSRpcRequestNewLicenseEx(
  2336. hHandle,
  2337. pSupportFlags,
  2338. ChallengeContext,
  2339. &rpcRequest,
  2340. pMachineName,
  2341. pUserName,
  2342. cbChallengeResponse,
  2343. pbChallengeResponse,
  2344. bAcceptTemporaryLicense,
  2345. dwQuantity,
  2346. pcbLicense,
  2347. ppbLicense,
  2348. pdwErrCode
  2349. );
  2350. if (dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE)
  2351. {
  2352. *pSupportFlags = 0;
  2353. dwStatus = TLSRpcRequestNewLicense(
  2354. hHandle,
  2355. ChallengeContext,
  2356. &rpcRequest,
  2357. pMachineName,
  2358. pUserName,
  2359. cbChallengeResponse,
  2360. pbChallengeResponse,
  2361. bAcceptTemporaryLicense,
  2362. pcbLicense,
  2363. ppbLicense,
  2364. pdwErrCode
  2365. );
  2366. }
  2367. return(dwStatus);
  2368. }
  2369. //----------------------------------------------------------------------------
  2370. DWORD WINAPI
  2371. TLSIssueNewLicenseExEx(
  2372. TLS_HANDLE hHandle,
  2373. PDWORD pSupportFlags,
  2374. CHALLENGE_CONTEXT ChallengeContext,
  2375. LICENSEREQUEST *pRequest,
  2376. LPTSTR pMachineName,
  2377. LPTSTR pUserName,
  2378. DWORD cbChallengeResponse,
  2379. PBYTE pbChallengeResponse,
  2380. BOOL bAcceptTemporaryLicense,
  2381. BOOL bAcceptFewerLicenses,
  2382. DWORD *pdwQuantity,
  2383. PDWORD pcbLicense,
  2384. PBYTE* ppbLicense,
  2385. PDWORD pdwErrCode
  2386. )
  2387. /*++
  2388. ++*/
  2389. {
  2390. DWORD dwStatus;
  2391. TLSLICENSEREQUEST rpcRequest;
  2392. RequestToTlsRequest( pRequest, &rpcRequest );
  2393. dwStatus = TLSRpcRequestNewLicenseExEx(
  2394. hHandle,
  2395. pSupportFlags,
  2396. ChallengeContext,
  2397. &rpcRequest,
  2398. pMachineName,
  2399. pUserName,
  2400. cbChallengeResponse,
  2401. pbChallengeResponse,
  2402. bAcceptTemporaryLicense,
  2403. bAcceptFewerLicenses,
  2404. pdwQuantity,
  2405. pcbLicense,
  2406. ppbLicense,
  2407. pdwErrCode
  2408. );
  2409. if (dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE)
  2410. {
  2411. dwStatus = TLSRpcRequestNewLicenseEx(
  2412. hHandle,
  2413. pSupportFlags,
  2414. ChallengeContext,
  2415. &rpcRequest,
  2416. pMachineName,
  2417. pUserName,
  2418. cbChallengeResponse,
  2419. pbChallengeResponse,
  2420. bAcceptTemporaryLicense,
  2421. *pdwQuantity,
  2422. pcbLicense,
  2423. ppbLicense,
  2424. pdwErrCode
  2425. );
  2426. if (dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE)
  2427. {
  2428. *pSupportFlags = 0;
  2429. dwStatus = TLSRpcRequestNewLicense(
  2430. hHandle,
  2431. ChallengeContext,
  2432. &rpcRequest,
  2433. pMachineName,
  2434. pUserName,
  2435. cbChallengeResponse,
  2436. pbChallengeResponse,
  2437. bAcceptTemporaryLicense,
  2438. pcbLicense,
  2439. ppbLicense,
  2440. pdwErrCode
  2441. );
  2442. }
  2443. }
  2444. return(dwStatus);
  2445. }
  2446. //----------------------------------------------------------------------------
  2447. DWORD WINAPI
  2448. TLSUpgradeLicense(
  2449. TLS_HANDLE hHandle,
  2450. LICENSEREQUEST *pRequest,
  2451. CHALLENGE_CONTEXT ChallengeContext,
  2452. DWORD cbChallengeResponse,
  2453. PBYTE pbChallengeResponse,
  2454. DWORD cbOldLicense,
  2455. PBYTE pbOldLicense,
  2456. PDWORD pcbNewLicense,
  2457. PBYTE* ppbNewLicense,
  2458. PDWORD pdwErrCode
  2459. )
  2460. /*++
  2461. ++*/
  2462. {
  2463. TLSLICENSEREQUEST rpcRequest;
  2464. RequestToTlsRequest( pRequest, &rpcRequest );
  2465. return TLSRpcUpgradeLicense(
  2466. hHandle,
  2467. &rpcRequest,
  2468. ChallengeContext,
  2469. cbChallengeResponse,
  2470. pbChallengeResponse,
  2471. cbOldLicense,
  2472. pbOldLicense,
  2473. pcbNewLicense,
  2474. ppbNewLicense,
  2475. pdwErrCode
  2476. );
  2477. }
  2478. //----------------------------------------------------------------------------
  2479. DWORD WINAPI
  2480. TLSUpgradeLicenseEx(
  2481. TLS_HANDLE hHandle,
  2482. PDWORD pSupportFlags,
  2483. LICENSEREQUEST *pRequest,
  2484. CHALLENGE_CONTEXT ChallengeContext,
  2485. DWORD cbChallengeResponse,
  2486. PBYTE pbChallengeResponse,
  2487. DWORD cbOldLicense,
  2488. PBYTE pbOldLicense,
  2489. DWORD dwQuantity,
  2490. PDWORD pcbNewLicense,
  2491. PBYTE* ppbNewLicense,
  2492. PDWORD pdwErrCode
  2493. )
  2494. /*++
  2495. ++*/
  2496. {
  2497. DWORD dwStatus;
  2498. TLSLICENSEREQUEST rpcRequest;
  2499. RequestToTlsRequest( pRequest, &rpcRequest );
  2500. dwStatus = TLSRpcUpgradeLicenseEx(
  2501. hHandle,
  2502. pSupportFlags,
  2503. &rpcRequest,
  2504. ChallengeContext,
  2505. cbChallengeResponse,
  2506. pbChallengeResponse,
  2507. cbOldLicense,
  2508. pbOldLicense,
  2509. dwQuantity,
  2510. pcbNewLicense,
  2511. ppbNewLicense,
  2512. pdwErrCode
  2513. );
  2514. if (dwStatus == RPC_S_PROCNUM_OUT_OF_RANGE)
  2515. {
  2516. *pSupportFlags = 0;
  2517. dwStatus = TLSRpcUpgradeLicense(
  2518. hHandle,
  2519. &rpcRequest,
  2520. ChallengeContext,
  2521. cbChallengeResponse,
  2522. pbChallengeResponse,
  2523. cbOldLicense,
  2524. pbOldLicense,
  2525. pcbNewLicense,
  2526. ppbNewLicense,
  2527. pdwErrCode
  2528. );
  2529. }
  2530. return(dwStatus);
  2531. }
  2532. //----------------------------------------------------------------------------
  2533. DWORD WINAPI
  2534. TLSAllocateConcurrentLicense(
  2535. TLS_HANDLE hHandle,
  2536. LPTSTR szHydraServer,
  2537. LICENSEREQUEST *pRequest,
  2538. LONG *dwQuantity,
  2539. PDWORD pdwErrCode
  2540. )
  2541. /*++
  2542. ++*/
  2543. {
  2544. TLSLICENSEREQUEST rpcRequest;
  2545. RequestToTlsRequest( pRequest, &rpcRequest );
  2546. return TLSRpcAllocateConcurrentLicense(
  2547. hHandle,
  2548. szHydraServer,
  2549. &rpcRequest,
  2550. dwQuantity,
  2551. pdwErrCode
  2552. );
  2553. }
  2554. //----------------------------------------------------------------------------
  2555. DWORD WINAPI
  2556. TLSGetLastError(
  2557. TLS_HANDLE hHandle,
  2558. DWORD cbBufferSize,
  2559. LPTSTR pszBuffer,
  2560. PDWORD pdwErrCode
  2561. )
  2562. /*++
  2563. ++*/
  2564. {
  2565. return TLSRpcGetLastError(
  2566. hHandle,
  2567. &cbBufferSize,
  2568. pszBuffer,
  2569. pdwErrCode
  2570. );
  2571. }
  2572. //----------------------------------------------------------------------------
  2573. DWORD WINAPI
  2574. TLSGetLastErrorFixed(
  2575. TLS_HANDLE hHandle,
  2576. LPTSTR *pszBuffer,
  2577. PDWORD pdwErrCode
  2578. )
  2579. /*++
  2580. ++*/
  2581. {
  2582. return TLSRpcGetLastErrorFixed(
  2583. hHandle,
  2584. pszBuffer,
  2585. pdwErrCode
  2586. );
  2587. }
  2588. //----------------------------------------------------------------------------
  2589. DWORD WINAPI
  2590. TLSKeyPackEnumBegin(
  2591. TLS_HANDLE hHandle,
  2592. DWORD dwSearchParm,
  2593. BOOL bMatchAll,
  2594. LPLSKeyPackSearchParm lpSearchParm,
  2595. PDWORD pdwErrCode
  2596. )
  2597. /*++
  2598. ++*/
  2599. {
  2600. return TLSRpcKeyPackEnumBegin(
  2601. hHandle,
  2602. dwSearchParm,
  2603. bMatchAll,
  2604. lpSearchParm,
  2605. pdwErrCode
  2606. );
  2607. }
  2608. //----------------------------------------------------------------------------
  2609. DWORD WINAPI
  2610. TLSKeyPackEnumNext(
  2611. TLS_HANDLE hHandle,
  2612. LPLSKeyPack lpKeyPack,
  2613. PDWORD pdwErrCode
  2614. )
  2615. /*++
  2616. ++*/
  2617. {
  2618. return TLSRpcKeyPackEnumNext(
  2619. hHandle,
  2620. lpKeyPack,
  2621. pdwErrCode
  2622. );
  2623. }
  2624. //----------------------------------------------------------------------------
  2625. DWORD WINAPI
  2626. TLSKeyPackEnumEnd(
  2627. TLS_HANDLE hHandle,
  2628. PDWORD pdwErrCode
  2629. )
  2630. /*++
  2631. ++*/
  2632. {
  2633. return TLSRpcKeyPackEnumEnd(hHandle, pdwErrCode);
  2634. }
  2635. //----------------------------------------------------------------------------
  2636. DWORD WINAPI
  2637. TLSLicenseEnumBegin(
  2638. TLS_HANDLE hHandle,
  2639. DWORD dwSearchParm,
  2640. BOOL bMatchAll,
  2641. LPLSLicenseSearchParm lpSearchParm,
  2642. PDWORD pdwErrCode
  2643. )
  2644. /*++
  2645. ++*/
  2646. {
  2647. return TLSRpcLicenseEnumBegin(
  2648. hHandle,
  2649. dwSearchParm,
  2650. bMatchAll,
  2651. lpSearchParm,
  2652. pdwErrCode
  2653. );
  2654. }
  2655. //----------------------------------------------------------------------------
  2656. DWORD WINAPI
  2657. TLSLicenseEnumNext(
  2658. TLS_HANDLE hHandle,
  2659. LPLSLicense lpLicense,
  2660. PDWORD pdwErrCode
  2661. )
  2662. /*++
  2663. ++*/
  2664. {
  2665. return TLSRpcLicenseEnumNext(
  2666. hHandle,
  2667. lpLicense,
  2668. pdwErrCode
  2669. );
  2670. }
  2671. //----------------------------------------------------------------------------
  2672. DWORD WINAPI
  2673. TLSLicenseEnumNextEx(
  2674. TLS_HANDLE hHandle,
  2675. LPLSLicenseEx lpLicenseEx,
  2676. PDWORD pdwErrCode
  2677. )
  2678. /*++
  2679. ++*/
  2680. {
  2681. DWORD dwRet;
  2682. if (NULL == lpLicenseEx)
  2683. {
  2684. return ERROR_INVALID_PARAMETER;
  2685. }
  2686. dwRet = TLSRpcLicenseEnumNextEx(
  2687. hHandle,
  2688. lpLicenseEx,
  2689. pdwErrCode
  2690. );
  2691. if (RPC_S_PROCNUM_OUT_OF_RANGE == dwRet)
  2692. {
  2693. LSLicense License;
  2694. dwRet = TLSRpcLicenseEnumNext(
  2695. hHandle,
  2696. &License,
  2697. pdwErrCode
  2698. );
  2699. if ((dwRet == RPC_S_OK)
  2700. && (NULL != pdwErrCode)
  2701. && (*pdwErrCode == ERROR_SUCCESS))
  2702. {
  2703. // older versions only support quantity == 1
  2704. memcpy(lpLicenseEx,&License,sizeof(License));
  2705. lpLicenseEx->dwQuantity = 1;
  2706. }
  2707. }
  2708. return dwRet;
  2709. }
  2710. //----------------------------------------------------------------------------
  2711. DWORD WINAPI
  2712. TLSLicenseEnumEnd(
  2713. TLS_HANDLE hHandle,
  2714. PDWORD pdwErrCode
  2715. )
  2716. /*++
  2717. ++*/
  2718. {
  2719. return TLSRpcLicenseEnumEnd(hHandle, pdwErrCode);
  2720. }
  2721. //----------------------------------------------------------------------------
  2722. DWORD WINAPI
  2723. TLSGetAvailableLicenses(
  2724. TLS_HANDLE hHandle,
  2725. DWORD dwSearchParm,
  2726. LPLSKeyPack lplsKeyPack,
  2727. LPDWORD lpdwAvail,
  2728. PDWORD pdwErrCode
  2729. )
  2730. /*++
  2731. ++*/
  2732. {
  2733. return TLSRpcGetAvailableLicenses(
  2734. hHandle,
  2735. dwSearchParm,
  2736. lplsKeyPack,
  2737. lpdwAvail,
  2738. pdwErrCode
  2739. );
  2740. }
  2741. //----------------------------------------------------------------------------
  2742. DWORD WINAPI
  2743. TLSGetRevokeKeyPackList(
  2744. TLS_HANDLE hHandle,
  2745. PDWORD pcbNumberOfRange,
  2746. LPLSRange *ppRevokeRange,
  2747. PDWORD pdwErrCode
  2748. )
  2749. /*++
  2750. ++*/
  2751. {
  2752. return TLSRpcGetRevokeKeyPackList(
  2753. hHandle,
  2754. pcbNumberOfRange,
  2755. ppRevokeRange,
  2756. pdwErrCode
  2757. );
  2758. }
  2759. //----------------------------------------------------------------------------
  2760. DWORD WINAPI
  2761. TLSGetRevokeLicenseList(
  2762. TLS_HANDLE hHandle,
  2763. PDWORD pcbNumberOfRange,
  2764. LPLSRange *ppRevokeRange,
  2765. PDWORD pdwErrCode
  2766. )
  2767. /*++
  2768. ++*/
  2769. {
  2770. return TLSRpcGetRevokeLicenseList(
  2771. hHandle,
  2772. pcbNumberOfRange,
  2773. ppRevokeRange,
  2774. pdwErrCode
  2775. );
  2776. }
  2777. //----------------------------------------------------------------------------
  2778. DWORD WINAPI
  2779. TLSMarkLicense(
  2780. TLS_HANDLE hHandle,
  2781. UCHAR ucFlags,
  2782. DWORD cbLicense,
  2783. PBYTE pLicense,
  2784. PDWORD pdwErrCode
  2785. )
  2786. /*++
  2787. ++*/
  2788. {
  2789. return TLSRpcMarkLicense(
  2790. hHandle,
  2791. ucFlags,
  2792. cbLicense,
  2793. pLicense,
  2794. pdwErrCode
  2795. );
  2796. }
  2797. //----------------------------------------------------------------------------
  2798. DWORD WINAPI
  2799. TLSCheckLicenseMark(
  2800. TLS_HANDLE hHandle,
  2801. DWORD cbLicense,
  2802. PBYTE pLicense,
  2803. PUCHAR pucFlags,
  2804. PDWORD pdwErrCode
  2805. )
  2806. /*++
  2807. ++*/
  2808. {
  2809. return TLSRpcCheckLicenseMark(
  2810. hHandle,
  2811. cbLicense,
  2812. pLicense,
  2813. pucFlags,
  2814. pdwErrCode
  2815. );
  2816. }
  2817. //----------------------------------------------------------------------------
  2818. DWORD WINAPI
  2819. TLSGetSupportFlags(
  2820. TLS_HANDLE hHandle,
  2821. DWORD *pdwSupportFlags
  2822. )
  2823. /*++
  2824. ++*/
  2825. {
  2826. return TLSRpcGetSupportFlags(
  2827. hHandle,
  2828. pdwSupportFlags
  2829. );
  2830. }