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.

604 lines
16 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. internal.c
  5. Abstract:
  6. User-mode interface to SR.SYS.
  7. Author:
  8. Keith Moore (keithmo) 15-Dec-1998 (ul.sys)
  9. Paul McDaniel (paulmcd) 07-Mar-2000
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. //
  14. // Private macros.
  15. //
  16. #define EA_BUFFER_LENGTH \
  17. ( sizeof(FILE_FULL_EA_INFORMATION) + \
  18. SR_OPEN_PACKET_NAME_LENGTH + \
  19. sizeof(SR_OPEN_PACKET) )
  20. //
  21. // Private prototypes.
  22. //
  23. NTSTATUS
  24. SrpAcquireCachedEvent(
  25. OUT PHANDLE pEvent
  26. );
  27. VOID
  28. SrpReleaseCachedEvent(
  29. IN HANDLE Event
  30. );
  31. //
  32. // Public functions.
  33. //
  34. /***************************************************************************++
  35. Routine Description:
  36. Synchronous wrapper around NtDeviceIoControlFile().
  37. Arguments:
  38. FileHandle - Supplies a handle to the file on which the service is
  39. being performed.
  40. IoControlCode - Subfunction code to determine exactly what operation
  41. is being performed.
  42. pInputBuffer - Optionally supplies an input buffer to be passed to the
  43. device driver. Whether or not the buffer is actually optional is
  44. dependent on the IoControlCode.
  45. InputBufferLength - Length of the pInputBuffer in bytes.
  46. pOutputBuffer - Optionally supplies an output buffer to receive
  47. information from the device driver. Whether or not the buffer is
  48. actually optional is dependent on the IoControlCode.
  49. OutputBufferLength - Length of the pOutputBuffer in bytes.
  50. pBytesTransferred - Optionally receives the number of bytes transferred.
  51. Return Value:
  52. NTSTATUS - Completion status.
  53. --***************************************************************************/
  54. NTSTATUS
  55. SrpSynchronousDeviceControl(
  56. IN HANDLE FileHandle,
  57. IN ULONG IoControlCode,
  58. IN PVOID pInputBuffer OPTIONAL,
  59. IN ULONG InputBufferLength,
  60. OUT PVOID pOutputBuffer OPTIONAL,
  61. IN ULONG OutputBufferLength,
  62. OUT PULONG pBytesTransferred OPTIONAL
  63. )
  64. {
  65. NTSTATUS status;
  66. IO_STATUS_BLOCK ioStatusBlock;
  67. HANDLE event;
  68. LARGE_INTEGER timeout;
  69. //
  70. // Try to snag an event object.
  71. //
  72. status = SrpAcquireCachedEvent( &event );
  73. if (NT_SUCCESS(status))
  74. {
  75. //
  76. // Make the call.
  77. //
  78. status = NtDeviceIoControlFile(
  79. FileHandle, // FileHandle
  80. event, // Event
  81. NULL, // ApcRoutine
  82. NULL, // ApcContext
  83. &ioStatusBlock, // IoStatusBlock
  84. IoControlCode, // IoControlCode
  85. pInputBuffer, // InputBuffer
  86. InputBufferLength, // InputBufferLength
  87. pOutputBuffer, // OutputBuffer
  88. OutputBufferLength // OutputBufferLength
  89. );
  90. if (status == STATUS_PENDING)
  91. {
  92. //
  93. // Wait for it to complete.
  94. //
  95. timeout.LowPart = 0xFFFFFFFF;
  96. timeout.HighPart = 0x7FFFFFFF;
  97. status = NtWaitForSingleObject( event, FALSE, &timeout );
  98. ASSERT( status == STATUS_SUCCESS );
  99. status = ioStatusBlock.Status;
  100. }
  101. //
  102. // If the call didn't fail and the caller wants the number
  103. // of bytes transferred, grab the value from the I/O status
  104. // block & return it.
  105. //
  106. if (!NT_ERROR(status) && pBytesTransferred != NULL)
  107. {
  108. *pBytesTransferred = (ULONG)ioStatusBlock.Information;
  109. }
  110. //
  111. // Release the cached event object we acquired above.
  112. //
  113. SrpReleaseCachedEvent( event );
  114. }
  115. return status;
  116. } // SrpSynchronousDeviceControl
  117. /***************************************************************************++
  118. Routine Description:
  119. Overlapped wrapper around NtDeviceIoControlFile().
  120. Arguments:
  121. FileHandle - Supplies a handle to the file on which the service is
  122. being performed.
  123. pOverlapped - Supplies an OVERLAPPED structure.
  124. IoControlCode - Subfunction code to determine exactly what operation
  125. is being performed.
  126. pInputBuffer - Optionally supplies an input buffer to be passed to the
  127. device driver. Whether or not the buffer is actually optional is
  128. dependent on the IoControlCode.
  129. InputBufferLength - Length of the pInputBuffer in bytes.
  130. pOutputBuffer - Optionally supplies an output buffer to receive
  131. information from the device driver. Whether or not the buffer is
  132. actually optional is dependent on the IoControlCode.
  133. OutputBufferLength - Length of the pOutputBuffer in bytes.
  134. pBytesTransferred - Optionally receives the number of bytes transferred.
  135. Return Value:
  136. NTSTATUS - Completion status.
  137. --***************************************************************************/
  138. NTSTATUS
  139. SrpOverlappedDeviceControl(
  140. IN HANDLE FileHandle,
  141. IN OUT LPOVERLAPPED pOverlapped,
  142. IN ULONG IoControlCode,
  143. IN PVOID pInputBuffer OPTIONAL,
  144. IN ULONG InputBufferLength,
  145. OUT PVOID pOutputBuffer OPTIONAL,
  146. IN ULONG OutputBufferLength,
  147. OUT PULONG pBytesTransferred OPTIONAL
  148. )
  149. {
  150. NTSTATUS status;
  151. //
  152. // Overlapped I/O gets a little more interesting. We'll strive to be
  153. // compatible with NT's KERNEL32 implementation. See DeviceIoControl()
  154. // in \\rastaman\ntwin\src\base\client\filehops.c for the gory details.
  155. //
  156. OVERLAPPED_TO_IO_STATUS(pOverlapped)->Status = STATUS_PENDING;
  157. status = NtDeviceIoControlFile(
  158. FileHandle, // FileHandle
  159. pOverlapped->hEvent, // Event
  160. NULL, // ApcRoutine
  161. (ULONG_PTR)pOverlapped->hEvent & 1 // ApcContext
  162. ? NULL : pOverlapped,
  163. OVERLAPPED_TO_IO_STATUS(pOverlapped), // IoStatusBlock
  164. IoControlCode, // IoControlCode
  165. pInputBuffer, // InputBuffer
  166. InputBufferLength, // InputBufferLength
  167. pOutputBuffer, // OutputBuffer
  168. OutputBufferLength // OutputBufferLength
  169. );
  170. //
  171. // If the call didn't fail or pend and the caller wants the number of
  172. // bytes transferred, grab the value from the I/O status block &
  173. // return it.
  174. //
  175. if (!NT_ERROR(status) &&
  176. status != STATUS_PENDING &&
  177. pBytesTransferred != NULL)
  178. {
  179. *pBytesTransferred =
  180. (ULONG)OVERLAPPED_TO_IO_STATUS(pOverlapped)->Information;
  181. }
  182. return status;
  183. } // SrpOverlappedDeviceControl
  184. /***************************************************************************++
  185. Routine Description:
  186. Initializes the event object cache.
  187. Return Value:
  188. ULONG - Completion status.
  189. --***************************************************************************/
  190. ULONG
  191. SrpInitializeEventCache(
  192. VOID
  193. )
  194. {
  195. //
  196. // CODEWORK: MAKE THIS CACHED!
  197. //
  198. return NO_ERROR;
  199. } // SrpInitializeEventCache
  200. /***************************************************************************++
  201. Routine Description:
  202. Terminates the event object cache.
  203. Return Value:
  204. ULONG - Completion status.
  205. --***************************************************************************/
  206. ULONG
  207. SrpTerminateEventCache(
  208. VOID
  209. )
  210. {
  211. //
  212. // CODEWORK: MAKE THIS CACHED!
  213. //
  214. return NO_ERROR;
  215. } // SrpTerminateEventCache
  216. /***************************************************************************++
  217. Routine Description:
  218. This routine attempts to start UL.SYS.
  219. Return Value:
  220. BOOLEAN - TRUE if successful, FALSE otherwise.
  221. --***************************************************************************/
  222. BOOLEAN
  223. SrpTryToStartDriver(
  224. VOID
  225. )
  226. {
  227. BOOLEAN result;
  228. SC_HANDLE scHandle;
  229. SC_HANDLE svcHandle;
  230. result = FALSE; // until proven otherwise...
  231. //
  232. // Open the service controller.
  233. //
  234. scHandle = OpenSCManagerW(
  235. NULL, // lpMachineName
  236. NULL, // lpDatabaseName
  237. SC_MANAGER_ALL_ACCESS // dwDesiredAccess
  238. );
  239. if (scHandle != NULL)
  240. {
  241. //
  242. // Try to open the UL service.
  243. //
  244. svcHandle = OpenServiceW(
  245. scHandle, // hSCManager
  246. SR_SERVICE_NAME, // lpServiceName
  247. SERVICE_ALL_ACCESS // dwDesiredAccess
  248. );
  249. if (svcHandle != NULL)
  250. {
  251. //
  252. // Try to start it.
  253. //
  254. if (StartService( svcHandle, 0, NULL))
  255. {
  256. result = TRUE;
  257. }
  258. CloseServiceHandle( svcHandle );
  259. }
  260. CloseServiceHandle( scHandle );
  261. }
  262. return result;
  263. } // SrpTryToStartDriver
  264. //
  265. // Private functions.
  266. //
  267. /***************************************************************************++
  268. Routine Description:
  269. Helper routine for opening a UL.SYS handle.
  270. Arguments:
  271. pHandle - Receives a handle if successful.
  272. DesiredAccess - Supplies the types of access requested to the file.
  273. AppPool - Supplies TRUE to open/create an application pool, FALSE
  274. to open a control channel.
  275. pAppPoolName - Optionally supplies the name of the application pool
  276. to create/open.
  277. Options - Supplies zero or more UL_OPTION_* flags.
  278. CreateDisposition - Supplies the creation disposition for the new
  279. object.
  280. pSecurityAttributes - Optionally supplies security attributes for
  281. the newly created application pool. Ignored if opening a
  282. control channel.
  283. Return Value:
  284. NTSTATUS - Completion status.
  285. --***************************************************************************/
  286. NTSTATUS
  287. SrpOpenDriverHelper(
  288. OUT PHANDLE pHandle,
  289. IN ACCESS_MASK DesiredAccess,
  290. IN ULONG Options,
  291. IN ULONG CreateDisposition,
  292. IN PSECURITY_ATTRIBUTES pSecurityAttributes OPTIONAL
  293. )
  294. {
  295. NTSTATUS status;
  296. OBJECT_ATTRIBUTES objectAttributes;
  297. UNICODE_STRING deviceName;
  298. IO_STATUS_BLOCK ioStatusBlock;
  299. ULONG shareAccess;
  300. ULONG createOptions;
  301. PFILE_FULL_EA_INFORMATION pEaBuffer;
  302. PSR_OPEN_PACKET pOpenPacket;
  303. WCHAR deviceNameBuffer[MAX_PATH];
  304. UCHAR rawEaBuffer[EA_BUFFER_LENGTH];
  305. //
  306. // Validate the parameters.
  307. //
  308. if ((pHandle == NULL) ||
  309. (Options & ~SR_OPTION_VALID))
  310. {
  311. return STATUS_INVALID_PARAMETER;
  312. }
  313. //
  314. // Build the open packet.
  315. //
  316. pEaBuffer = (PFILE_FULL_EA_INFORMATION)rawEaBuffer;
  317. pEaBuffer->NextEntryOffset = 0;
  318. pEaBuffer->Flags = 0;
  319. pEaBuffer->EaNameLength = SR_OPEN_PACKET_NAME_LENGTH;
  320. pEaBuffer->EaValueLength = sizeof(*pOpenPacket);
  321. RtlCopyMemory(
  322. pEaBuffer->EaName,
  323. SR_OPEN_PACKET_NAME,
  324. SR_OPEN_PACKET_NAME_LENGTH + 1
  325. );
  326. pOpenPacket =
  327. (PSR_OPEN_PACKET)( pEaBuffer->EaName + pEaBuffer->EaNameLength + 1 );
  328. pOpenPacket->MajorVersion = SR_INTERFACE_VERSION_MAJOR;
  329. pOpenPacket->MinorVersion = SR_INTERFACE_VERSION_MINOR;
  330. //
  331. // Build the device name.
  332. //
  333. //
  334. // It's a control channel, so just use the appropriate device name.
  335. //
  336. wcscpy( deviceNameBuffer, SR_CONTROL_DEVICE_NAME );
  337. //
  338. // Determine the share access and create options based on the
  339. // Flags parameter.
  340. //
  341. shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
  342. createOptions = 0;
  343. if ((Options & SR_OPTION_OVERLAPPED) == 0)
  344. {
  345. createOptions |= FILE_SYNCHRONOUS_IO_NONALERT;
  346. }
  347. //
  348. // Build the object attributes.
  349. //
  350. RtlInitUnicodeString( &deviceName, deviceNameBuffer );
  351. InitializeObjectAttributes(
  352. &objectAttributes, // ObjectAttributes
  353. &deviceName, // ObjectName
  354. OBJ_CASE_INSENSITIVE, // Attributes
  355. NULL, // RootDirectory
  356. NULL // SecurityDescriptor
  357. );
  358. if (pSecurityAttributes != NULL)
  359. {
  360. objectAttributes.SecurityDescriptor =
  361. pSecurityAttributes->lpSecurityDescriptor;
  362. if (pSecurityAttributes->bInheritHandle)
  363. {
  364. objectAttributes.Attributes |= OBJ_INHERIT;
  365. }
  366. }
  367. //
  368. // Open the SR device.
  369. //
  370. status = NtCreateFile(
  371. pHandle, // FileHandle
  372. DesiredAccess, // DesiredAccess
  373. &objectAttributes, // ObjectAttributes
  374. &ioStatusBlock, // IoStatusBlock
  375. NULL, // AllocationSize
  376. 0, // FileAttributes
  377. shareAccess, // ShareAccess
  378. CreateDisposition, // CreateDisposition
  379. createOptions, // CreateOptions
  380. pEaBuffer, // EaBuffer
  381. EA_BUFFER_LENGTH // EaLength
  382. );
  383. if (!NT_SUCCESS(status))
  384. {
  385. *pHandle = NULL;
  386. }
  387. return status;
  388. } // SrpOpenDriverHelper
  389. /***************************************************************************++
  390. Routine Description:
  391. Acquires a short-term event from the global event cache. This event
  392. object may only be used for pseudo-synchronous I/O.
  393. Arguments:
  394. pEvent - Receives the event handle.
  395. Return Value:
  396. NTSTATUS - Completion status.
  397. --***************************************************************************/
  398. NTSTATUS
  399. SrpAcquireCachedEvent(
  400. OUT PHANDLE pEvent
  401. )
  402. {
  403. NTSTATUS status;
  404. //
  405. // CODEWORK: MAKE THIS CACHED!
  406. //
  407. status = NtCreateEvent(
  408. pEvent, // EventHandle
  409. EVENT_ALL_ACCESS, // DesiredAccess
  410. NULL, // ObjectAttributes
  411. SynchronizationEvent, // EventType
  412. FALSE // InitialState
  413. );
  414. return status;
  415. } // SrpAcquireCachedEvent
  416. /***************************************************************************++
  417. Routine Description:
  418. Releases a cached event acquired via SrpAcquireCachedEvent().
  419. Arguments:
  420. Event - Supplies the event to release.
  421. --***************************************************************************/
  422. VOID
  423. SrpReleaseCachedEvent(
  424. IN HANDLE Event
  425. )
  426. {
  427. NTSTATUS status;
  428. //
  429. // CODEWORK: MAKE THIS CACHED!
  430. //
  431. status = NtClose( Event );
  432. ASSERT( NT_SUCCESS(status) );
  433. } // SrpReleaseCachedEvent