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.

666 lines
15 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. Shutdown.c
  5. Abstract:
  6. This module contains the client side wrappers for the Win32 remote
  7. shutdown APIs, that is:
  8. - InitiateSystemShutdownA
  9. - InitiateSystemShutdownW
  10. - AbortSystemShutdownA
  11. - AbortSystemShutdownW
  12. Author:
  13. Dave Chalmers (davidc) 29-Apr-1992
  14. Notes:
  15. Revision History:
  16. Dragos C. Sambotin (dragoss) 21-May-1999
  17. Added support for the new winlogon's Shutdown interface
  18. --*/
  19. #define UNICODE
  20. #include <rpc.h>
  21. #include "regrpc.h"
  22. #include "client.h"
  23. #include "shutinit.h"
  24. #include "..\regconn\regconn.h"
  25. LONG
  26. BaseBindToMachine(
  27. IN LPCWSTR lpMachineName,
  28. IN PBIND_CALLBACK BindCallback,
  29. IN PVOID Context1,
  30. IN PVOID Context2
  31. );
  32. LONG
  33. ShutdownCallback(
  34. IN RPC_BINDING_HANDLE *pbinding,
  35. IN PUNICODE_STRING Message,
  36. IN PVOID Context2
  37. );
  38. LONG
  39. ShutdownCallbackEx(
  40. IN RPC_BINDING_HANDLE *pbinding,
  41. IN PUNICODE_STRING Message,
  42. IN PVOID Context2
  43. );
  44. LONG
  45. AbortShutdownCallback(
  46. IN RPC_BINDING_HANDLE *pbinding,
  47. IN PVOID Context1,
  48. IN PVOID Context2
  49. );
  50. BOOL
  51. APIENTRY
  52. InitiateSystemShutdownW(
  53. IN LPWSTR lpMachineName OPTIONAL,
  54. IN LPWSTR lpMessage OPTIONAL,
  55. IN DWORD dwTimeout,
  56. IN BOOL bForceAppsClosed,
  57. IN BOOL bRebootAfterShutdown
  58. )
  59. /*++
  60. Routine Description:
  61. Win32 Unicode API for initiating the shutdown of a (possibly remote) machine.
  62. Arguments:
  63. lpMachineName - Name of machine to shutdown.
  64. lpMessage - Message to display during shutdown timeout period.
  65. dwTimeout - Number of seconds to delay before shutting down
  66. bForceAppsClosed - Normally applications may prevent system shutdown.
  67. If this flag is set, all applications are terminated
  68. unconditionally.
  69. bRebootAfterShutdown - TRUE if the system should reboot.
  70. FALSE if it should be left in a shutdown state.
  71. Return Value:
  72. Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
  73. Possible errors :
  74. ERROR_SHUTDOWN_IN_PROGRESS - a shutdown has already been started on
  75. the specified machine.
  76. --*/
  77. {
  78. DWORD Result;
  79. UNICODE_STRING Message;
  80. SHUTDOWN_CONTEXT ShutdownContext;
  81. BOOL TryOld = TRUE;
  82. //
  83. // Explicitly bind to the given server.
  84. //
  85. if (!ARGUMENT_PRESENT(lpMachineName)) {
  86. lpMachineName = L"";
  87. TryOld = FALSE;
  88. }
  89. ShutdownContext.dwTimeout = dwTimeout;
  90. ShutdownContext.bForceAppsClosed = (bForceAppsClosed != 0);
  91. ShutdownContext.bRebootAfterShutdown = (bRebootAfterShutdown != 0);
  92. RtlInitUnicodeString(&Message, lpMessage);
  93. //
  94. // Call the server
  95. //
  96. //
  97. // First try to connect to the new InitShutdown interface
  98. //
  99. Result = BaseBindToMachineShutdownInterface(lpMachineName,
  100. NewShutdownCallback,
  101. &Message,
  102. &ShutdownContext);
  103. if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) {
  104. //
  105. // try the old one, maybe we are calling into a NT4 machine
  106. // which doesn't know about the new interface
  107. //
  108. Result = BaseBindToMachine(lpMachineName,
  109. ShutdownCallback,
  110. &Message,
  111. &ShutdownContext);
  112. }
  113. if (Result != ERROR_SUCCESS) {
  114. SetLastError(Result);
  115. }
  116. return(Result == ERROR_SUCCESS);
  117. }
  118. BOOL
  119. APIENTRY
  120. InitiateSystemShutdownExW(
  121. IN LPWSTR lpMachineName OPTIONAL,
  122. IN LPWSTR lpMessage OPTIONAL,
  123. IN DWORD dwTimeout,
  124. IN BOOL bForceAppsClosed,
  125. IN BOOL bRebootAfterShutdown,
  126. IN DWORD dwReason
  127. )
  128. /*++
  129. Routine Description:
  130. Win32 Unicode API for initiating the shutdown of a (possibly remote) machine.
  131. Arguments:
  132. lpMachineName - Name of machine to shutdown.
  133. lpMessage - Message to display during shutdown timeout period.
  134. dwTimeout - Number of seconds to delay before shutting down
  135. bForceAppsClosed - Normally applications may prevent system shutdown.
  136. If this flag is set, all applications are terminated
  137. unconditionally.
  138. bRebootAfterShutdown - TRUE if the system should reboot.
  139. FALSE if it should be left in a shutdown state.
  140. dwReason - Reason for initiating the shutdown. This reason is logged
  141. in the eventlog #6006 event.
  142. Return Value:
  143. Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
  144. Possible errors :
  145. ERROR_SHUTDOWN_IN_PROGRESS - a shutdown has already been started on
  146. the specified machine.
  147. --*/
  148. {
  149. DWORD Result;
  150. UNICODE_STRING Message;
  151. SHUTDOWN_CONTEXTEX ShutdownContext;
  152. BOOL TryOld = TRUE;
  153. //
  154. // Explicitly bind to the given server.
  155. //
  156. if (!ARGUMENT_PRESENT(lpMachineName)) {
  157. lpMachineName = L"";
  158. TryOld = FALSE;
  159. }
  160. ShutdownContext.dwTimeout = dwTimeout;
  161. ShutdownContext.bForceAppsClosed = (bForceAppsClosed != 0);
  162. ShutdownContext.bRebootAfterShutdown = (bRebootAfterShutdown != 0);
  163. ShutdownContext.dwReason = dwReason;
  164. RtlInitUnicodeString(&Message, lpMessage);
  165. //
  166. // Call the server
  167. //
  168. //
  169. // First try to connect to the new InitShutdown interface
  170. //
  171. Result = BaseBindToMachineShutdownInterface(lpMachineName,
  172. NewShutdownCallbackEx,
  173. &Message,
  174. &ShutdownContext);
  175. if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) {
  176. //
  177. // try the old one, maybe we are calling into a NT4 machine
  178. // which doesn't know about the new interface
  179. //
  180. Result = BaseBindToMachine(lpMachineName,
  181. ShutdownCallbackEx,
  182. &Message,
  183. &ShutdownContext);
  184. }
  185. if (Result != ERROR_SUCCESS) {
  186. SetLastError(Result);
  187. }
  188. return(Result == ERROR_SUCCESS);
  189. }
  190. BOOL
  191. APIENTRY
  192. InitiateSystemShutdownA(
  193. IN LPSTR lpMachineName OPTIONAL,
  194. IN LPSTR lpMessage OPTIONAL,
  195. IN DWORD dwTimeout,
  196. IN BOOL bForceAppsClosed,
  197. IN BOOL bRebootAfterShutdown
  198. )
  199. /*++
  200. Routine Description:
  201. See InitiateSystemShutdownW
  202. --*/
  203. {
  204. UNICODE_STRING MachineName;
  205. UNICODE_STRING Message;
  206. ANSI_STRING AnsiString;
  207. NTSTATUS Status;
  208. BOOL Result;
  209. //
  210. // Convert the ansi machinename to wide-character
  211. //
  212. RtlInitAnsiString( &AnsiString, lpMachineName );
  213. Status = RtlAnsiStringToUnicodeString(
  214. &MachineName,
  215. &AnsiString,
  216. TRUE
  217. );
  218. if( NT_SUCCESS( Status )) {
  219. //
  220. // Convert the ansi message to wide-character
  221. //
  222. RtlInitAnsiString( &AnsiString, lpMessage );
  223. Status = RtlAnsiStringToUnicodeString(
  224. &Message,
  225. &AnsiString,
  226. TRUE
  227. );
  228. if (NT_SUCCESS(Status)) {
  229. //
  230. // Call the wide-character api
  231. //
  232. Result = InitiateSystemShutdownW(
  233. MachineName.Buffer,
  234. Message.Buffer,
  235. dwTimeout,
  236. bForceAppsClosed,
  237. bRebootAfterShutdown
  238. );
  239. RtlFreeUnicodeString(&Message);
  240. }
  241. RtlFreeUnicodeString(&MachineName);
  242. }
  243. if (!NT_SUCCESS(Status)) {
  244. SetLastError(RtlNtStatusToDosError(Status));
  245. Result = FALSE;
  246. }
  247. return(Result);
  248. }
  249. BOOL
  250. APIENTRY
  251. InitiateSystemShutdownExA(
  252. IN LPSTR lpMachineName OPTIONAL,
  253. IN LPSTR lpMessage OPTIONAL,
  254. IN DWORD dwTimeout,
  255. IN BOOL bForceAppsClosed,
  256. IN BOOL bRebootAfterShutdown,
  257. IN DWORD dwReason
  258. )
  259. /*++
  260. Routine Description:
  261. See InitiateSystemShutdownW
  262. --*/
  263. {
  264. UNICODE_STRING MachineName;
  265. UNICODE_STRING Message;
  266. ANSI_STRING AnsiString;
  267. NTSTATUS Status;
  268. BOOL Result;
  269. //
  270. // Convert the ansi machinename to wide-character
  271. //
  272. RtlInitAnsiString( &AnsiString, lpMachineName );
  273. Status = RtlAnsiStringToUnicodeString(
  274. &MachineName,
  275. &AnsiString,
  276. TRUE
  277. );
  278. if( NT_SUCCESS( Status )) {
  279. //
  280. // Convert the ansi message to wide-character
  281. //
  282. RtlInitAnsiString( &AnsiString, lpMessage );
  283. Status = RtlAnsiStringToUnicodeString(
  284. &Message,
  285. &AnsiString,
  286. TRUE
  287. );
  288. if (NT_SUCCESS(Status)) {
  289. //
  290. // Call the wide-character api
  291. //
  292. Result = InitiateSystemShutdownExW(
  293. MachineName.Buffer,
  294. Message.Buffer,
  295. dwTimeout,
  296. bForceAppsClosed,
  297. bRebootAfterShutdown,
  298. dwReason
  299. );
  300. RtlFreeUnicodeString(&Message);
  301. }
  302. RtlFreeUnicodeString(&MachineName);
  303. }
  304. if (!NT_SUCCESS(Status)) {
  305. SetLastError(RtlNtStatusToDosError(Status));
  306. Result = FALSE;
  307. }
  308. return(Result);
  309. }
  310. BOOL
  311. APIENTRY
  312. AbortSystemShutdownW(
  313. IN LPWSTR lpMachineName OPTIONAL
  314. )
  315. /*++
  316. Routine Description:
  317. Win32 Unicode API for aborting the shutdown of a (possibly remote) machine.
  318. Arguments:
  319. lpMachineName - Name of target machine.
  320. Return Value:
  321. Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
  322. --*/
  323. {
  324. DWORD Result;
  325. RPC_BINDING_HANDLE binding;
  326. BOOL TryOld = TRUE;
  327. //
  328. // Explicitly bind to the given server.
  329. //
  330. if (!ARGUMENT_PRESENT(lpMachineName)) {
  331. lpMachineName = L"";
  332. TryOld = FALSE;
  333. }
  334. //
  335. // Call the server
  336. //
  337. //
  338. // First try to connect to the new InitShutdown interface
  339. //
  340. Result = BaseBindToMachineShutdownInterface(lpMachineName,
  341. NewAbortShutdownCallback,
  342. NULL,
  343. NULL);
  344. if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) {
  345. //
  346. // try the old one, maybe we are calling into a NT4 machine
  347. // which doesn't know about the new interface
  348. Result = BaseBindToMachine(lpMachineName,
  349. AbortShutdownCallback,
  350. NULL,
  351. NULL);
  352. }
  353. if (Result != ERROR_SUCCESS) {
  354. SetLastError(Result);
  355. }
  356. return(Result == ERROR_SUCCESS);
  357. }
  358. BOOL
  359. APIENTRY
  360. AbortSystemShutdownA(
  361. IN LPSTR lpMachineName OPTIONAL
  362. )
  363. /*++
  364. Routine Description:
  365. See AbortSystemShutdownW
  366. --*/
  367. {
  368. UNICODE_STRING MachineName;
  369. ANSI_STRING AnsiString;
  370. NTSTATUS Status;
  371. BOOL Result;
  372. //
  373. // Convert the ansi machinename to wide-character
  374. //
  375. RtlInitAnsiString( &AnsiString, lpMachineName );
  376. Status = RtlAnsiStringToUnicodeString(
  377. &MachineName,
  378. &AnsiString,
  379. TRUE
  380. );
  381. if( NT_SUCCESS( Status )) {
  382. //
  383. // Call the wide-character api
  384. //
  385. Result = AbortSystemShutdownW(
  386. MachineName.Buffer
  387. );
  388. RtlFreeUnicodeString(&MachineName);
  389. }
  390. if (!NT_SUCCESS(Status)) {
  391. SetLastError(RtlNtStatusToDosError(Status));
  392. Result = FALSE;
  393. }
  394. return(Result);
  395. }
  396. LONG
  397. ShutdownCallback(
  398. IN RPC_BINDING_HANDLE *pbinding,
  399. IN PUNICODE_STRING Message,
  400. IN PSHUTDOWN_CONTEXT ShutdownContext
  401. )
  402. /*++
  403. Routine Description:
  404. Callback for binding to a machine to initiate a shutdown.
  405. Arguments:
  406. pbinding - Supplies a pointer to the RPC binding context
  407. Message - Supplies message to display during shutdown timeout period.
  408. ShutdownContext - Supplies remaining parameters for BaseInitiateSystemShutdown
  409. Return Value:
  410. ERROR_SUCCESS if no error.
  411. --*/
  412. {
  413. DWORD Result;
  414. RpcTryExcept {
  415. Result = BaseInitiateSystemShutdown((PREGISTRY_SERVER_NAME)pbinding,
  416. Message,
  417. ShutdownContext->dwTimeout,
  418. ShutdownContext->bForceAppsClosed,
  419. ShutdownContext->bRebootAfterShutdown);
  420. } RpcExcept(EXCEPTION_EXECUTE_HANDLER) {
  421. Result = RpcExceptionCode();
  422. } RpcEndExcept;
  423. if (Result != ERROR_SUCCESS) {
  424. RpcBindingFree(pbinding);
  425. }
  426. return(Result);
  427. }
  428. LONG
  429. ShutdownCallbackEx(
  430. IN RPC_BINDING_HANDLE *pbinding,
  431. IN PUNICODE_STRING Message,
  432. IN PSHUTDOWN_CONTEXTEX ShutdownContext
  433. )
  434. /*++
  435. Routine Description:
  436. Callback for binding to a machine to initiate a shutdown.
  437. Arguments:
  438. pbinding - Supplies a pointer to the RPC binding context
  439. Message - Supplies message to display during shutdown timeout period.
  440. ShutdownContext - Supplies remaining parameters for BaseInitiateSystemShutdown
  441. Return Value:
  442. ERROR_SUCCESS if no error.
  443. --*/
  444. {
  445. DWORD Result;
  446. RpcTryExcept {
  447. Result = BaseInitiateSystemShutdownEx((PREGISTRY_SERVER_NAME)pbinding,
  448. Message,
  449. ShutdownContext->dwTimeout,
  450. ShutdownContext->bForceAppsClosed,
  451. ShutdownContext->bRebootAfterShutdown,
  452. ShutdownContext->dwReason);
  453. } RpcExcept(EXCEPTION_EXECUTE_HANDLER) {
  454. Result = RpcExceptionCode();
  455. } RpcEndExcept;
  456. if (Result != ERROR_SUCCESS) {
  457. RpcBindingFree(pbinding);
  458. }
  459. return(Result);
  460. }
  461. LONG
  462. AbortShutdownCallback(
  463. IN RPC_BINDING_HANDLE *pbinding,
  464. IN PVOID Unused1,
  465. IN PVOID Unused2
  466. )
  467. /*++
  468. Routine Description:
  469. Callback for binding to a machine to abort a shutdown.
  470. Arguments:
  471. pbinding - Supplies a pointer to the RPC binding context
  472. Return Value:
  473. ERROR_SUCCESS if no error.
  474. --*/
  475. {
  476. DWORD Result;
  477. RpcTryExcept {
  478. Result = BaseAbortSystemShutdown((PREGISTRY_SERVER_NAME)pbinding);
  479. } RpcExcept(EXCEPTION_EXECUTE_HANDLER) {
  480. Result = RpcExceptionCode();
  481. } RpcEndExcept;
  482. if (Result != ERROR_SUCCESS) {
  483. RpcBindingFree(pbinding);
  484. }
  485. return(Result);
  486. }