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.

473 lines
15 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999
  5. //
  6. // File: main.cpp
  7. //
  8. // Contents: Front end to license "needer"; lists TS licenses
  9. //
  10. // History: 06-05-99 t-BStern Created
  11. //
  12. //---------------------------------------------------------------------------
  13. // The goal here is to export
  14. // all [temporary] licenses [issued between <shortdate1> and <shortdate2>]
  15. // to a file [named <outFile>] [only from server[s] <S>]
  16. //
  17. // So possible command lines are:
  18. // lsls | lsls /T /D 1/1/99 2/2/00 /F outfile ls-server ls2 ls3
  19. #include "lsreport.h"
  20. #include "lsrepdef.h"
  21. #include <oleauto.h>
  22. // I found that ErrorPrintf didn't do %1-style formatting, so this does
  23. // complete formatting and stderr output. It is referenced by code in
  24. // lsreport.cpp, so if the program becomes GUI-based, ShowError needs to
  25. // maintain a presence.
  26. DWORD
  27. ShowError(
  28. IN DWORD dwStatus, // This is both the return value and the resource ID.
  29. IN INT_PTR *args, // Casted to va_list* and passed to FormatMessage.
  30. IN BOOL fSysError // Use the system message table (T) or the module (F)?
  31. ) {
  32. LPTSTR lpSysError;
  33. TCHAR szBuffer[TLS_ERROR_LENGTH];
  34. DWORD dwFlag = FORMAT_MESSAGE_FROM_SYSTEM;
  35. DWORD dwRet;
  36. if ((dwStatus == ERROR_FILE_NOT_FOUND) || !fSysError)
  37. {
  38. // We need to special-case File-not-Found because the system error
  39. // is insufficiently educational. FnF really means that the server
  40. // is not running TS.
  41. int retVal;
  42. retVal = LoadString(NULL, dwStatus, szBuffer, TLS_ERROR_LENGTH);
  43. if (!retVal)
  44. {
  45. // This is a more serious error.
  46. dwStatus = GetLastError();
  47. }
  48. else
  49. {
  50. dwFlag = FORMAT_MESSAGE_FROM_STRING;
  51. }
  52. }
  53. dwRet = FormatMessage(dwFlag |
  54. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  55. FORMAT_MESSAGE_ARGUMENT_ARRAY, // Tell FM to use INT_PTRs internally.
  56. szBuffer,
  57. dwStatus,
  58. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  59. (LPTSTR)&lpSysError,
  60. 0,
  61. (va_list *)args); // FormatMessage requires va_lists, even
  62. // if the arguments are flagged as being INT_PTRs.
  63. if ((dwRet != 0) && (lpSysError != NULL))
  64. {
  65. _fputts(lpSysError, stderr);
  66. LocalFree(lpSysError);
  67. }
  68. return dwStatus;
  69. }
  70. // Used only to enumerate the License Servers around, and thereby build a list
  71. // Used in EnumerateTlsServer()
  72. BOOL
  73. ServerEnumCallBack(
  74. IN TLS_HANDLE hHandle,
  75. IN LPCWSTR pszServerName,
  76. IN HANDLE dwUserData // Really a PServerHolder
  77. ) {
  78. LPWSTR *block;
  79. PServerHolder pSrvHold; // The casts get so hairy that I'll do this.
  80. pSrvHold = (PServerHolder)dwUserData;
  81. if ((hHandle != NULL) && (pSrvHold != NULL))
  82. {
  83. if (pSrvHold->pszNames == NULL)
  84. {
  85. // We need to allocate the names list for the first time.
  86. block = (LPWSTR *)LocalAlloc(LMEM_FIXED, sizeof (LPWSTR));
  87. } else {
  88. // The names list needs to get bigger.
  89. block = (LPWSTR *)LocalReAlloc(pSrvHold->pszNames,
  90. (1+pSrvHold->dwCount) * sizeof (LPWSTR),
  91. LMEM_MOVEABLE);
  92. }
  93. if (block != NULL)
  94. {
  95. // We can add a name to the list.
  96. pSrvHold->pszNames = block;
  97. pSrvHold->pszNames[pSrvHold->dwCount] = (LPWSTR)LocalAlloc(LMEM_FIXED, (_tcslen(pszServerName)+1)*sizeof(pszServerName[0]));
  98. if(pSrvHold->pszNames[pSrvHold->dwCount])
  99. {
  100. _tcscpy(pSrvHold->pszNames[pSrvHold->dwCount], pszServerName);
  101. pSrvHold->dwCount++;
  102. }
  103. }
  104. // It's okay if we have to stick with the names we already have.
  105. }
  106. return FALSE;
  107. }
  108. BOOL
  109. SortDates(
  110. PSYSTEMTIME pstStart,
  111. PSYSTEMTIME pstEnd)
  112. {
  113. BOOL fSwapped = FALSE;
  114. FILETIME ftStart, ftEnd;
  115. SYSTEMTIME stHolder;
  116. SystemTimeToFileTime(pstStart, &ftStart);
  117. SystemTimeToFileTime(pstEnd, &ftEnd);
  118. if ((ftStart.dwHighDateTime > ftEnd.dwHighDateTime) ||
  119. ((ftStart.dwHighDateTime == ftEnd.dwHighDateTime) &&
  120. (ftStart.dwLowDateTime > ftEnd.dwLowDateTime)))
  121. {
  122. // We need to swap.
  123. stHolder.wYear = pstStart->wYear;
  124. stHolder.wMonth = pstStart->wMonth;
  125. stHolder.wDay = pstStart->wDay;
  126. pstStart->wYear = pstEnd->wYear;
  127. pstStart->wMonth = pstEnd->wMonth;
  128. pstStart->wDay = pstEnd->wDay;
  129. pstEnd->wYear = stHolder.wYear;
  130. pstEnd->wMonth = stHolder.wMonth;
  131. pstEnd->wDay = stHolder.wDay;
  132. fSwapped = TRUE;
  133. }
  134. return fSwapped;
  135. }
  136. // All that wmain needs to do is parse the command line and
  137. // therefore collect a list of machines to connect to, along with
  138. // any options passed, and open & close the (possibly command-line
  139. // specified) output file.
  140. extern "C" int _cdecl
  141. wmain(
  142. int argc,
  143. WCHAR *argv[]
  144. ) {
  145. // These represent which command-line options were chosen.
  146. BOOL fTempOnly = FALSE;
  147. BOOL fError = FALSE;
  148. BOOL fDateSpec = FALSE;
  149. BOOL fHwid = FALSE;
  150. DWORD dwStatus;
  151. DWORD dwSrvLoc; // This is a bitfield.
  152. ServerHolder srvHold; // This holds all the servers.
  153. // These are for parsing the command-line-specified date(s).
  154. DATE startDate;
  155. DATE endDate;
  156. UDATE usDate;
  157. UDATE ueDate;
  158. // Basic file I/O.
  159. TCHAR ofName[MAX_PATH+1] = { 0 };
  160. FILE *outFile;
  161. int i;
  162. INT_PTR arg; // All of my strings have at most 1 parm.
  163. dwSrvLoc = 0;
  164. srvHold.dwCount = 0;
  165. srvHold.pszNames = NULL;
  166. if (!(LoadString(NULL, IDS_DEFAULT_FILE, ofName, MAX_PATH) &&
  167. InitLSReportStrings()))
  168. {
  169. return ShowError(GetLastError(), NULL, TRUE);
  170. }
  171. for (i = 1; (i < argc) && !fError; i++) {
  172. if ((argv[i][0] == '-') || (argv[i][0] == '/'))
  173. {
  174. switch (argv[i][1]) {
  175. case 'F': case 'f': // format: /F [path\]filename
  176. if (i+1 == argc)
  177. {
  178. // They didn't include enough parameters.
  179. fError = TRUE;
  180. } else {
  181. i++;
  182. _tcsncpy(ofName, argv[i], MAX_PATH);
  183. }
  184. break;
  185. case 'D': case 'd': // format: /D startdate [enddate]
  186. // Do a lot of date manipulation.
  187. if (i+1 == argc)
  188. {
  189. fError = TRUE;
  190. }
  191. else
  192. {
  193. i++;
  194. dwStatus = VarDateFromStr(argv[i],
  195. LOCALE_USER_DEFAULT,
  196. VAR_DATEVALUEONLY,
  197. &startDate);
  198. if (dwStatus != S_OK)
  199. {
  200. // The date couldn't get converted.
  201. ShowError(dwStatus, NULL, TRUE);
  202. fError = TRUE;
  203. break;
  204. }
  205. if (VarUdateFromDate(startDate, 0, &usDate) != S_OK)
  206. {
  207. // We don't want to set error, because the user can't
  208. // fix this with command line syntax. We're out of
  209. // memory or something. ABEND.
  210. return ShowError(GetLastError(), NULL, TRUE);
  211. }
  212. i++;
  213. if (i < argc)
  214. {
  215. dwStatus = VarDateFromStr(argv[i],
  216. LOCALE_USER_DEFAULT,
  217. VAR_DATEVALUEONLY,
  218. &endDate);
  219. if (dwStatus != S_OK)
  220. {
  221. ShowError(dwStatus, NULL, TRUE);
  222. fError = TRUE;
  223. break;
  224. }
  225. if (VarUdateFromDate(endDate, 0, &ueDate) != S_OK)
  226. {
  227. return ShowError(GetLastError(), NULL, TRUE);
  228. }
  229. }
  230. else
  231. {
  232. // We have to use today's date, because they didn't
  233. // give us an EndDate.
  234. GetSystemTime(&ueDate.st); // Fill in the SystemTime.
  235. }
  236. // Check if the dates are in the right order.
  237. // If the user gives us only /D 1/1/2022 and it is 1999, I
  238. // choose not to have a fit and die.
  239. SortDates(&usDate.st, &ueDate.st);
  240. fDateSpec = TRUE;
  241. }
  242. break;
  243. case 'T': case 't': // Format: /T
  244. fTempOnly = TRUE;
  245. break;
  246. case 'W': case 'w':
  247. fHwid = TRUE;
  248. break;
  249. // case '?': case 'H': case 'h': // Format: /?
  250. default: // Let the default get this, since it'll work the same.
  251. // This'll show syntax help.
  252. fError = TRUE;
  253. break;
  254. } // switch
  255. }
  256. else
  257. {
  258. // It wasn't -T or /F or something.
  259. // It must be a server name, since it's not anything else.
  260. dwSrvLoc |= (1 << i); // Tag this is as a server name.
  261. srvHold.dwCount++;
  262. }
  263. } // argc loop
  264. if (fError)
  265. {
  266. ShowError(IDS_HELP_USAGE1, NULL, FALSE);
  267. // Set the exe name:
  268. arg = (INT_PTR)argv[0];
  269. ShowError(IDS_HELP_USAGE2, &arg, FALSE);
  270. ShowError(IDS_HELP_USAGE3, NULL, FALSE);
  271. ShowError(IDS_HELP_USAGE4, NULL, FALSE);
  272. ShowError(IDS_HELP_USAGE5, NULL, FALSE);
  273. ShowError(IDS_HELP_USAGE6, NULL, FALSE);
  274. ShowError(IDS_HELP_USAGE7, NULL, FALSE);
  275. ShowError(IDS_HELP_USAGE14, NULL, FALSE);
  276. ShowError(IDS_HELP_USAGE8, NULL, FALSE);
  277. ShowError(IDS_HELP_USAGE9, NULL, FALSE);
  278. ShowError(IDS_HELP_USAGE10, NULL, FALSE);
  279. ShowError(IDS_HELP_USAGE11, NULL, FALSE);
  280. ShowError(IDS_HELP_USAGE12, &arg, FALSE);
  281. ShowError(IDS_HELP_USAGE13, &arg, FALSE);
  282. return ERROR_BAD_SYNTAX;
  283. }
  284. outFile = _tfopen(ofName, _T("w"));
  285. if (outFile == NULL)
  286. {
  287. // This is an extra level of indirection for FormatMessage.
  288. arg = (INT_PTR)ofName;
  289. ShowError(IDS_NO_FOPEN, &arg, FALSE);
  290. return ShowError(GetLastError(), NULL, TRUE);
  291. }
  292. TLSInit();
  293. if (dwSrvLoc)
  294. {
  295. int holder;
  296. srvHold.pszNames = (LPWSTR *)LocalAlloc(LMEM_FIXED,
  297. srvHold.dwCount * sizeof (LPWSTR *));
  298. if (srvHold.pszNames == NULL)
  299. {
  300. dwStatus = ShowError(GetLastError(), NULL, TRUE);
  301. goto done;
  302. }
  303. holder = 0;
  304. for (i = 1; i < argc; i++) { // argc (less one) == max # of servers.
  305. if (dwSrvLoc & (1 << i)) {
  306. srvHold.pszNames[holder] = (LPWSTR)LocalAlloc(LMEM_FIXED, (_tcslen(argv[i])+1)*sizeof(argv[i][0]));
  307. if(srvHold.pszNames[holder])
  308. {
  309. _tcscpy(srvHold.pszNames[holder], argv[i]);
  310. }
  311. holder++;
  312. }
  313. }
  314. }
  315. else
  316. {
  317. // We need to collect a list of servers.
  318. LPTSTR *pszEntSrvNames;
  319. DWORD dwEntSrvNum;
  320. HRESULT hrEntResult;
  321. dwStatus = EnumerateTlsServer(
  322. ServerEnumCallBack,
  323. (LPVOID)&srvHold,
  324. 3000, // seems a good timeout
  325. FALSE);
  326. hrEntResult = GetAllEnterpriseServers(&pszEntSrvNames, &dwEntSrvNum);
  327. if (SUCCEEDED(hrEntResult))
  328. {
  329. DWORD j, k;
  330. BOOL fFound;
  331. for (k = 0; k < dwEntSrvNum; k++) {
  332. fFound = FALSE;
  333. for (j = 0; j < srvHold.dwCount; j++) {
  334. if (!_tcscmp(srvHold.pszNames[j], pszEntSrvNames[k]))
  335. {
  336. fFound = TRUE;
  337. break;
  338. }
  339. }
  340. if (!fFound)
  341. {
  342. // This is a new name.
  343. LPTSTR *block;
  344. if (srvHold.pszNames == NULL)
  345. {
  346. // We have to allocate names for the first time.
  347. block = (LPTSTR *)LocalAlloc(LMEM_FIXED, sizeof (LPTSTR));
  348. }
  349. else
  350. {
  351. // Try to increase the array.
  352. block = (LPTSTR *)LocalReAlloc(srvHold.pszNames,
  353. (1+srvHold.dwCount) * sizeof (LPTSTR),
  354. LMEM_MOVEABLE);
  355. }
  356. if (block != NULL)
  357. {
  358. // We can add a name to the list.
  359. srvHold.pszNames = block;
  360. srvHold.pszNames[srvHold.dwCount] = pszEntSrvNames[k];
  361. srvHold.dwCount++;
  362. }
  363. else
  364. {
  365. // If we can't copy it into our array, we should drop it.
  366. LocalFree(pszEntSrvNames[k]);
  367. }
  368. // End need to add name
  369. }
  370. // End loop through existing servers
  371. }
  372. // We've removed all of the names from this one way or the other.
  373. LocalFree(pszEntSrvNames);
  374. // End <GetEntSrv worked>
  375. }
  376. // Autodiscovery complete.
  377. }
  378. if (srvHold.dwCount)
  379. {
  380. dwStatus = ExportLicenses(
  381. outFile,
  382. &srvHold,
  383. fTempOnly,
  384. &usDate.st,
  385. &ueDate.st,
  386. fDateSpec,
  387. fHwid);
  388. while (srvHold.dwCount){
  389. LocalFree(srvHold.pszNames[--srvHold.dwCount]);
  390. }
  391. LocalFree(srvHold.pszNames);
  392. }
  393. else
  394. {
  395. arg = (INT_PTR)argv[0];
  396. ShowError(IDS_NO_SERVERS, &arg, FALSE);
  397. dwStatus = ERROR_NO_SERVERS;
  398. }
  399. done:
  400. fclose(outFile);
  401. return dwStatus;
  402. }