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.

385 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. handle.c
  5. Abstract:
  6. This module implements the Win32 handle management services.
  7. Author:
  8. Mark Lucovsky (markl) 21-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. BOOL
  13. CloseHandle(
  14. HANDLE hObject
  15. )
  16. /*++
  17. Routine Description:
  18. An open handle to any object can be closed using CloseHandle.
  19. This is a generic function and operates on the following object
  20. types:
  21. - Process Object
  22. - Thread Object
  23. - Mutex Object
  24. - Event Object
  25. - Semaphore Object
  26. - File Object
  27. Please note that Module Objects are not in this list.
  28. Closing an open handle to an object causes the handle to become
  29. invalid and the HandleCount of the associated object to be
  30. decremented and object retention checks to be performed. Once the
  31. last open handle to an object is closed, the object is removed from
  32. the system.
  33. Arguments:
  34. hObject - An open handle to an object.
  35. Return Value:
  36. TRUE - The operation was successful.
  37. FALSE/NULL - The operation failed. Extended error status is available
  38. using GetLastError.
  39. --*/
  40. {
  41. NTSTATUS Status;
  42. PPEB Peb;
  43. Peb = NtCurrentPeb();
  44. //
  45. // Perhaps we ought to use a full-fledged lock here, however, it
  46. // doesn't seem absolutely necessary, and it's reasonable to
  47. // assume that callers are aware of the various race conditions
  48. // which may be involved with using and closing the standard
  49. // handles.
  50. //
  51. // In any event, a proper fix would use a lock in kernel mode, and
  52. // do the mapping there, as the lock would really need to be held
  53. // across the translation from handle to kernel object.
  54. //
  55. // Replacing handles with NULL will cause StuffStdHandle() to
  56. // ignore them when duplicating handles to child processes.
  57. //
  58. switch( HandleToUlong(hObject) ) {
  59. case STD_INPUT_HANDLE:
  60. hObject = InterlockedExchangePointer(
  61. &Peb->ProcessParameters->StandardInput,
  62. NULL);
  63. break;
  64. case STD_OUTPUT_HANDLE:
  65. hObject = InterlockedExchangePointer(
  66. &Peb->ProcessParameters->StandardOutput,
  67. NULL);
  68. break;
  69. case STD_ERROR_HANDLE:
  70. hObject = InterlockedExchangePointer(
  71. &Peb->ProcessParameters->StandardError,
  72. NULL);
  73. break;
  74. }
  75. if (CONSOLE_HANDLE(hObject)) {
  76. return CloseConsoleHandle(hObject);
  77. }
  78. Status = NtClose(hObject);
  79. if ( NT_SUCCESS(Status) ) {
  80. return TRUE;
  81. }
  82. else {
  83. BaseSetLastNTError(Status);
  84. return FALSE;
  85. }
  86. }
  87. BOOL
  88. DuplicateHandle(
  89. HANDLE hSourceProcessHandle,
  90. HANDLE hSourceHandle,
  91. HANDLE hTargetProcessHandle,
  92. LPHANDLE lpTargetHandle,
  93. DWORD dwDesiredAccess,
  94. BOOL bInheritHandle,
  95. DWORD dwOptions
  96. )
  97. /*++
  98. Routine Description:
  99. A duplicate handle can be created with the DuplicateHandle function.
  100. This is a generic function and operates on the following object
  101. types:
  102. - Process Object
  103. - Thread Object
  104. - Mutex Object
  105. - Event Object
  106. - Semaphore Object
  107. - File Object
  108. Please note that Module Objects are not in this list.
  109. This function requires PROCESS_DUP_ACCESS to both the
  110. SourceProcessHandle and the TargetProcessHandle. This function is
  111. used to pass an object handle from one process to another. Once
  112. this call is complete, the target process needs to be informed of
  113. the value of the target handle. The target process can then operate
  114. on the object using this handle value.
  115. Arguments:
  116. hSourceProcessHandle - An open handle to the process that contains the
  117. handle to be duplicated. The handle must have been created with
  118. PROCESS_DUP_HANDLE access to the process.
  119. hSourceHandle - An open handle to any object that is valid in the
  120. context of the source process.
  121. hTargetProcessHandle - An open handle to the process that is to
  122. receive the duplicated handle. The handle must have been
  123. created with PROCESS_DUP_HANDLE access to the process.
  124. lpTargetHandle - A pointer to a variable which receives the new handle
  125. that points to the same object as SourceHandle does. This
  126. handle value is valid in the context of the target process.
  127. dwDesiredAccess - The access requested to for the new handle. This
  128. parameter is ignored if the DUPLICATE_SAME_ACCESS option is
  129. specified.
  130. bInheritHandle - Supplies a flag that if TRUE, marks the target
  131. handle as inheritable. If this is the case, then the target
  132. handle will be inherited to new processes each time the target
  133. process creates a new process using CreateProcess.
  134. dwOptions - Specifies optional behaviors for the caller.
  135. Options Flags:
  136. DUPLICATE_CLOSE_SOURCE - The SourceHandle will be closed by
  137. this service prior to returning to the caller. This occurs
  138. regardless of any error status returned.
  139. DUPLICATE_SAME_ACCESS - The DesiredAccess parameter is ignored
  140. and instead the GrantedAccess associated with SourceHandle
  141. is used as the DesiredAccess when creating the TargetHandle.
  142. Return Value:
  143. TRUE - The operation was successful.
  144. FALSE/NULL - The operation failed. Extended error status is available
  145. using GetLastError.
  146. --*/
  147. {
  148. NTSTATUS Status;
  149. PPEB Peb;
  150. Peb = NtCurrentPeb();
  151. switch( HandleToUlong(hSourceHandle) ) {
  152. case STD_INPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardInput;
  153. break;
  154. case STD_OUTPUT_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardOutput;
  155. break;
  156. case STD_ERROR_HANDLE: hSourceHandle = Peb->ProcessParameters->StandardError;
  157. break;
  158. }
  159. if (CONSOLE_HANDLE(hSourceHandle) &&
  160. (hSourceHandle != NtCurrentProcess() &&
  161. hSourceHandle != NtCurrentThread()) ) {
  162. HANDLE Target;
  163. if (hSourceProcessHandle != NtCurrentProcess() ||
  164. hTargetProcessHandle != NtCurrentProcess()) {
  165. BaseSetLastNTError(STATUS_INVALID_PARAMETER);
  166. return FALSE;
  167. }
  168. Target = DuplicateConsoleHandle(hSourceHandle,
  169. dwDesiredAccess,
  170. bInheritHandle,
  171. dwOptions
  172. );
  173. if (Target == INVALID_HANDLE_VALUE) {
  174. return FALSE;
  175. }
  176. else {
  177. try {
  178. if ( ARGUMENT_PRESENT(lpTargetHandle) ) {
  179. *lpTargetHandle = Target;
  180. }
  181. }
  182. except (EXCEPTION_EXECUTE_HANDLER) {
  183. return TRUE;
  184. }
  185. return TRUE;
  186. }
  187. }
  188. Status = NtDuplicateObject(
  189. hSourceProcessHandle,
  190. hSourceHandle,
  191. hTargetProcessHandle,
  192. lpTargetHandle,
  193. (ACCESS_MASK)dwDesiredAccess,
  194. bInheritHandle ? OBJ_INHERIT : 0,
  195. dwOptions
  196. );
  197. if ( NT_SUCCESS(Status) ) {
  198. return TRUE;
  199. }
  200. else {
  201. BaseSetLastNTError(Status);
  202. return FALSE;
  203. }
  204. return FALSE;
  205. }
  206. BOOL
  207. GetHandleInformation(
  208. HANDLE hObject,
  209. LPDWORD lpdwFlags
  210. )
  211. {
  212. NTSTATUS Status;
  213. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
  214. DWORD Result;
  215. PPEB Peb;
  216. Peb = NtCurrentPeb();
  217. switch( HandleToUlong(hObject) ) {
  218. case STD_INPUT_HANDLE: hObject = Peb->ProcessParameters->StandardInput;
  219. break;
  220. case STD_OUTPUT_HANDLE: hObject = Peb->ProcessParameters->StandardOutput;
  221. break;
  222. case STD_ERROR_HANDLE: hObject = Peb->ProcessParameters->StandardError;
  223. break;
  224. }
  225. if (CONSOLE_HANDLE(hObject)) {
  226. return GetConsoleHandleInformation(hObject,
  227. lpdwFlags
  228. );
  229. }
  230. Status = NtQueryObject( hObject,
  231. ObjectHandleFlagInformation,
  232. &HandleInfo,
  233. sizeof( HandleInfo ),
  234. NULL
  235. );
  236. if (NT_SUCCESS( Status )) {
  237. Result = 0;
  238. if (HandleInfo.Inherit) {
  239. Result |= HANDLE_FLAG_INHERIT;
  240. }
  241. if (HandleInfo.ProtectFromClose) {
  242. Result |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
  243. }
  244. *lpdwFlags = Result;
  245. return TRUE;
  246. }
  247. else {
  248. BaseSetLastNTError( Status );
  249. return FALSE;
  250. }
  251. }
  252. BOOL
  253. SetHandleInformation(
  254. HANDLE hObject,
  255. DWORD dwMask,
  256. DWORD dwFlags
  257. )
  258. {
  259. NTSTATUS Status;
  260. OBJECT_HANDLE_FLAG_INFORMATION HandleInfo;
  261. PPEB Peb;
  262. Peb = NtCurrentPeb();
  263. switch( HandleToUlong(hObject) ) {
  264. case STD_INPUT_HANDLE: hObject = Peb->ProcessParameters->StandardInput;
  265. break;
  266. case STD_OUTPUT_HANDLE: hObject = Peb->ProcessParameters->StandardOutput;
  267. break;
  268. case STD_ERROR_HANDLE: hObject = Peb->ProcessParameters->StandardError;
  269. break;
  270. }
  271. if (CONSOLE_HANDLE(hObject)) {
  272. return SetConsoleHandleInformation(hObject,
  273. dwMask,
  274. dwFlags
  275. );
  276. }
  277. Status = NtQueryObject( hObject,
  278. ObjectHandleFlagInformation,
  279. &HandleInfo,
  280. sizeof( HandleInfo ),
  281. NULL
  282. );
  283. if (NT_SUCCESS( Status )) {
  284. if (dwMask & HANDLE_FLAG_INHERIT) {
  285. HandleInfo.Inherit = (dwFlags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
  286. }
  287. if (dwMask & HANDLE_FLAG_PROTECT_FROM_CLOSE) {
  288. HandleInfo.ProtectFromClose = (dwFlags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
  289. }
  290. Status = NtSetInformationObject( hObject,
  291. ObjectHandleFlagInformation,
  292. &HandleInfo,
  293. sizeof( HandleInfo )
  294. );
  295. if (NT_SUCCESS( Status )) {
  296. return TRUE;
  297. }
  298. }
  299. BaseSetLastNTError( Status );
  300. return FALSE;
  301. }