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.

707 lines
18 KiB

  1. #include <nt.h>
  2. #include <ntrtl.h>
  3. #include <nturtl.h>
  4. #include <windows.h>
  5. #include <shellapi.h>
  6. #include "SmartPtr.h"
  7. #include "strings.h"
  8. #include <strsafe.h>
  9. extern "C"
  10. {
  11. BOOL PrependToPath( LPWSTR, LPWSTR*);
  12. void PathUnquoteSpaces( LPWSTR );
  13. void UpdateUserEnvironment();
  14. LPWSTR GetSidString( HANDLE UserToken );
  15. void DeleteSidString( LPWSTR SidString );
  16. };
  17. #define GPO_SCRIPTS_KEY L"Software\\Policies\\Microsoft\\Windows\\System\\Scripts"
  18. #define GP_STATE_KEY L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\State"
  19. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  20. #define SCRIPT L"Script"
  21. #define PARAMETERS L"Parameters"
  22. #define EXECTIME L"ExecTime"
  23. #define GPOID L"GPO-ID"
  24. #define SOMID L"SOM-ID"
  25. #define FILESYSPATH L"FileSysPath"
  26. #define SCR_STARTUP L"Startup"
  27. #define SCR_SHUTDOWN L"Shutdown"
  28. #define SCR_LOGON L"Logon"
  29. #define SCR_LOGOFF L"Logoff"
  30. LPTSTR
  31. CheckSlash (LPTSTR lpDir)
  32. {
  33. LPTSTR lpEnd;
  34. lpEnd = lpDir + lstrlen(lpDir);
  35. if (*(lpEnd - 1) != TEXT('\\')) {
  36. *lpEnd = TEXT('\\');
  37. lpEnd++;
  38. *lpEnd = TEXT('\0');
  39. }
  40. return lpEnd;
  41. }
  42. PSID
  43. GetUserSid( HANDLE UserToken )
  44. {
  45. PTOKEN_USER pUser, pTemp;
  46. PSID pSid;
  47. DWORD BytesRequired = 200;
  48. NTSTATUS status;
  49. //
  50. // Allocate space for the user info
  51. //
  52. pUser = (PTOKEN_USER)LocalAlloc(LMEM_FIXED, BytesRequired);
  53. if ( pUser == NULL )
  54. {
  55. return NULL;
  56. }
  57. //
  58. // Read in the UserInfo
  59. //
  60. status = NtQueryInformationToken(
  61. UserToken, // Handle
  62. TokenUser, // TokenInformationClass
  63. pUser, // TokenInformation
  64. BytesRequired, // TokenInformationLength
  65. &BytesRequired // ReturnLength
  66. );
  67. if ( status == STATUS_BUFFER_TOO_SMALL )
  68. {
  69. //
  70. // Allocate a bigger buffer and try again.
  71. //
  72. pTemp = (PTOKEN_USER)LocalReAlloc(pUser, BytesRequired, LMEM_MOVEABLE);
  73. if ( pTemp == NULL )
  74. {
  75. LocalFree (pUser);
  76. return NULL;
  77. }
  78. pUser = pTemp;
  79. status = NtQueryInformationToken(
  80. UserToken, // Handle
  81. TokenUser, // TokenInformationClass
  82. pUser, // TokenInformation
  83. BytesRequired, // TokenInformationLength
  84. &BytesRequired // ReturnLength
  85. );
  86. }
  87. if ( !NT_SUCCESS(status) )
  88. {
  89. LocalFree(pUser);
  90. return NULL;
  91. }
  92. BytesRequired = RtlLengthSid(pUser->User.Sid);
  93. pSid = (PSID)LocalAlloc(LMEM_FIXED, BytesRequired);
  94. if ( pSid == NULL )
  95. {
  96. LocalFree(pUser);
  97. return NULL;
  98. }
  99. status = RtlCopySid(BytesRequired, pSid, pUser->User.Sid);
  100. LocalFree(pUser);
  101. if ( !NT_SUCCESS(status) )
  102. {
  103. LocalFree(pSid);
  104. pSid = NULL;
  105. }
  106. return pSid;
  107. }
  108. LPWSTR
  109. GetSidString( HANDLE UserToken )
  110. {
  111. NTSTATUS NtStatus;
  112. PSID UserSid;
  113. UNICODE_STRING UnicodeString;
  114. //
  115. // Get the user sid
  116. //
  117. UserSid = GetUserSid( UserToken );
  118. if ( !UserSid )
  119. {
  120. return 0;
  121. }
  122. //
  123. // Convert user SID to a string.
  124. //
  125. NtStatus = RtlConvertSidToUnicodeString(&UnicodeString,
  126. UserSid,
  127. (BOOLEAN)TRUE ); // Allocate
  128. LocalFree( UserSid );
  129. if ( !NT_SUCCESS(NtStatus) )
  130. {
  131. return 0;
  132. }
  133. return UnicodeString.Buffer ;
  134. }
  135. void
  136. DeleteSidString( LPWSTR SidString )
  137. {
  138. UNICODE_STRING String;
  139. RtlInitUnicodeString( &String, SidString );
  140. RtlFreeUnicodeString( &String );
  141. }
  142. typedef BOOL (*PFNSHELLEXECUTEEX)(LPSHELLEXECUTEINFO lpExecInfo);
  143. DWORD
  144. ExecuteScript( LPWSTR szCmdLine,
  145. LPWSTR szArgs,
  146. LPWSTR szWorkingDir,
  147. BOOL bSync,
  148. BOOL bHide,
  149. BOOL bRunMin,
  150. LPWSTR szType,
  151. PFNSHELLEXECUTEEX pfnShellExecuteEx,
  152. HANDLE hEventLog )
  153. {
  154. WCHAR szCmdLineEx[MAX_PATH];
  155. WCHAR szArgsEx[3 * MAX_PATH];
  156. WCHAR szCurDir[MAX_PATH];
  157. LPWSTR szOldPath = 0;
  158. BOOL bResult;
  159. DWORD dwError = ERROR_SUCCESS;;
  160. SHELLEXECUTEINFO ExecInfo;
  161. if ( GetSystemDirectory( szCurDir, ARRAYSIZE( szCurDir ) ) )
  162. {
  163. bResult = SetCurrentDirectory( szCurDir );
  164. if ( ! bResult )
  165. {
  166. dwError = GetLastError();
  167. }
  168. }
  169. else
  170. {
  171. dwError = GetLastError();
  172. }
  173. if ( ERROR_SUCCESS != dwError )
  174. {
  175. goto ExecuteScript_Exit;
  176. }
  177. //
  178. // Expand the command line and args
  179. //
  180. DWORD cchExpanded;
  181. cchExpanded = ExpandEnvironmentStrings( szCmdLine, szCmdLineEx, ARRAYSIZE(szCmdLineEx ) );
  182. if ( cchExpanded > 0 )
  183. {
  184. cchExpanded = ExpandEnvironmentStrings( szArgs, szArgsEx, ARRAYSIZE(szArgsEx) );
  185. }
  186. if ( 0 == cchExpanded )
  187. {
  188. dwError = GetLastError();
  189. goto ExecuteScript_Exit;
  190. }
  191. //
  192. // Put the working directory on the front of the PATH
  193. // environment variable
  194. //
  195. bResult = PrependToPath( szWorkingDir, &szOldPath );
  196. if ( ! bResult )
  197. {
  198. dwError = GetLastError();
  199. goto ExecuteScript_Exit;
  200. }
  201. //
  202. // Run the script
  203. //
  204. PathUnquoteSpaces( szCmdLineEx );
  205. ZeroMemory(&ExecInfo, sizeof(ExecInfo));
  206. ExecInfo.cbSize = sizeof(ExecInfo);
  207. ExecInfo.fMask = SEE_MASK_DOENVSUBST |
  208. SEE_MASK_FLAG_NO_UI |
  209. SEE_MASK_NOZONECHECKS |
  210. SEE_MASK_NOCLOSEPROCESS;
  211. ExecInfo.lpFile = szCmdLineEx;
  212. ExecInfo.lpParameters = !szArgsEx[0] ? 0 : szArgsEx;
  213. ExecInfo.lpDirectory = szWorkingDir;
  214. if ( bHide )
  215. {
  216. ExecInfo.nShow = SW_HIDE;
  217. }
  218. else
  219. {
  220. ExecInfo.nShow = (bRunMin ? SW_SHOWMINNOACTIVE : SW_SHOWNORMAL );
  221. }
  222. bResult = pfnShellExecuteEx( &ExecInfo );
  223. dwError = GetLastError();
  224. //
  225. // Try to put the PATH environment variable back the way it was
  226. // If this fails, we have to continue
  227. //
  228. if ( szOldPath )
  229. {
  230. SetEnvironmentVariable( L"PATH", szOldPath );
  231. LocalFree( szOldPath );
  232. szOldPath = 0;
  233. }
  234. if ( bResult )
  235. {
  236. dwError = 0;
  237. if (bSync)
  238. {
  239. WaitForSingleObject(ExecInfo.hProcess, INFINITE);
  240. UpdateUserEnvironment();
  241. }
  242. CloseHandle(ExecInfo.hProcess);
  243. }
  244. else
  245. {
  246. if ( hEventLog != 0 )
  247. {
  248. LPWSTR szMsgBuf[2] = { (LPTSTR) ExecInfo.lpFile, 0 };
  249. FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  250. 0,
  251. dwError,
  252. 0,
  253. (LPTSTR) (&szMsgBuf[1]),
  254. 1,
  255. 0);
  256. ReportEvent(hEventLog,
  257. EVENTLOG_ERROR_TYPE,
  258. 0,
  259. SHELLEXEC_ERROR,
  260. 0,
  261. 2,
  262. 0,
  263. (LPCTSTR*) szMsgBuf,
  264. 0);
  265. if ( szMsgBuf[1] )
  266. {
  267. LocalFree( szMsgBuf[1] );
  268. }
  269. }
  270. }
  271. ExecuteScript_Exit:
  272. return dwError;
  273. }
  274. ScrExecGPOFromReg( HKEY hKeyGPO,
  275. HKEY hKeyStateGPO,
  276. BOOL bSync,
  277. BOOL bHidden,
  278. BOOL bRunMin,
  279. LPWSTR szType,
  280. PFNSHELLEXECUTEEX pfnShellExecuteEx,
  281. HANDLE hEventLog )
  282. {
  283. DWORD dwError = ERROR_SUCCESS;
  284. DWORD cSubKeys = 0;
  285. WCHAR szFileSysPath[3*MAX_PATH];
  286. DWORD dwType;
  287. DWORD dwSize;
  288. HRESULT hr = S_OK;
  289. //
  290. // FILESYSPATH
  291. //
  292. dwType = REG_SZ;
  293. dwSize = sizeof( szFileSysPath );
  294. dwError = RegQueryValueEx( hKeyGPO,
  295. FILESYSPATH,
  296. 0,
  297. &dwType,
  298. (LPBYTE) szFileSysPath,
  299. &dwSize );
  300. if ( dwError != ERROR_SUCCESS )
  301. {
  302. return dwError;
  303. }
  304. hr = StringCchCat( szFileSysPath, sizeof(szFileSysPath)/sizeof(WCHAR), L"\\Scripts\\" );
  305. if(FAILED(hr)){
  306. SetLastError(HRESULT_CODE(hr));
  307. return HRESULT_CODE(hr);
  308. }
  309. hr = StringCchCat( szFileSysPath, sizeof(szFileSysPath)/sizeof(WCHAR), szType );
  310. if(FAILED(hr)){
  311. SetLastError(HRESULT_CODE(hr));
  312. return HRESULT_CODE(hr);
  313. }
  314. //
  315. // get the numer of Scripts
  316. //
  317. dwError = RegQueryInfoKey( hKeyGPO,
  318. 0,
  319. 0,
  320. 0,
  321. &cSubKeys,
  322. 0,
  323. 0,
  324. 0,
  325. 0,
  326. 0,
  327. 0,
  328. 0 );
  329. if ( dwError == ERROR_SUCCESS )
  330. {
  331. //
  332. // for every Script
  333. //
  334. for ( DWORD dwIndex = 0 ; dwIndex < cSubKeys ; dwIndex++ )
  335. {
  336. XKey hKeyScript;
  337. XKey hKeyStateScript;
  338. WCHAR szTemp[32];
  339. dwError = RegOpenKeyEx( hKeyStateGPO,
  340. _itow( dwIndex, szTemp, 16 ),
  341. 0,
  342. KEY_ALL_ACCESS,
  343. &hKeyStateScript );
  344. if ( dwError != ERROR_SUCCESS )
  345. {
  346. return dwError;
  347. }
  348. //
  349. // open the Script key (we need only read perms)
  350. //
  351. dwError = RegOpenKeyEx( hKeyGPO,
  352. szTemp,
  353. 0,
  354. KEY_READ,
  355. &hKeyScript );
  356. if ( dwError != ERROR_SUCCESS )
  357. {
  358. return dwError;
  359. }
  360. WCHAR szScript[MAX_PATH];
  361. WCHAR szParameters[MAX_PATH];
  362. SYSTEMTIME execTime;
  363. //
  364. // script
  365. //
  366. dwType = REG_SZ;
  367. dwSize = sizeof( szScript );
  368. dwError = RegQueryValueEx( hKeyScript,
  369. SCRIPT,
  370. 0,
  371. &dwType,
  372. (LPBYTE) szScript,
  373. &dwSize );
  374. if ( dwError != ERROR_SUCCESS )
  375. {
  376. break;
  377. }
  378. //
  379. // parameters
  380. //
  381. dwType = REG_SZ;
  382. dwSize = sizeof( szParameters );
  383. dwError = RegQueryValueEx( hKeyScript,
  384. PARAMETERS,
  385. 0,
  386. &dwType,
  387. (LPBYTE) szParameters,
  388. &dwSize );
  389. if ( dwError != ERROR_SUCCESS )
  390. {
  391. break;
  392. }
  393. //
  394. // execute script
  395. //
  396. GetSystemTime( &execTime );
  397. dwError = ExecuteScript(szScript,
  398. szParameters,
  399. szFileSysPath,
  400. bSync,
  401. bHidden,
  402. bRunMin,
  403. szType,
  404. pfnShellExecuteEx,
  405. hEventLog );
  406. if ( dwError != ERROR_SUCCESS )
  407. {
  408. ZeroMemory( &execTime, sizeof( execTime ) );
  409. }
  410. //
  411. // write exec time
  412. //
  413. RegSetValueEx( hKeyStateScript,
  414. EXECTIME,
  415. 0,
  416. REG_QWORD,
  417. (LPBYTE) &execTime,
  418. sizeof( execTime ) );
  419. }
  420. }
  421. return dwError;
  422. }
  423. extern "C" DWORD
  424. ScrExecGPOListFromReg( LPWSTR szType,
  425. BOOL bMachine,
  426. BOOL bSync,
  427. BOOL bHidden,
  428. BOOL bRunMin,
  429. HANDLE hEventLog )
  430. {
  431. DWORD dwError = ERROR_SUCCESS;
  432. WCHAR szBuffer[MAX_PATH];
  433. XKey hKeyType;
  434. XKey hKeyState;
  435. XKey hKeyStateType;
  436. HRESULT hr = S_OK;
  437. //
  438. // create the following key
  439. // HKLM\Software\Microsoft\Windows\CurrentVersion\Group Policy\State\<Target>\Scripts\<Type>
  440. //
  441. hr = StringCchCopy( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), GP_STATE_KEY L"\\" );
  442. if(FAILED(hr))
  443. {
  444. SetLastError(HRESULT_CODE(hr));
  445. return HRESULT_CODE(hr);
  446. }
  447. if ( bMachine )
  448. {
  449. hr = StringCchCat( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), L"Machine\\Scripts" );
  450. if(FAILED(hr)){
  451. SetLastError(HRESULT_CODE(hr));
  452. return HRESULT_CODE(hr);
  453. }
  454. }
  455. else
  456. {
  457. XHandle hToken;
  458. if ( !OpenProcessToken( GetCurrentProcess(),
  459. TOKEN_ALL_ACCESS,
  460. &hToken ) )
  461. {
  462. return GetLastError();
  463. }
  464. LPWSTR szSid = GetSidString( hToken );
  465. if ( !szSid )
  466. {
  467. return GetLastError();
  468. }
  469. hr = StringCchCat( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), szSid );
  470. if(FAILED(hr)){
  471. SetLastError(HRESULT_CODE(hr));
  472. return HRESULT_CODE(hr);
  473. }
  474. hr = StringCchCat( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), L"\\Scripts" );
  475. if(FAILED(hr)){
  476. SetLastError(HRESULT_CODE(hr));
  477. return HRESULT_CODE(hr);
  478. }
  479. DeleteSidString( szSid );
  480. }
  481. //
  482. // state
  483. //
  484. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  485. szBuffer,
  486. 0,
  487. KEY_ALL_ACCESS,
  488. &hKeyState );
  489. if ( dwError != ERROR_SUCCESS )
  490. {
  491. return dwError;
  492. }
  493. dwError = RegOpenKeyEx( hKeyState,
  494. szType,
  495. 0,
  496. KEY_ALL_ACCESS,
  497. &hKeyStateType );
  498. if ( dwError != ERROR_SUCCESS )
  499. {
  500. return dwError;
  501. }
  502. //
  503. // construct "Software\\Policies\\Microsoft\\Windows\\System\\Scripts\\<Type>
  504. //
  505. hr = StringCchCopy( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), GPO_SCRIPTS_KEY L"\\" );
  506. if(FAILED(hr)){
  507. SetLastError(HRESULT_CODE(hr));
  508. return HRESULT_CODE(hr);
  509. }
  510. hr = StringCchCat( szBuffer, sizeof(szBuffer)/sizeof(WCHAR), szType );
  511. if(FAILED(hr)){
  512. SetLastError(HRESULT_CODE(hr));
  513. return HRESULT_CODE(hr);
  514. }
  515. //
  516. // open the key
  517. //
  518. dwError = RegOpenKeyEx( bMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
  519. szBuffer,
  520. 0,
  521. KEY_READ,
  522. &hKeyType );
  523. if ( dwError != ERROR_SUCCESS )
  524. {
  525. return dwError;
  526. }
  527. DWORD cSubKeys = 0;
  528. //
  529. // get the numer of GPOs
  530. //
  531. dwError = RegQueryInfoKey( hKeyType,
  532. 0,
  533. 0,
  534. 0,
  535. &cSubKeys,
  536. 0,
  537. 0,
  538. 0,
  539. 0,
  540. 0,
  541. 0,
  542. 0 );
  543. if ( dwError != ERROR_SUCCESS )
  544. {
  545. return dwError;
  546. }
  547. HINSTANCE hShell32;
  548. PFNSHELLEXECUTEEX pfnShellExecuteEx = NULL;
  549. hShell32 = LoadLibrary( L"shell32.dll" );
  550. if ( hShell32 )
  551. {
  552. pfnShellExecuteEx = (PFNSHELLEXECUTEEX) GetProcAddress( hShell32, "ShellExecuteExW" );
  553. }
  554. if ( !pfnShellExecuteEx )
  555. {
  556. return GetLastError();
  557. }
  558. //
  559. // for every GPO
  560. //
  561. for ( DWORD dwIndex = 0 ; dwIndex < cSubKeys ; dwIndex++ )
  562. {
  563. XKey hKeyGPO;
  564. XKey hKeyStateGPO;
  565. //
  566. // open the state GPO key
  567. //
  568. dwError = RegOpenKeyEx( hKeyStateType,
  569. _itow( dwIndex, szBuffer, 16 ),
  570. 0,
  571. KEY_ALL_ACCESS,
  572. &hKeyStateGPO );
  573. if ( dwError != ERROR_SUCCESS )
  574. {
  575. break;
  576. }
  577. //
  578. // open the policy GPO key (we need only read perms)
  579. //
  580. dwError = RegOpenKeyEx( hKeyType,
  581. szBuffer,
  582. 0,
  583. KEY_READ,
  584. &hKeyGPO );
  585. if ( dwError != ERROR_SUCCESS )
  586. {
  587. break;
  588. }
  589. //
  590. // execute all scripts in the GPO
  591. //
  592. DWORD dwExecError;
  593. dwExecError = ScrExecGPOFromReg(hKeyGPO,
  594. hKeyStateGPO,
  595. bSync,
  596. bHidden,
  597. bRunMin,
  598. szType,
  599. pfnShellExecuteEx,
  600. hEventLog );
  601. if ( dwExecError != ERROR_SUCCESS )
  602. {
  603. dwError = dwExecError;
  604. }
  605. }
  606. return dwError;
  607. }