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.

1007 lines
28 KiB

  1. #include "brian.h"
  2. #define OPLOCK_VERBOSES_DEFAULT TRUE
  3. typedef struct _OPLOCK {
  4. ULONG FileHandleIndex;
  5. BOOLEAN VerboseResults;
  6. USHORT BufferIndex;
  7. } OPLOCK, *POPLOCK;
  8. //
  9. // Local procedures
  10. //
  11. VOID
  12. RequestOplockI (
  13. IN POPLOCK Oplock
  14. );
  15. VOID
  16. RequestBatchOplock (
  17. IN POPLOCK Oplock
  18. );
  19. VOID
  20. RequestFilterOplock (
  21. IN POPLOCK Oplock
  22. );
  23. VOID
  24. RequestOplockII (
  25. IN POPLOCK Oplock
  26. );
  27. VOID
  28. AcknowledgeOplockBreak (
  29. IN POPLOCK Oplock
  30. );
  31. VOID
  32. AcknowledgeOplockBreakNo2 (
  33. IN POPLOCK Oplock
  34. );
  35. VOID
  36. AcknowledgeOpBatchBreakPending (
  37. IN POPLOCK Oplock
  38. );
  39. VOID
  40. OplockBreakNotify (
  41. IN POPLOCK Oplock
  42. );
  43. VOID
  44. InputOplock(
  45. IN PCHAR ParamBuffer
  46. )
  47. {
  48. ULONG Operation;
  49. BOOLEAN VerboseResults;
  50. BOOLEAN DisplayParms;
  51. BOOLEAN ParamReceived;
  52. BOOLEAN LastInput;
  53. POPLOCK Oplock;
  54. ULONG FileHandleIndex;
  55. VerboseResults = OPLOCK_VERBOSES_DEFAULT;
  56. DisplayParms = FALSE;
  57. ParamReceived = FALSE;
  58. LastInput = TRUE;
  59. FileHandleIndex = 0;
  60. Operation = (ULONG) -1;
  61. //
  62. // While there is more input, analyze the parameter and update the
  63. // query flags.
  64. //
  65. while (TRUE) {
  66. ULONG DummyCount;
  67. //
  68. // Swallow leading white spaces.
  69. //
  70. ParamBuffer = SwallowWhite( ParamBuffer, &DummyCount );
  71. if (*ParamBuffer) {
  72. //
  73. // If the next parameter is legal then check the paramter value.
  74. // Update the parameter value.
  75. //
  76. if ((*ParamBuffer == '-'
  77. || *ParamBuffer == '/')
  78. && (ParamBuffer++, *ParamBuffer != '\0')) {
  79. BOOLEAN SwitchBool;
  80. //
  81. // Switch on the next character.
  82. //
  83. switch (*ParamBuffer) {
  84. //
  85. // Modify the operation
  86. //
  87. case 'o' :
  88. case 'O' :
  89. ParamBuffer++;
  90. SwitchBool = TRUE;
  91. while (*ParamBuffer
  92. && *ParamBuffer != ' '
  93. && *ParamBuffer != '\t') {
  94. //
  95. // Perform switch on character.
  96. //
  97. switch (*ParamBuffer) {
  98. case 'a' :
  99. case 'A' :
  100. Operation = FSCTL_REQUEST_OPLOCK_LEVEL_1;
  101. ParamReceived = TRUE;
  102. break;
  103. case 'b' :
  104. case 'B' :
  105. Operation = FSCTL_REQUEST_OPLOCK_LEVEL_2;
  106. ParamReceived = TRUE;
  107. break;
  108. case 'c' :
  109. case 'C' :
  110. Operation = FSCTL_REQUEST_BATCH_OPLOCK;
  111. ParamReceived = TRUE;
  112. break;
  113. case 'd' :
  114. case 'D' :
  115. Operation = FSCTL_REQUEST_FILTER_OPLOCK;
  116. ParamReceived = TRUE;
  117. break;
  118. case 'e' :
  119. case 'E' :
  120. Operation = FSCTL_OPLOCK_BREAK_ACKNOWLEDGE;
  121. ParamReceived = TRUE;
  122. break;
  123. case 'f' :
  124. case 'F' :
  125. Operation = FSCTL_OPBATCH_ACK_CLOSE_PENDING;
  126. ParamReceived = TRUE;
  127. break;
  128. case 'g' :
  129. case 'G' :
  130. Operation = FSCTL_OPLOCK_BREAK_NOTIFY;
  131. ParamReceived = TRUE;
  132. break;
  133. case 'h' :
  134. case 'H' :
  135. Operation = FSCTL_OPLOCK_BREAK_ACK_NO_2;
  136. ParamReceived = TRUE;
  137. break;
  138. case 'z' :
  139. case 'Z' :
  140. ParamReceived = FALSE;
  141. Operation = (ULONG) -1;
  142. break;
  143. default :
  144. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  145. SwitchBool = FALSE;
  146. }
  147. if (!SwitchBool) {
  148. break;
  149. }
  150. ParamBuffer++;
  151. }
  152. break;
  153. //
  154. // Update the file handle index.
  155. //
  156. case 'i' :
  157. case 'I' :
  158. //
  159. // Move to the next character, as long as there
  160. // are no white spaces continue analyzing letters.
  161. // On the first bad letter, skip to the next
  162. // parameter.
  163. //
  164. ParamBuffer++;
  165. FileHandleIndex = AsciiToInteger( ParamBuffer );
  166. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  167. break;
  168. case 'v' :
  169. case 'V' :
  170. //
  171. // Legal values for params are T/t or F/f.
  172. //
  173. ParamBuffer++;
  174. if (*ParamBuffer == 'T'
  175. || *ParamBuffer == 't') {
  176. VerboseResults = TRUE;
  177. ParamBuffer++;
  178. } else if (*ParamBuffer == 'F'
  179. || *ParamBuffer == 'f') {
  180. VerboseResults = FALSE;
  181. ParamBuffer++;
  182. }
  183. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  184. break;
  185. case 'y' :
  186. case 'Y' :
  187. //
  188. // Set the display parms flag and jump over this
  189. // character.
  190. //
  191. DisplayParms = TRUE;
  192. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  193. break;
  194. case 'z' :
  195. case 'Z' :
  196. //
  197. // Set flag for more input and jump over this char.
  198. //
  199. LastInput = FALSE;
  200. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  201. break;
  202. default :
  203. //
  204. // Swallow to the next white space and continue the
  205. // loop.
  206. //
  207. ParamBuffer = SwallowNonWhite( ParamBuffer, &DummyCount );
  208. }
  209. }
  210. //
  211. // Else the text is invalid, skip the entire block.
  212. //
  213. //
  214. //
  215. // Else if there is no input then exit.
  216. //
  217. } else if (LastInput) {
  218. break;
  219. //
  220. // Else try to read another line for open parameters.
  221. //
  222. } else {
  223. }
  224. }
  225. //
  226. // If no parameters were received then display the syntax message.
  227. //
  228. if (!ParamReceived) {
  229. printf( "\n Usage: oplk -i<digits> -o<char> [options]*\n" );
  230. printf( "\n Options:" );
  231. printf( "\n -i<digits> Open file handle" );
  232. printf( "\n -o<chars> Oplock operation" );
  233. printf( "\n -v[t|f] Verbose results" );
  234. printf( "\n -y Display parameters to query" );
  235. printf( "\n -z Additional input line" );
  236. printf( "\n\n" );
  237. //
  238. // Else process the call.
  239. //
  240. } else {
  241. NTSTATUS Status;
  242. SIZE_T RegionSize;
  243. ULONG TempIndex;
  244. USHORT BufferIndex;
  245. HANDLE ThreadHandle;
  246. ULONG ThreadId;
  247. RegionSize = sizeof( OPLOCK );
  248. Status = AllocateBuffer( 0, &RegionSize, &TempIndex );
  249. BufferIndex = (USHORT) TempIndex;
  250. if (!NT_SUCCESS( Status )) {
  251. printf("\n\tInputOplock: Unable to allocate async structure" );
  252. } else {
  253. Oplock = (POPLOCK) Buffers[BufferIndex].Buffer;
  254. Oplock->FileHandleIndex = FileHandleIndex;
  255. Oplock->VerboseResults = VerboseResults;
  256. Oplock->BufferIndex = BufferIndex;
  257. if (DisplayParms) {
  258. printf( "\nOplock Operation Parameters" );
  259. printf( "\n Handle index -> %ld", FileHandleIndex );
  260. printf( "\n Oplock operation -> %ld", Operation );
  261. printf( "\n Structure buffer index -> %d", BufferIndex );
  262. printf( "\n\n" );
  263. }
  264. switch (Operation) {
  265. case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
  266. ThreadHandle = CreateThread( NULL,
  267. 0,
  268. RequestOplockI,
  269. Oplock,
  270. 0,
  271. &ThreadId );
  272. break;
  273. case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
  274. ThreadHandle = CreateThread( NULL,
  275. 0,
  276. RequestOplockII,
  277. Oplock,
  278. 0,
  279. &ThreadId );
  280. break;
  281. case FSCTL_REQUEST_BATCH_OPLOCK :
  282. ThreadHandle = CreateThread( NULL,
  283. 0,
  284. RequestBatchOplock,
  285. Oplock,
  286. 0,
  287. &ThreadId );
  288. break;
  289. case FSCTL_REQUEST_FILTER_OPLOCK :
  290. ThreadHandle = CreateThread( NULL,
  291. 0,
  292. RequestFilterOplock,
  293. Oplock,
  294. 0,
  295. &ThreadId );
  296. break;
  297. case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
  298. ThreadHandle = CreateThread( NULL,
  299. 0,
  300. AcknowledgeOplockBreak,
  301. Oplock,
  302. 0,
  303. &ThreadId );
  304. break;
  305. case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
  306. ThreadHandle = CreateThread( NULL,
  307. 0,
  308. AcknowledgeOpBatchBreakPending,
  309. Oplock,
  310. 0,
  311. &ThreadId );
  312. break;
  313. case FSCTL_OPLOCK_BREAK_NOTIFY :
  314. ThreadHandle = CreateThread( NULL,
  315. 0,
  316. OplockBreakNotify,
  317. Oplock,
  318. 0,
  319. &ThreadId );
  320. break;
  321. case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
  322. ThreadHandle = CreateThread( NULL,
  323. 0,
  324. AcknowledgeOplockBreakNo2,
  325. Oplock,
  326. 0,
  327. &ThreadId );
  328. break;
  329. default :
  330. printf( "\nInputOplock: Invalid operation\n" );
  331. return;
  332. }
  333. if (ThreadHandle == 0) {
  334. printf( "\nInputOplock: Spawning thread fails -> %d\n", GetLastError() );
  335. }
  336. }
  337. }
  338. return;
  339. }
  340. VOID
  341. RequestOplockI (
  342. IN POPLOCK Oplock
  343. )
  344. {
  345. HANDLE Event;
  346. NTSTATUS Status;
  347. IO_STATUS_BLOCK IoSb;
  348. IoSb.Status = 0;
  349. IoSb.Information = 0;
  350. Status = NtCreateEvent( &Event,
  351. SYNCHRONIZE
  352. | GENERIC_READ
  353. | GENERIC_WRITE,
  354. NULL,
  355. NotificationEvent,
  356. FALSE );
  357. if (!NT_SUCCESS( Status )) {
  358. bprint "\nRequestOplockI: NtCreateEvent failed -> %08lx\n", Status );
  359. } else {
  360. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  361. Event,
  362. NULL,
  363. NULL,
  364. &IoSb,
  365. FSCTL_REQUEST_OPLOCK_LEVEL_1,
  366. NULL,
  367. 0,
  368. NULL,
  369. 0 );
  370. if (Oplock->VerboseResults) {
  371. bprint "\nRequestOplockI: Status -> %08lx\n", Status );
  372. if (NT_SUCCESS( Status )) {
  373. if ((Status = NtWaitForSingleObject( Event,
  374. FALSE,
  375. NULL )) != STATUS_SUCCESS) {
  376. bprint "\n\tRequestOplockI: Wait for event failed -> %08lx", Status );
  377. }
  378. }
  379. if (NT_SUCCESS( Status )) {
  380. bprint "\nRequestOplockI: IoSb.Status -> %08lx", IoSb.Status );
  381. bprint "\nRequestOplockI: IoSb.Information -> %08lx", IoSb.Information );
  382. }
  383. bprint "\n" );
  384. }
  385. }
  386. DeallocateBuffer( Oplock->BufferIndex );
  387. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  388. bprint "\nRequestOplockI: Thread not terminated\n" );
  389. }
  390. VOID
  391. RequestBatchOplock (
  392. IN POPLOCK Oplock
  393. )
  394. {
  395. HANDLE Event;
  396. NTSTATUS Status;
  397. IO_STATUS_BLOCK IoSb;
  398. IoSb.Status = 0;
  399. IoSb.Information = 0;
  400. Status = NtCreateEvent( &Event,
  401. SYNCHRONIZE
  402. | GENERIC_READ
  403. | GENERIC_WRITE,
  404. NULL,
  405. NotificationEvent,
  406. FALSE );
  407. if (!NT_SUCCESS( Status )) {
  408. bprint "\nRequestBatchOplock: NtCreateEvent failed -> %08lx\n", Status );
  409. } else {
  410. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  411. Event,
  412. NULL,
  413. NULL,
  414. &IoSb,
  415. FSCTL_REQUEST_BATCH_OPLOCK,
  416. NULL,
  417. 0,
  418. NULL,
  419. 0 );
  420. if (Oplock->VerboseResults) {
  421. bprint "\nRequestBatchOplock: Status -> %08lx\n", Status );
  422. if (NT_SUCCESS( Status )) {
  423. if ((Status = NtWaitForSingleObject( Event,
  424. FALSE,
  425. NULL )) != STATUS_SUCCESS) {
  426. bprint "\n\tRequestBatchOplock: Wait for event failed -> %08lx", Status );
  427. }
  428. }
  429. if (NT_SUCCESS( Status )) {
  430. bprint "\nRequestBatchOplock: IoSb.Status -> %08lx", IoSb.Status );
  431. bprint "\nRequestBatchOplock: IoSb.Information -> %08lx", IoSb.Information );
  432. }
  433. bprint "\n" );
  434. }
  435. }
  436. DeallocateBuffer( Oplock->BufferIndex );
  437. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  438. bprint "\nRequestBatchOplock: Thread not terminated\n" );
  439. }
  440. VOID
  441. RequestFilterOplock (
  442. IN POPLOCK Oplock
  443. )
  444. {
  445. HANDLE Event;
  446. NTSTATUS Status;
  447. IO_STATUS_BLOCK IoSb;
  448. IoSb.Status = 0;
  449. IoSb.Information = 0;
  450. Status = NtCreateEvent( &Event,
  451. SYNCHRONIZE
  452. | GENERIC_READ
  453. | GENERIC_WRITE,
  454. NULL,
  455. NotificationEvent,
  456. FALSE );
  457. if (!NT_SUCCESS( Status )) {
  458. bprint "\nRequestFilterOplock: NtCreateEvent failed -> %08lx\n", Status );
  459. } else {
  460. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  461. Event,
  462. NULL,
  463. NULL,
  464. &IoSb,
  465. FSCTL_REQUEST_FILTER_OPLOCK,
  466. NULL,
  467. 0,
  468. NULL,
  469. 0 );
  470. if (Oplock->VerboseResults) {
  471. bprint "\nRequestFilterOplock: Status -> %08lx\n", Status );
  472. if (NT_SUCCESS( Status )) {
  473. if ((Status = NtWaitForSingleObject( Event,
  474. FALSE,
  475. NULL )) != STATUS_SUCCESS) {
  476. bprint "\n\tRequestFilterOplock: Wait for event failed -> %08lx", Status );
  477. }
  478. if (NT_SUCCESS( Status )) {
  479. bprint "\nRequestFilterOplock: IoSb.Status -> %08lx", IoSb.Status );
  480. bprint "\nRequestFilterOplock: IoSb.Information -> %08lx", IoSb.Information );
  481. }
  482. }
  483. bprint "\n" );
  484. }
  485. }
  486. DeallocateBuffer( Oplock->BufferIndex );
  487. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  488. bprint "\nRequestFilterOplock: Thread not terminated\n" );
  489. }
  490. VOID
  491. RequestOplockII (
  492. IN POPLOCK Oplock
  493. )
  494. {
  495. HANDLE Event;
  496. NTSTATUS Status;
  497. IO_STATUS_BLOCK IoSb;
  498. IoSb.Status = 0;
  499. IoSb.Information = 0;
  500. Status = NtCreateEvent( &Event,
  501. SYNCHRONIZE
  502. | GENERIC_READ
  503. | GENERIC_WRITE,
  504. NULL,
  505. NotificationEvent,
  506. FALSE );
  507. if (!NT_SUCCESS( Status )) {
  508. bprint "\nRequestOplockII: NtCreateEvent failed -> %08lx\n", Status );
  509. } else {
  510. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  511. Event,
  512. NULL,
  513. NULL,
  514. &IoSb,
  515. FSCTL_REQUEST_OPLOCK_LEVEL_2,
  516. NULL,
  517. 0,
  518. NULL,
  519. 0 );
  520. if (Oplock->VerboseResults) {
  521. bprint "\nRequestOplockII: Status -> %08lx\n", Status );
  522. if (NT_SUCCESS( Status )) {
  523. if ((Status = NtWaitForSingleObject( Event,
  524. FALSE,
  525. NULL )) != STATUS_SUCCESS) {
  526. bprint "\n\tRequestOplockII: Wait for event failed -> %08lx", Status );
  527. }
  528. if (NT_SUCCESS( Status )) {
  529. bprint "\nRequestOplockII: IoSb.Status -> %08lx", IoSb.Status );
  530. bprint "\nRequestOplockII: IoSb.Information -> %08lx", IoSb.Information );
  531. }
  532. }
  533. bprint "\n" );
  534. }
  535. }
  536. DeallocateBuffer( Oplock->BufferIndex );
  537. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  538. bprint "\nRequestOplockII: Thread not terminated\n" );
  539. }
  540. VOID
  541. AcknowledgeOplockBreak (
  542. IN POPLOCK Oplock
  543. )
  544. {
  545. HANDLE Event;
  546. NTSTATUS Status;
  547. IO_STATUS_BLOCK IoSb;
  548. IoSb.Status = 0;
  549. IoSb.Information = 0;
  550. Status = NtCreateEvent( &Event,
  551. SYNCHRONIZE
  552. | GENERIC_READ
  553. | GENERIC_WRITE,
  554. NULL,
  555. NotificationEvent,
  556. FALSE );
  557. if (!NT_SUCCESS( Status )) {
  558. bprint "\nAcknowledgeOplockBreak: NtCreateEvent failed -> %08lx\n", Status );
  559. } else {
  560. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  561. Event,
  562. NULL,
  563. NULL,
  564. &IoSb,
  565. FSCTL_OPLOCK_BREAK_ACKNOWLEDGE,
  566. NULL,
  567. 0,
  568. NULL,
  569. 0 );
  570. if (Oplock->VerboseResults) {
  571. bprint "\nAcknowledgeOplockBreak: Status -> %08lx\n", Status );
  572. if (NT_SUCCESS( Status )) {
  573. if ((Status = NtWaitForSingleObject( Event,
  574. FALSE,
  575. NULL )) != STATUS_SUCCESS) {
  576. bprint "\n\tAcknowledgeOplockBreak: Wait for event failed -> %08lx", Status );
  577. }
  578. if (NT_SUCCESS( Status )) {
  579. bprint "\nAcknowledgeOplockBreak: IoSb.Status -> %08lx", IoSb.Status );
  580. bprint "\nAcknowledgeOplockBreak: IoSb.Information -> %08lx", IoSb.Information );
  581. }
  582. }
  583. bprint "\n" );
  584. }
  585. }
  586. DeallocateBuffer( Oplock->BufferIndex );
  587. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  588. bprint "\nAcknowledgeOplockBreak: Thread not terminated\n" );
  589. }
  590. VOID
  591. AcknowledgeOplockBreakNo2 (
  592. IN POPLOCK Oplock
  593. )
  594. {
  595. HANDLE Event;
  596. NTSTATUS Status;
  597. IO_STATUS_BLOCK IoSb;
  598. IoSb.Status = 0;
  599. IoSb.Information = 0;
  600. Status = NtCreateEvent( &Event,
  601. SYNCHRONIZE
  602. | GENERIC_READ
  603. | GENERIC_WRITE,
  604. NULL,
  605. NotificationEvent,
  606. FALSE );
  607. if (!NT_SUCCESS( Status )) {
  608. bprint "\nAcknowledgeOplockBreakNo2: NtCreateEvent failed -> %08lx\n", Status );
  609. } else {
  610. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  611. Event,
  612. NULL,
  613. NULL,
  614. &IoSb,
  615. FSCTL_OPLOCK_BREAK_ACK_NO_2,
  616. NULL,
  617. 0,
  618. NULL,
  619. 0 );
  620. if (Oplock->VerboseResults) {
  621. bprint "\nAcknowledgeOplockBreakNo2: Status -> %08lx\n", Status );
  622. if (NT_SUCCESS( Status )) {
  623. if ((Status = NtWaitForSingleObject( Event,
  624. FALSE,
  625. NULL )) != STATUS_SUCCESS) {
  626. bprint "\n\tAcknowledgeOplockBreakNo2: Wait for event failed -> %08lx", Status );
  627. }
  628. if (NT_SUCCESS( Status )) {
  629. bprint "\nAcknowledgeOplockBreakNo2: IoSb.Status -> %08lx", IoSb.Status );
  630. bprint "\nAcknowledgeOplockBreakNo2: IoSb.Information -> %08lx", IoSb.Information );
  631. }
  632. }
  633. bprint "\n" );
  634. }
  635. }
  636. DeallocateBuffer( Oplock->BufferIndex );
  637. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  638. bprint "\nAcknowledgeOplockBreak: Thread not terminated\n" );
  639. }
  640. VOID
  641. AcknowledgeOpBatchBreakPending (
  642. IN POPLOCK Oplock
  643. )
  644. {
  645. HANDLE Event;
  646. NTSTATUS Status;
  647. IO_STATUS_BLOCK IoSb;
  648. IoSb.Status = 0;
  649. IoSb.Information = 0;
  650. Status = NtCreateEvent( &Event,
  651. SYNCHRONIZE
  652. | GENERIC_READ
  653. | GENERIC_WRITE,
  654. NULL,
  655. NotificationEvent,
  656. FALSE );
  657. if (!NT_SUCCESS( Status )) {
  658. bprint "\nAcknowledgeOpBatchBreakPending: NtCreateEvent failed -> %08lx\n", Status );
  659. } else {
  660. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  661. Event,
  662. NULL,
  663. NULL,
  664. &IoSb,
  665. FSCTL_OPBATCH_ACK_CLOSE_PENDING,
  666. NULL,
  667. 0,
  668. NULL,
  669. 0 );
  670. if (Oplock->VerboseResults) {
  671. bprint "\nAcknowledgeOpBatchBreakPending: Status -> %08lx\n", Status );
  672. if (NT_SUCCESS( Status )) {
  673. if ((Status = NtWaitForSingleObject( Event,
  674. FALSE,
  675. NULL )) != STATUS_SUCCESS) {
  676. bprint "\n\tAcknowledgeOpBatchBreakPending: Wait for event failed -> %08lx", Status );
  677. }
  678. if (NT_SUCCESS( Status )) {
  679. bprint "\nAcknowledgeOpBatchBreakPending: IoSb.Status -> %08lx", IoSb.Status );
  680. bprint "\nAcknowledgeOpBatchBreakPending: IoSb.Information -> %08lx", IoSb.Information );
  681. }
  682. }
  683. bprint "\n" );
  684. }
  685. }
  686. DeallocateBuffer( Oplock->BufferIndex );
  687. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  688. bprint "\nAcknowledgeOpBatchBreakPending: Thread not terminated\n" );
  689. }
  690. VOID
  691. OplockBreakNotify (
  692. IN POPLOCK Oplock
  693. )
  694. {
  695. HANDLE Event;
  696. NTSTATUS Status;
  697. IO_STATUS_BLOCK IoSb;
  698. IoSb.Status = 0;
  699. IoSb.Information = 0;
  700. Status = NtCreateEvent( &Event,
  701. SYNCHRONIZE
  702. | GENERIC_READ
  703. | GENERIC_WRITE,
  704. NULL,
  705. NotificationEvent,
  706. FALSE );
  707. if (!NT_SUCCESS( Status )) {
  708. bprint "\nOplockBreakNotify: NtCreateEvent failed -> %08lx\n", Status );
  709. } else {
  710. Status = NtFsControlFile( Handles[Oplock->FileHandleIndex].Handle,
  711. Event,
  712. NULL,
  713. NULL,
  714. &IoSb,
  715. FSCTL_OPLOCK_BREAK_NOTIFY,
  716. NULL,
  717. 0,
  718. NULL,
  719. 0 );
  720. if (Oplock->VerboseResults) {
  721. bprint "\nOplockBreakNotify: Status -> %08lx\n", Status );
  722. if (NT_SUCCESS( Status )) {
  723. if ((Status = NtWaitForSingleObject( Event,
  724. FALSE,
  725. NULL )) != STATUS_SUCCESS) {
  726. bprint "\n\tOplockBreakNotify: Wait for event failed -> %08lx", Status );
  727. }
  728. if (NT_SUCCESS( Status )) {
  729. bprint "\nOplockBreakNotify: IoSb.Status -> %08lx", IoSb.Status );
  730. bprint "\nOplockBreakNotify: IoSb.Information -> %08lx", IoSb.Information );
  731. }
  732. }
  733. bprint "\n" );
  734. }
  735. }
  736. DeallocateBuffer( Oplock->BufferIndex );
  737. NtTerminateThread( NtCurrentThread(), STATUS_SUCCESS );
  738. bprint "\nOplockBreakNotify: Thread not terminated\n" );
  739. }