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.

678 lines
17 KiB

  1. ////////////////////////////////////////////////////////////////
  2. //
  3. // Refgp.cxx
  4. //
  5. // Refresh Group Policy exe
  6. //
  7. //
  8. ////////////////////////////////////////////////////////////////
  9. #include "refgp.h"
  10. #define USER_POLICY_APPLIED_EVENT TEXT("userenv: User Group Policy has been applied")
  11. #define MACHINE_POLICY_APPLIED_EVENT TEXT("Global\\userenv: Machine Group Policy has been applied")
  12. #define USER_POLICY_DONE_EVENT TEXT("userenv: User Group Policy Processing is done")
  13. #define MACHINE_POLICY_DONE_EVENT TEXT("Global\\userenv: Machine Group Policy Processing is done")
  14. #define USER_POLICY_REFRESH_NEEDFG_EVENT TEXT("userenv: User Group Policy ForcedRefresh Needs Foreground Processing")
  15. #define MACHINE_POLICY_REFRESH_NEEDFG_EVENT TEXT("Global\\userenv: Machine Group Policy ForcedRefresh Needs Foreground Processing")
  16. #define REFRESH_MACHINE 1
  17. #define REFRESH_USER 2
  18. HINSTANCE hInst;
  19. typedef enum _FAILSTATES {
  20. NO_FAILURE,
  21. REFRESH_FAILED,
  22. POLWAIT_FAILED,
  23. POLWAIT_TIMEDOUT
  24. } FAILSTATES;
  25. typedef struct _REFSTRUCT {
  26. BOOL bMachine;
  27. DWORD dwOption;
  28. DWORD dwTimeOut;
  29. DWORD dwError;
  30. FAILSTATES fState;
  31. BOOL bFGNeeded;
  32. } REFSTRUCT, *LPREFSTRUCT;
  33. REFSTRUCT refMach;
  34. REFSTRUCT refUser;
  35. WCHAR szUser[200];
  36. WCHAR szMach[200];
  37. WCHAR szErr[MAX_PATH*2];
  38. // Process arg. checks whether argument is present
  39. BOOL ProcessArg(int *pargc, LPWSTR **pargv, DWORD dwStringId, BOOL *bValue)
  40. {
  41. WCHAR szStr[200];
  42. LPWSTR *argv = *pargv;
  43. if (*pargc == 0)
  44. return TRUE;
  45. if (!LoadString (hInst, dwStringId, szStr, 200)) {
  46. return FALSE;
  47. }
  48. for (; (*argv); *argv++) {
  49. if (_wcsicmp(*argv, szStr) == 0) {
  50. *bValue = TRUE;
  51. (*pargc)--;
  52. return TRUE;
  53. }
  54. }
  55. return TRUE;
  56. }
  57. // Process arg. checks whether argument is present and what the value is after the ":" in string format
  58. BOOL ProcessArg(int *pargc, WCHAR ***pargv, DWORD dwStringId, WCHAR **szValue)
  59. {
  60. WCHAR szStr[200];
  61. LPWSTR *argv = *pargv, szJunk=NULL;
  62. if (*pargc == 0)
  63. return TRUE;
  64. if (!LoadString (hInst, dwStringId, szStr, 200)) {
  65. return FALSE;
  66. }
  67. for (; (*argv); *argv++) {
  68. if (_wcsnicmp(*argv, szStr, lstrlen(szStr)) == 0) {
  69. *szValue = (*argv)+lstrlen(szStr);
  70. (*pargc)--;
  71. return TRUE;
  72. }
  73. }
  74. *szValue = NULL;
  75. return TRUE;
  76. }
  77. // Process arg. checks whether argument is present and what the value is after the ":" in long format
  78. BOOL ProcessArg(int *pargc, WCHAR ***pargv, DWORD dwStringId, long *plValue)
  79. {
  80. WCHAR szStr[200];
  81. LPWSTR *argv = *pargv, szJunk=NULL;
  82. if (*pargc == 0)
  83. return TRUE;
  84. if (!LoadString (hInst, dwStringId, szStr, 200)) {
  85. return FALSE;
  86. }
  87. for (; (*argv); *argv++) {
  88. if (_wcsnicmp(*argv, szStr, lstrlen(szStr)) == 0) {
  89. *plValue = wcstol((*argv)+lstrlen(szStr), &szJunk, 10);
  90. (*pargc)--;
  91. return TRUE;
  92. }
  93. }
  94. return TRUE;
  95. }
  96. BOOL CompareOptions(WCHAR *szValue, DWORD dwOptionId)
  97. {
  98. WCHAR szStr[200];
  99. if (!szValue)
  100. return FALSE;
  101. if (!LoadString (hInst, dwOptionId, szStr, 200)) {
  102. return FALSE;
  103. }
  104. if (_wcsicmp(szValue, szStr) == 0)
  105. return TRUE;
  106. return FALSE;
  107. }
  108. BOOL GetValue(WCHAR *szValue, DWORD dwOptionId)
  109. {
  110. if (!LoadString (hInst, dwOptionId, szValue, 200)) {
  111. return FALSE;
  112. }
  113. return TRUE;
  114. }
  115. void PrintMsg(DWORD dwMsgId, ...)
  116. {
  117. WCHAR szFmt[200];
  118. WCHAR szMsg[200];
  119. va_list marker;
  120. if (!LoadString (hInst, dwMsgId, szFmt, 200)) {
  121. return;
  122. }
  123. va_start(marker, dwMsgId);
  124. wvnsprintf(szMsg, 200, szFmt, marker);
  125. va_end(marker);
  126. wprintf(szMsg);
  127. return;
  128. }
  129. void PrintUsage()
  130. {
  131. for (DWORD dwMsgId = IDS_USAGE_FIRST; dwMsgId <= IDS_USAGE_LAST; dwMsgId++) {
  132. PrintMsg(dwMsgId);
  133. }
  134. return;
  135. }
  136. BOOL PromptUserForFG(BOOL bMachine)
  137. {
  138. WCHAR tTemp, tChar;
  139. WCHAR Yes[20], No[20];
  140. if (!LoadString (hInst, IDS_YES, Yes, 20)) {
  141. return FALSE; // safe
  142. }
  143. if (!LoadString (hInst, IDS_NO, No, 20)) {
  144. return FALSE; // safe
  145. }
  146. for (;;) {
  147. if (bMachine)
  148. PrintMsg(IDS_PROMPT_REBOOT);
  149. else
  150. PrintMsg(IDS_PROMPT_LOGOFF);
  151. tChar = getwchar();
  152. tTemp = tChar;
  153. while (tTemp != TEXT('\n')) {
  154. tTemp = getwchar();
  155. }
  156. if (towupper(tChar) == towupper(Yes[0]))
  157. return TRUE;
  158. if (towupper(tChar) == towupper(No[0]))
  159. return FALSE;
  160. }
  161. return FALSE;
  162. }
  163. //***************************************************************************
  164. //
  165. // GetErrString
  166. //
  167. // Purpose: Calls FormatMessage to Get the error string corresp. to a error
  168. // code
  169. //
  170. //
  171. // Parameters: dwErr - Error Code
  172. // szErr - Buffer to return the error string (MAX_PATH)
  173. // is assumed.!!!
  174. //
  175. // Return: szErr
  176. //
  177. //***************************************************************************
  178. LPTSTR GetErrString(DWORD dwErr, LPTSTR szErr)
  179. {
  180. szErr[0] = TEXT('\0');
  181. FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,
  182. NULL, dwErr,
  183. MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
  184. szErr, MAX_PATH, NULL);
  185. return szErr;
  186. }
  187. void RefreshPolicyAndWait(LPREFSTRUCT lpRef)
  188. {
  189. HANDLE hNotifyEvent=NULL, hFGProcessingEvent=NULL;
  190. DWORD dwRet=0;
  191. lpRef->fState = REFRESH_FAILED;
  192. lpRef->dwError = E_FAIL;
  193. lpRef->bFGNeeded = FALSE;
  194. if (!RefreshPolicyEx(lpRef->bMachine, lpRef->dwOption)) {
  195. lpRef->fState = REFRESH_FAILED;
  196. lpRef->dwError = GetLastError();
  197. goto Exit;
  198. }
  199. if (lpRef->dwTimeOut != 0) {
  200. lpRef->fState = POLWAIT_FAILED;
  201. lpRef->dwError = E_FAIL;
  202. hNotifyEvent = OpenEvent(SYNCHRONIZE, FALSE, lpRef->bMachine ? MACHINE_POLICY_DONE_EVENT : USER_POLICY_DONE_EVENT );
  203. if (!hNotifyEvent) {
  204. lpRef->fState = POLWAIT_FAILED;
  205. lpRef->dwError = GetLastError();
  206. goto Exit;
  207. }
  208. hFGProcessingEvent = OpenEvent(SYNCHRONIZE, FALSE, lpRef->bMachine ? MACHINE_POLICY_REFRESH_NEEDFG_EVENT : USER_POLICY_REFRESH_NEEDFG_EVENT);
  209. if (!hNotifyEvent) {
  210. lpRef->fState = POLWAIT_FAILED;
  211. lpRef->dwError = GetLastError();
  212. goto Exit;
  213. }
  214. dwRet = WaitForSingleObject(hNotifyEvent, (lpRef->dwTimeOut == INFINITE) ? INFINITE : 1000*(lpRef->dwTimeOut));
  215. if (dwRet == WAIT_FAILED) {
  216. lpRef->fState = POLWAIT_FAILED;
  217. lpRef->dwError = GetLastError();
  218. goto Exit;
  219. }
  220. else if (dwRet == WAIT_ABANDONED) {
  221. lpRef->fState = POLWAIT_FAILED;
  222. lpRef->dwError = E_UNEXPECTED;
  223. goto Exit;
  224. }
  225. else if (dwRet == WAIT_TIMEOUT) {
  226. lpRef->fState = POLWAIT_TIMEDOUT;
  227. lpRef->dwError = 0;
  228. goto Exit;
  229. }
  230. lpRef->bFGNeeded = (lpRef->dwOption == RP_FORCE) && (WaitForSingleObject(hFGProcessingEvent, 0) == WAIT_OBJECT_0);
  231. }
  232. lpRef->fState = NO_FAILURE;
  233. Exit:
  234. if (hNotifyEvent)
  235. CloseHandle(hNotifyEvent);
  236. if (hFGProcessingEvent)
  237. CloseHandle(hFGProcessingEvent);
  238. return;
  239. }
  240. void PrintRefreshError(LPREFSTRUCT lpRef)
  241. {
  242. LPWSTR szTarget = (lpRef->bMachine) ? szMach: szUser;
  243. switch (lpRef->fState) {
  244. case REFRESH_FAILED:
  245. PrintMsg(IDS_REFRESH_FAILED, szTarget, GetErrString(lpRef->dwError, szErr));
  246. break;
  247. case POLWAIT_FAILED:
  248. PrintMsg(IDS_POLWAIT_FAILED, szTarget, GetErrString(lpRef->dwError, szErr));
  249. break;
  250. case POLWAIT_TIMEDOUT:
  251. PrintMsg(IDS_POLWAIT_TIMEDOUT, szTarget);
  252. case NO_FAILURE:
  253. if (lpRef->dwTimeOut == 0)
  254. PrintMsg(IDS_REFRESH_BACKGND_TRIGGERED, szTarget);
  255. else
  256. PrintMsg(IDS_REFRESH_BACKGND_SUCCESS, szTarget);
  257. break;
  258. default:
  259. break;
  260. }
  261. }
  262. void __cdecl main (int argc, char **argv)
  263. {
  264. DWORD uTarget=0;
  265. BOOL bArgValid = TRUE;
  266. LONG lTime = 600;
  267. DWORD dwTime = 600, dwRet = 0, dwOption = 0, dwThread = 0;
  268. HANDLE hNotifyEvent=NULL, hFGProcessingEvent=NULL, hToken = NULL;
  269. BOOL bNeedFG = FALSE;
  270. LPWSTR lpCommandLine=0, szTarget=0;
  271. int wargc=0;
  272. LPWSTR *wargv=NULL, *wargv1=NULL;
  273. BOOL bForce=FALSE, bOkToLogoff=FALSE, bOkToBoot=FALSE, bNextFgSync = FALSE;
  274. BOOL bNeedBoot = FALSE, bNeedLogoff = FALSE;
  275. BOOL bError = FALSE;
  276. HANDLE hThreads[2] = {0, 0};
  277. setlocale( LC_ALL, ".OCP" );
  278. SetThreadUILanguage(0);
  279. lpCommandLine = GetCommandLine();
  280. wargv1 = CommandLineToArgvW(lpCommandLine, &wargc);
  281. wargv = (LPWSTR *)LocalAlloc(LPTR, (1+wargc)*sizeof(LPWSTR));
  282. if (!wargv) {
  283. PrintMsg(IDS_OUT_OF_MEMORY);
  284. goto Exit;
  285. }
  286. memcpy(wargv, wargv1, wargc*sizeof(LPWSTR));
  287. hInst = GetModuleHandle(wargv[0]);
  288. if ((!GetValue(szUser, IDS_USER)) || (!GetValue(szMach, IDS_MACHINE))) {
  289. // we cannot read the resource strings. no point continuing
  290. return;
  291. }
  292. //
  293. // Ignore the first argument
  294. //
  295. wargc--;
  296. wargv++;
  297. //
  298. // Get the args
  299. //
  300. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_TARGET, &szTarget);
  301. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_TIME, &lTime);
  302. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_FORCE, &bForce);
  303. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_LOGOFF, &bOkToLogoff);
  304. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_BOOT, &bOkToBoot);
  305. bArgValid = bArgValid && ProcessArg(&wargc, &wargv, IDS_SYNC, &bNextFgSync);
  306. bArgValid = bArgValid && (wargc == 0);
  307. //
  308. // Get the target correctly
  309. //
  310. uTarget = 0;
  311. if (bArgValid ) {
  312. if (!szTarget) {
  313. uTarget |= REFRESH_MACHINE;
  314. uTarget |= REFRESH_USER;
  315. }
  316. else if ( CompareOptions(szTarget, IDS_MACHINE) )
  317. uTarget |= REFRESH_MACHINE;
  318. else if ( CompareOptions(szTarget, IDS_USER) )
  319. uTarget |= REFRESH_USER;
  320. else {
  321. bArgValid = FALSE;
  322. }
  323. }
  324. //
  325. // Get the options correctly
  326. //
  327. if (bArgValid) {
  328. if ( bForce )
  329. dwOption = RP_FORCE;
  330. else
  331. dwOption = 0;
  332. }
  333. if (lTime == -1)
  334. dwTime = INFINITE;
  335. else
  336. dwTime = lTime;
  337. if (!bArgValid) {
  338. PrintUsage();
  339. goto Exit;
  340. }
  341. if (bOkToBoot)
  342. bOkToLogoff = TRUE;
  343. if (bNextFgSync) {
  344. if (uTarget & REFRESH_MACHINE) {
  345. dwRet = ForceSyncFgPolicy( 0 );
  346. if (dwRet != ERROR_SUCCESS) {
  347. PrintMsg(IDS_SET_MODE_FAILED, GetErrString(dwRet, szErr));
  348. goto Exit;
  349. }
  350. }
  351. if (uTarget & REFRESH_USER) {
  352. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
  353. PrintMsg(IDS_SET_MODE_FAILED, GetErrString(GetLastError(), szErr));
  354. goto Exit;
  355. }
  356. LPWSTR szSid = GetSidString( hToken );
  357. if (!szSid) {
  358. PrintMsg(IDS_SET_MODE_FAILED, GetErrString(GetLastError(), szErr));
  359. goto Exit;
  360. }
  361. dwRet = ForceSyncFgPolicy( szSid );
  362. if (dwRet != ERROR_SUCCESS) {
  363. LocalFree (szSid);
  364. PrintMsg(IDS_SET_MODE_FAILED, GetErrString(dwRet, szErr));
  365. goto Exit;
  366. }
  367. LocalFree (szSid);
  368. CloseHandle (hToken);
  369. hToken = 0;
  370. }
  371. }
  372. else {
  373. if (uTarget & REFRESH_MACHINE) {
  374. refMach.bMachine = TRUE;
  375. refMach.dwOption = dwOption;
  376. refMach.dwTimeOut = dwTime;
  377. if ((hThreads[dwThread] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RefreshPolicyAndWait, &refMach, 0, 0)) == NULL) {
  378. PrintMsg(IDS_REFRESH_POLICY_FAILED, GetErrString(GetLastError(), szErr));
  379. goto Exit;
  380. }
  381. dwThread++;
  382. }
  383. if (uTarget & REFRESH_USER) {
  384. refUser.bMachine = FALSE;
  385. refUser.dwOption = dwOption;
  386. refUser.dwTimeOut = dwTime;
  387. if ((hThreads[dwThread] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)RefreshPolicyAndWait, &refUser, 0, 0)) == NULL) {
  388. PrintMsg(IDS_REFRESH_POLICY_FAILED, GetErrString(GetLastError(), szErr));
  389. goto Exit;
  390. }
  391. dwThread++;
  392. }
  393. PrintMsg(IDS_REFRESH_LAUNCHED);
  394. dwRet = WaitForMultipleObjects(dwThread, hThreads, TRUE, INFINITE);
  395. if ((dwRet != WAIT_OBJECT_0) && (dwRet != (WAIT_OBJECT_0 + 1))) {
  396. // our threads didn't terminate properly..
  397. PrintMsg(IDS_REFRESH_POLICY_FAILED, GetErrString(GetLastError(), szErr));
  398. goto Exit;
  399. }
  400. if (uTarget & REFRESH_USER) {
  401. PrintRefreshError(&refUser);
  402. if (refUser.fState != NO_FAILURE)
  403. bError = TRUE;
  404. }
  405. if (uTarget & REFRESH_MACHINE) {
  406. PrintRefreshError(&refMach);
  407. if (refMach.fState != NO_FAILURE)
  408. bError = TRUE;
  409. }
  410. if (bError) {
  411. goto Exit;
  412. }
  413. }
  414. PrintMsg(IDS_SPACE);
  415. if ((uTarget & REFRESH_USER) && (bNextFgSync || refUser.bFGNeeded)) {
  416. if ( bNextFgSync )
  417. PrintMsg(IDS_NEED_LOGOFF_SYNC);
  418. else
  419. PrintMsg(IDS_NEED_LOGOFF);
  420. bNeedLogoff = TRUE;
  421. }
  422. if ((uTarget & REFRESH_MACHINE) && (bNextFgSync || refMach.bFGNeeded)) {
  423. if ( bNextFgSync )
  424. PrintMsg(IDS_NEED_REBOOT_SYNC);
  425. else
  426. PrintMsg(IDS_NEED_REBOOT);
  427. bNeedBoot = TRUE;
  428. }
  429. if ( !bNeedBoot && !bNeedLogoff) {
  430. goto Exit;
  431. }
  432. PrintMsg(IDS_SPACE);
  433. if (bNeedBoot && !bOkToBoot) {
  434. bOkToBoot = PromptUserForFG(TRUE);
  435. }
  436. if (bNeedBoot && bOkToBoot) {
  437. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
  438. PrintMsg(IDS_COULDNT_REBOOT, GetErrString(GetLastError(), szErr));
  439. goto Exit;
  440. }
  441. BYTE bytesTokenPrivNew[sizeof(DWORD)+sizeof(LUID_AND_ATTRIBUTES)];
  442. PTOKEN_PRIVILEGES pTokenPrivNew = (PTOKEN_PRIVILEGES)bytesTokenPrivNew;
  443. BYTE bytesTokenPrivOld[sizeof(DWORD)+sizeof(LUID_AND_ATTRIBUTES)];
  444. PTOKEN_PRIVILEGES pTokenPrivOld = (PTOKEN_PRIVILEGES)bytesTokenPrivOld;
  445. DWORD dwSize=sizeof(DWORD)+sizeof(LUID_AND_ATTRIBUTES);
  446. DWORD dwRetSize=0;
  447. pTokenPrivNew->PrivilegeCount = 1;
  448. pTokenPrivNew->Privileges->Attributes = SE_PRIVILEGE_ENABLED;
  449. if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &(pTokenPrivNew->Privileges->Luid))) {
  450. PrintMsg(IDS_COULDNT_REBOOT, GetErrString(GetLastError(), szErr));
  451. goto Exit;
  452. }
  453. if (!AdjustTokenPrivileges(hToken, FALSE, pTokenPrivNew, dwSize, pTokenPrivOld, &dwRetSize)) {
  454. PrintMsg(IDS_COULDNT_REBOOT, GetErrString(GetLastError(), szErr));
  455. goto Exit;
  456. }
  457. PrintMsg(IDS_NOTIFY_MACHINE_FG);
  458. if (!ExitWindowsEx(EWX_REBOOT, 0)) {
  459. PrintMsg(IDS_COULDNT_REBOOT, GetErrString(GetLastError(), szErr));
  460. }
  461. else {
  462. PrintMsg(IDS_REBOOTING);
  463. }
  464. if (!AdjustTokenPrivileges(hToken, FALSE, pTokenPrivOld, 0, NULL, 0)) {
  465. PrintMsg(IDS_COULDNT_REBOOT, GetErrString(GetLastError(), szErr));
  466. goto Exit;
  467. }
  468. // if we are rebooting no need to call logoff code
  469. goto Exit;
  470. }
  471. if (bNeedLogoff && !bOkToLogoff) {
  472. bOkToLogoff = PromptUserForFG(FALSE);
  473. }
  474. if (bNeedLogoff && bOkToLogoff) {
  475. PrintMsg(IDS_NOTIFY_USER_FG);
  476. if (!ExitWindowsEx(EWX_LOGOFF, 0)) {
  477. PrintMsg(IDS_COULDNT_LOGOFF, GetErrString(GetLastError(), szErr));
  478. }
  479. else {
  480. PrintMsg(IDS_LOGGING_OFF);
  481. }
  482. }
  483. Exit:
  484. if (hToken)
  485. CloseHandle(hToken);
  486. for (;dwThread;dwThread--)
  487. if (hThreads[dwThread-1]) {
  488. CloseHandle(hThreads[dwThread-1]);
  489. }
  490. if (wargv1)
  491. GlobalFree(wargv1);
  492. if (wargv)
  493. LocalFree(wargv);
  494. return;
  495. }