Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

446 lines
14 KiB

  1. /*-----------------------------------------------**
  2. ** Copyright (c) 1999 Microsoft Corporation **
  3. ** All Rights reserved **
  4. ** **
  5. ** tsvsm.cpp **
  6. ** **
  7. ** Main for TsVer.dll **
  8. ** **
  9. ** 06-25-99 a-clindh Created **
  10. **-----------------------------------------------*/
  11. #include "tsvsm.h"
  12. WINSTATIONCLIENT ClientData;
  13. int g_count;
  14. HINSTANCE g_hInst;
  15. TCHAR szWinStaKey[MAX_PATH];
  16. //////////////////////////////////////////////////////////////////////////////
  17. BOOL WINAPI DllMain(
  18. HINSTANCE hinstDLL, // handle to DLL module
  19. DWORD fdwReason, // reason for calling function
  20. LPVOID lpReserved ) // reserved
  21. {
  22. // Perform actions based on the reason for calling.
  23. switch( fdwReason )
  24. {
  25. case DLL_PROCESS_ATTACH:
  26. // Initialize once for each new process.
  27. // Return FALSE to fail DLL load.
  28. break;
  29. case DLL_THREAD_ATTACH:
  30. // Do thread-specific initialization.
  31. break;
  32. case DLL_THREAD_DETACH:
  33. // Do thread-specific cleanup.
  34. break;
  35. case DLL_PROCESS_DETACH:
  36. // Perform any necessary cleanup.
  37. break;
  38. }
  39. return TRUE; // Successful DLL_PROCESS_ATTACH.
  40. }
  41. //////////////////////////////////////////////////////////////////////////////
  42. VOID TsVerEventStartup (PWLX_NOTIFICATION_INFO pInfo)
  43. {
  44. CheckClientVersion();
  45. }
  46. //////////////////////////////////////////////////////////////////////////////
  47. int CheckClientVersion(void)
  48. //VOID CheckClientVersion (PWLX_NOTIFICATION_INFO pInfo)
  49. {
  50. DWORD pBytesReturned;
  51. OSVERSIONINFO osvi;
  52. ULONG *pNumber;
  53. TCHAR szNewRegistryString[MAX_LEN];
  54. TCHAR tmp[MAX_PATH];
  55. TCHAR szConstraints[MAX_LEN];
  56. UINT i;
  57. BOOL b1 = FALSE, b2 = FALSE, b3 = FALSE, b4 = FALSE;
  58. // Get the handle to the dll
  59. g_hInst = GetModuleHandle(TEXT("tsver"));
  60. // path to the registry keys
  61. LoadString (g_hInst, IDS_REG_KEY_PATH,
  62. szWinStaKey, sizeof (szWinStaKey));
  63. // if NO "Constraints" registry key value is there, write one
  64. if (! CheckForRegKey(HKEY_USERS, szWinStaKey, KeyName[CONSTRAINTS]))
  65. {
  66. // String to allow everyone on. Only write this if
  67. // there is no key present.
  68. // Get the current version
  69. osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  70. GetVersionEx (&osvi);
  71. _tcscpy(szNewRegistryString, TEXT("(0:"));
  72. _itot(++osvi.dwBuildNumber, tmp, 10);
  73. _tcscat(szNewRegistryString, tmp);
  74. _tcscat(szNewRegistryString, TEXT(")"));
  75. // write the range from 0 to the current build + 1
  76. szNewRegistryString[_tcslen(szNewRegistryString)] = '\0';
  77. SetRegKeyString(HKEY_USERS, szNewRegistryString,
  78. szWinStaKey, KeyName[CONSTRAINTS]);
  79. }
  80. if (GetSystemMetrics(SM_REMOTESESSION))
  81. {
  82. if (WTSQuerySessionInformation(
  83. WTS_CURRENT_SERVER_HANDLE,
  84. GetCurrentLogonId(),
  85. WTSClientBuildNumber,
  86. (LPTSTR *)(&pNumber),
  87. &pBytesReturned))
  88. {
  89. WinStationQueryInformation(
  90. WTS_CURRENT_SERVER_HANDLE,
  91. GetCurrentLogonId(),
  92. WinStationClient,
  93. &ClientData,
  94. sizeof(WINSTATIONCLIENT),
  95. &pBytesReturned );
  96. // let me on if:
  97. // = Can be more than 1 entry, client build must equal this number.
  98. // < Can only be 1 entry. ANY build less than this number.
  99. // > Can only be 1 entry. ANY build greater than this number.
  100. // != Can be more than 1 entry, client build can't equal this number.
  101. // (####:####) Can be more than 1 entry.
  102. // If client build is within this range.
  103. // ; separator (semicolon)
  104. // "=419,2054,2070;(9000:9050);(2063:2070)"
  105. // get the constraints string from the registry
  106. _tcscpy(szConstraints, GetRegString(HKEY_USERS,
  107. szWinStaKey, KeyName[CONSTRAINTS]));
  108. for (i = 0; i < _tcslen(szConstraints); i++)
  109. {
  110. switch (szConstraints[i])
  111. {
  112. case '=':
  113. {
  114. g_count = 0;
  115. // skip the case where the = sign follows a !
  116. if (szConstraints[i-1] != '!')
  117. if (ParseNumberFromString(i,
  118. szConstraints,
  119. *pNumber))
  120. {
  121. b1 = TRUE;
  122. } else {
  123. b1 = FALSE;
  124. }
  125. }
  126. break;
  127. case '<':
  128. {
  129. g_count = 0;
  130. if (LessThan(i,
  131. szConstraints,
  132. *pNumber))
  133. {
  134. b2 = TRUE;
  135. } else {
  136. b2 = FALSE;
  137. }
  138. }
  139. break;
  140. case '>':
  141. {
  142. g_count = 0;
  143. if (GreaterThan(i,
  144. szConstraints,
  145. *pNumber))
  146. {
  147. b3 = TRUE;
  148. } else {
  149. b3 = FALSE;
  150. }
  151. }
  152. break;
  153. case '!':
  154. {
  155. g_count = 0;
  156. i++; // increment past the = sign
  157. if (ParseNumberFromString(i,
  158. szConstraints,
  159. *pNumber))
  160. {
  161. // if we find this number we can just
  162. // kick the user off.
  163. KickMeOff(*pNumber);
  164. WTSFreeMemory(pNumber);
  165. return 0;
  166. }
  167. }
  168. break;
  169. case '(':
  170. {
  171. g_count = 0;
  172. if (ParseRangeFromString(i,
  173. szConstraints,
  174. *pNumber))
  175. {
  176. b4 = TRUE;
  177. } else {
  178. b4 = FALSE;
  179. }
  180. }
  181. break;
  182. default:
  183. break;
  184. }
  185. }
  186. }
  187. }
  188. // if the user hasn't passed at least one of our constraints
  189. // then kick them off.
  190. if (GetSystemMetrics(SM_REMOTESESSION))// so we can run the first time
  191. // to initially write the registry
  192. // keys without getting a warning
  193. if (!b1 && !b2 && !b3 && !b4)
  194. KickMeOff(*pNumber);
  195. WTSFreeMemory(pNumber);
  196. return 0;
  197. }
  198. //////////////////////////////////////////////////////////////////////////////
  199. void KickMeOff(ULONG pNumber)
  200. {
  201. TCHAR szClientNumber[10];
  202. TCHAR szServerName[MAX_COMPUTERNAME_LENGTH + 1];
  203. DWORD pResponse = sizeof(szServerName) / sizeof(TCHAR) - 1;
  204. TCHAR pTitle[MAX_LEN];
  205. TCHAR pMessage[MAX_LEN];
  206. TCHAR szStringBuf[MAX_LEN];
  207. LPTSTR sz;
  208. LoadString (g_hInst, IDS_MSG_TITLE,
  209. pTitle, sizeof (pTitle));
  210. _itot(pNumber, szClientNumber, 10);
  211. GetComputerName(szServerName, &pResponse);
  212. _tcscpy(pMessage, ClientData.ClientAddress);
  213. LoadString (g_hInst, IDS_SPACE,
  214. szStringBuf, sizeof (szStringBuf));
  215. _tcscat(pMessage, szStringBuf);
  216. _tcscat(pMessage, ClientData.ClientName);
  217. _tcscat(pMessage, szStringBuf);
  218. // custom message
  219. if (CheckForRegKey(HKEY_USERS, szWinStaKey,
  220. KeyName[USE_MSG]))
  221. {
  222. sz = GetRegString(HKEY_USERS, szWinStaKey, KeyName[MSG]);
  223. if(sz)
  224. {
  225. _tcscat(pMessage, sz);
  226. sz = GetRegString(HKEY_USERS, szWinStaKey, KeyName[MSG_TITLE]);
  227. if(sz)
  228. {
  229. _tcscpy(pTitle, sz);
  230. }
  231. }
  232. }
  233. else
  234. {
  235. LoadString (g_hInst, IDS_DEFAULT1,
  236. szStringBuf, sizeof (szStringBuf));
  237. _tcscat(pMessage, szStringBuf);
  238. _tcscat(pMessage, szServerName);
  239. LoadString (g_hInst, IDS_DEFAULT2,
  240. szStringBuf, sizeof (szStringBuf));
  241. _tcscat(pMessage, szStringBuf);
  242. _tcscat(pMessage, szClientNumber);
  243. LoadString (g_hInst, IDS_DEFAULT3,
  244. szStringBuf, sizeof (szStringBuf));
  245. _tcscat(pMessage, szStringBuf);
  246. _tcscat(pMessage, szServerName);
  247. LoadString (g_hInst, IDS_DEFAULT4,
  248. szStringBuf, sizeof (szStringBuf));
  249. _tcscat(pMessage, szStringBuf);
  250. }
  251. WTSSendMessage(
  252. WTS_CURRENT_SERVER_HANDLE,
  253. GetCurrentLogonId(),
  254. pTitle,
  255. sizeof(pTitle),
  256. pMessage,
  257. sizeof(pMessage),
  258. MB_OK | MB_ICONSTOP,
  259. 30,
  260. &pResponse,
  261. TRUE);
  262. ExitProcess(0);
  263. }
  264. //////////////////////////////////////////////////////////////////////////////
  265. BOOL ParseNumberFromString(UINT i, TCHAR *szConstraints,
  266. ULONG pNumber)
  267. {
  268. int index;
  269. TCHAR szNumber[10];
  270. // parse a number out of the registry string
  271. index = 0;
  272. while (szConstraints[i+1] == 32) i++; //strip out any leading spaces
  273. while (szConstraints[i + 1] >= 48 &&
  274. szConstraints[i + 1] <= 57)
  275. {
  276. szNumber[index] = szConstraints[i + 1];
  277. i++;
  278. index++;
  279. }
  280. szNumber[index] = '\0';
  281. if (pNumber == (ULONG)_ttol(szNumber)) g_count++;
  282. // if there's more than one in the "equal" list,
  283. // execute the while loop again
  284. if (szConstraints[i+1] == ',')
  285. {
  286. i++;
  287. index = 0;
  288. for (int j = 0; j < 10; j++)
  289. szNumber[j] = '\0';
  290. ParseNumberFromString(i, szConstraints, pNumber);
  291. }
  292. // return TRUE if the user's build matches one in the registry.
  293. if (g_count > 0)
  294. {
  295. return TRUE;
  296. } else {
  297. return FALSE;
  298. }
  299. }
  300. //////////////////////////////////////////////////////////////////////////////
  301. BOOL ParseRangeFromString(UINT i, TCHAR *szConstraints,
  302. ULONG pNumber)
  303. {
  304. int index;
  305. TCHAR szNumber1[10];
  306. TCHAR szNumber2[10];
  307. // parse the first number out of the registry string
  308. index = 0;
  309. while (szConstraints[i + 1] >= 48 &&
  310. szConstraints[i + 1] <= 57)
  311. {
  312. szNumber1[index] = szConstraints[i + 1];
  313. i++;
  314. index++;
  315. }
  316. szNumber1[index] = '\0';
  317. // parse the second number out of the registry string
  318. i++; // increment past the : symbol
  319. index = 0;
  320. while (szConstraints[i+1] >= 48 &&
  321. szConstraints[i+1] <= 57)
  322. {
  323. szNumber2[index] = szConstraints[i+1];
  324. i++;
  325. index++;
  326. }
  327. szNumber2[index] = '\0';
  328. if (pNumber >= (ULONG)_ttol(szNumber1) &&
  329. pNumber <= (ULONG)_ttol(szNumber2)) g_count++;
  330. // return TRUE if the user's build is within our range.
  331. if (g_count > 0)
  332. {
  333. return TRUE;
  334. } else {
  335. return FALSE;
  336. }
  337. }
  338. //////////////////////////////////////////////////////////////////////////////
  339. BOOL GreaterThan(UINT i, TCHAR *szConstraints,
  340. ULONG pNumber)
  341. {
  342. int index;
  343. TCHAR szNumber[10];
  344. // parse a number out of the registry string
  345. index = 0;
  346. while (szConstraints[i + 1] >= 48 &&
  347. szConstraints[i + 1] <= 57)
  348. {
  349. szNumber[index] = szConstraints[i + 1];
  350. i++;
  351. index++;
  352. }
  353. szNumber[index] = '\0';
  354. if (pNumber > (ULONG)_ttol(szNumber)) g_count++;
  355. // return TRUE if the user's build matches one in the registry.
  356. if (g_count > 0)
  357. {
  358. return TRUE;
  359. } else {
  360. return FALSE;
  361. }
  362. }
  363. //////////////////////////////////////////////////////////////////////////////
  364. BOOL LessThan(UINT i, TCHAR *szConstraints,
  365. ULONG pNumber)
  366. {
  367. int index;
  368. TCHAR szNumber[10];
  369. // parse a number out of the registry string
  370. index = 0;
  371. while (szConstraints[i + 1] >= 48 &&
  372. szConstraints[i + 1] <= 57)
  373. {
  374. szNumber[index] = szConstraints[i + 1];
  375. i++;
  376. index++;
  377. }
  378. szNumber[index] = '\0';
  379. if (pNumber < (ULONG)_ttol(szNumber)) g_count++;
  380. // return TRUE if the user's build matches one in the registry.
  381. if (g_count > 0)
  382. {
  383. return TRUE;
  384. } else {
  385. return FALSE;
  386. }
  387. }
  388. //////////////////////////////////////////////////////////////////////////////