1 /* 2 * PROJECT: ReactOS Sound System "MME Buddy" Library 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: include/reactos/libs/sound/mmebuddy.h 5 * 6 * PURPOSE: Header for the "MME Buddy" helper library (located in 7 * lib/drivers/sound/mmebuddy) 8 * 9 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 10 * 11 * HISTORY: 4 July 2008 - Created 12 * 31 Dec 2008 - Split off NT4-specific code into a separate library 13 * 14 * NOTES: MME Buddy was the best name I could come up with... 15 * The structures etc. here should be treated as internal to the 16 * library so should not be directly accessed elsewhere. Perhaps they 17 * can be moved to an internal header? 18 */ 19 20 #ifndef ROS_AUDIO_MMEBUDDY_H 21 #define ROS_AUDIO_MMEBUDDY_H 22 23 /* 24 Some memory allocation helper macros 25 */ 26 27 #define AllocateStruct(thing) \ 28 (thing*) AllocateMemory(sizeof(thing)) 29 30 #define StringLengthToBytes(chartype, string_length) \ 31 ( ( string_length + 1 ) * sizeof(chartype) ) 32 33 #define AllocateWideString(string_length) \ 34 (PWSTR) AllocateMemory(StringLengthToBytes(WCHAR, string_length)) 35 36 #define ZeroWideString(string) \ 37 ZeroMemory(string, StringLengthToBytes(WCHAR, wcslen(string))) 38 39 #define CopyWideString(dest, source) \ 40 CopyMemory(dest, source, StringLengthToBytes(WCHAR, wcslen(source))) 41 42 43 /* 44 Helps find the minimum/maximum of two values 45 */ 46 47 #define MinimumOf(value_a, value_b) \ 48 ( value_a < value_b ? value_a : value_b ) 49 50 #define MaximumOf(value_a, value_b) \ 51 ( value_a > value_b ? value_a : value_b ) 52 53 54 /* 55 Convert a device type into a zero-based array index 56 */ 57 58 #define SOUND_DEVICE_TYPE_TO_INDEX(x) \ 59 ( x - MIN_SOUND_DEVICE_TYPE ) 60 61 #define INDEX_TO_SOUND_DEVICE_TYPE(x) \ 62 ( x + MIN_SOUND_DEVICE_TYPE ) 63 64 65 /* 66 Validation 67 */ 68 69 #define IsValidSoundDeviceType IS_VALID_SOUND_DEVICE_TYPE 70 71 #define VALIDATE_MMSYS_PARAMETER(parameter_condition) \ 72 { \ 73 if ( ! (parameter_condition) ) \ 74 { \ 75 SND_ERR(L"FAILED parameter check: %hS at File %S Line %lu\n", #parameter_condition, __FILE__, __LINE__); \ 76 return MMSYSERR_INVALPARAM; \ 77 } \ 78 } 79 80 #define MMSUCCESS(result) \ 81 ( result == MMSYSERR_NOERROR ) 82 83 84 /* 85 Types and Structures 86 */ 87 88 typedef UCHAR MMDEVICE_TYPE, *PMMDEVICE_TYPE; 89 struct _SOUND_DEVICE; 90 struct _SOUND_DEVICE_INSTANCE; 91 92 93 #define DEFINE_GETCAPS_FUNCTYPE(func_typename, caps_type) \ 94 typedef MMRESULT (*func_typename)( \ 95 IN struct _SOUND_DEVICE* SoundDevice, \ 96 IN DWORD DeviceId, \ 97 OUT caps_type Capabilities, \ 98 IN DWORD CapabilitiesSize); 99 100 /* This one is for those of us who don't care */ 101 DEFINE_GETCAPS_FUNCTYPE(MMGETCAPS_FUNC, PVOID); 102 103 /* These are for those of us that do */ 104 DEFINE_GETCAPS_FUNCTYPE(MMGETWAVEOUTCAPS_FUNC, LPWAVEOUTCAPS); 105 DEFINE_GETCAPS_FUNCTYPE(MMGETWAVEINCAPS_FUNC, LPWAVEINCAPS ); 106 DEFINE_GETCAPS_FUNCTYPE(MMGETMIDIOUTCAPS_FUNC, LPMIDIOUTCAPS); 107 DEFINE_GETCAPS_FUNCTYPE(MMGETMIDIINCAPS_FUNC, LPMIDIINCAPS ); 108 109 struct _SOUND_DEVICE; 110 struct _SOUND_DEVICE_INSTANCE; 111 112 113 /* 114 By extending the OVERLAPPED structure, it becomes possible to provide the 115 I/O completion routines with additional information. 116 */ 117 118 typedef struct _SOUND_OVERLAPPED 119 { 120 OVERLAPPED Standard; 121 struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance; 122 PWAVEHDR Header; 123 124 LPOVERLAPPED_COMPLETION_ROUTINE OriginalCompletionRoutine; 125 PVOID CompletionContext; 126 127 } SOUND_OVERLAPPED, *PSOUND_OVERLAPPED; 128 129 typedef MMRESULT (*WAVE_COMMIT_FUNC)( 130 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 131 IN PVOID OffsetPtr, 132 IN DWORD Bytes, 133 IN PSOUND_OVERLAPPED Overlap, 134 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); 135 136 typedef MMRESULT (*MMMIXERQUERY_FUNC) ( 137 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 138 IN DWORD DeviceId, 139 IN UINT uMsg, 140 IN LPVOID Parameter, 141 IN DWORD Flags); 142 143 typedef MMRESULT (*MMWAVEQUERYFORMATSUPPORT_FUNC)( 144 IN struct _SOUND_DEVICE* Device, 145 IN PWAVEFORMATEX WaveFormat, 146 IN DWORD WaveFormatSize); 147 148 typedef MMRESULT (*MMWAVESETFORMAT_FUNC)( 149 IN struct _SOUND_DEVICE_INSTANCE* Instance, 150 IN DWORD DeviceId, 151 IN PWAVEFORMATEX WaveFormat, 152 IN DWORD WaveFormatSize); 153 154 typedef MMRESULT (*MMOPEN_FUNC)( 155 IN struct _SOUND_DEVICE* SoundDevice, 156 OUT PVOID* Handle); 157 158 typedef MMRESULT (*MMCLOSE_FUNC)( 159 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 160 IN PVOID Handle); /* not sure about this */ 161 162 typedef MMRESULT (*MMWAVEHEADER_FUNC)( 163 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 164 IN PWAVEHDR WaveHeader); 165 166 typedef MMRESULT (*MMBUFFER_FUNC)( 167 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 168 IN PVOID Buffer, 169 IN DWORD Length); 170 171 typedef MMRESULT(*MMGETPOS_FUNC)( 172 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 173 IN MMTIME* Time); 174 175 176 typedef MMRESULT(*MMSETSTATE_FUNC)( 177 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 178 IN BOOL bStart); 179 180 181 typedef MMRESULT(*MMQUERYDEVICEINTERFACESTRING_FUNC)( 182 IN MMDEVICE_TYPE DeviceType, 183 IN DWORD DeviceId, 184 IN LPWSTR Interface, 185 IN DWORD InterfaceLength, 186 OUT DWORD * InterfaceSize); 187 188 typedef MMRESULT(*MMRESETSTREAM_FUNC)( 189 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 190 IN MMDEVICE_TYPE DeviceType, 191 IN BOOLEAN bStartReset); 192 193 typedef MMRESULT(*MMGETVOLUME_FUNC)( 194 _In_ struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 195 _In_ DWORD DeviceId, 196 _Out_ PDWORD pdwVolume); 197 198 typedef MMRESULT(*MMSETVOLUME_FUNC)( 199 _In_ struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 200 _In_ DWORD DeviceId, 201 _In_ DWORD dwVolume); 202 203 typedef struct _MMFUNCTION_TABLE 204 { 205 union 206 { 207 MMGETCAPS_FUNC GetCapabilities; 208 MMGETWAVEOUTCAPS_FUNC GetWaveOutCapabilities; 209 MMGETWAVEINCAPS_FUNC GetWaveInCapabilities; 210 MMGETMIDIOUTCAPS_FUNC GetMidiOutCapabilities; 211 MMGETMIDIINCAPS_FUNC GetMidiInCapabilities; 212 }; 213 214 MMOPEN_FUNC Open; 215 MMCLOSE_FUNC Close; 216 217 MMWAVEQUERYFORMATSUPPORT_FUNC QueryWaveFormatSupport; 218 MMWAVESETFORMAT_FUNC SetWaveFormat; 219 220 MMMIXERQUERY_FUNC QueryMixerInfo; 221 222 WAVE_COMMIT_FUNC CommitWaveBuffer; 223 224 MMGETPOS_FUNC GetPos; 225 MMSETSTATE_FUNC SetState; 226 MMQUERYDEVICEINTERFACESTRING_FUNC GetDeviceInterfaceString; 227 MMRESETSTREAM_FUNC ResetStream; 228 229 MMGETVOLUME_FUNC GetVolume; 230 MMSETVOLUME_FUNC SetVolume; 231 232 // Redundant 233 //MMWAVEHEADER_FUNC PrepareWaveHeader; 234 //MMWAVEHEADER_FUNC UnprepareWaveHeader; 235 //MMWAVEHEADER_FUNC WriteWaveHeader; 236 237 //MMWAVEHEADER_FUNC SubmitWaveHeaderToDevice; 238 //MMBUFFER_FUNC CompleteBuffer; 239 } MMFUNCTION_TABLE, *PMMFUNCTION_TABLE; 240 241 242 243 typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER)( 244 IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance, 245 IN PVOID Parameter); 246 247 typedef struct _SOUND_THREAD 248 { 249 HANDLE Handle; 250 BOOL Running; 251 252 struct 253 { 254 HANDLE Ready; 255 HANDLE Request; 256 HANDLE Done; 257 } Events; 258 259 struct 260 { 261 SOUND_THREAD_REQUEST_HANDLER Handler; 262 struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance; 263 PVOID Parameter; 264 MMRESULT Result; 265 } Request; 266 } SOUND_THREAD, *PSOUND_THREAD; 267 268 typedef struct _SOUND_DEVICE 269 { 270 struct _SOUND_DEVICE* Next; 271 struct _SOUND_DEVICE_INSTANCE* HeadInstance; 272 struct _SOUND_DEVICE_INSTANCE* TailInstance; 273 MMDEVICE_TYPE Type; 274 PVOID Identifier; /* Path for NT4 drivers */ 275 /*PWSTR Path;*/ 276 MMFUNCTION_TABLE FunctionTable; 277 } SOUND_DEVICE, *PSOUND_DEVICE; 278 279 typedef struct _SOUND_DEVICE_INSTANCE 280 { 281 struct _SOUND_DEVICE_INSTANCE* Next; 282 struct _SOUND_DEVICE* Device; 283 PVOID Handle; 284 struct _SOUND_THREAD* Thread; 285 286 /* Stuff generously donated to us from WinMM */ 287 struct 288 { 289 HDRVR Handle; 290 DWORD Flags; 291 DWORD_PTR ClientCallback; 292 DWORD_PTR ClientCallbackInstanceData; 293 } WinMM; 294 295 /* DO NOT TOUCH THESE OUTSIDE OF THE SOUND THREAD */ 296 297 union 298 { 299 PWAVEHDR HeadWaveHeader; 300 }; 301 302 union 303 { 304 PWAVEHDR TailWaveHeader; 305 }; 306 307 PWAVEHDR WaveLoopStart; 308 //PWAVEHDR CurrentWaveHeader; 309 DWORD OutstandingBuffers; 310 DWORD LoopsRemaining; 311 DWORD FrameSize; 312 DWORD BufferCount; 313 WAVEFORMATEX WaveFormatEx; 314 HANDLE hNotifyEvent; 315 HANDLE hStopEvent; 316 HANDLE hResetEvent; 317 BOOL ResetInProgress; 318 BOOL bPaused; 319 } SOUND_DEVICE_INSTANCE, *PSOUND_DEVICE_INSTANCE; 320 321 /* This lives in WAVEHDR.reserved */ 322 typedef struct _WAVEHDR_EXTENSION 323 { 324 DWORD BytesCommitted; 325 DWORD BytesCompleted; 326 } WAVEHDR_EXTENSION, *PWAVEHDR_EXTENSION; 327 328 329 /* 330 reentrancy.c 331 */ 332 333 MMRESULT 334 InitEntrypointMutexes(VOID); 335 336 VOID 337 CleanupEntrypointMutexes(VOID); 338 339 VOID 340 AcquireEntrypointMutex( 341 IN MMDEVICE_TYPE DeviceType); 342 343 VOID 344 ReleaseEntrypointMutex( 345 IN MMDEVICE_TYPE DeviceType); 346 347 348 /* 349 mme.c 350 */ 351 352 VOID 353 NotifyMmeClient( 354 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 355 IN UINT Message, 356 IN DWORD_PTR Parameter); 357 358 MMRESULT 359 MmeGetSoundDeviceCapabilities( 360 IN MMDEVICE_TYPE DeviceType, 361 IN DWORD DeviceId, 362 IN PVOID Capabilities, 363 IN DWORD CapabilitiesSize); 364 365 MMRESULT 366 MmeOpenDevice( 367 IN MMDEVICE_TYPE DeviceType, 368 IN UINT DeviceId, 369 IN LPWAVEOPENDESC OpenParameters, 370 IN DWORD Flags, 371 OUT DWORD_PTR* PrivateHandle); 372 373 MMRESULT 374 MmeCloseDevice( 375 IN DWORD_PTR PrivateHandle); 376 377 MMRESULT 378 MmeGetPosition( 379 IN MMDEVICE_TYPE DeviceType, 380 IN DWORD DeviceId, 381 IN DWORD_PTR PrivateHandle, 382 IN MMTIME* Time, 383 IN DWORD Size); 384 385 MMRESULT 386 MmeGetVolume( 387 _In_ MMDEVICE_TYPE DeviceType, 388 _In_ DWORD DeviceId, 389 _In_ DWORD_PTR PrivateHandle, 390 _Out_ DWORD_PTR pdwVolume); 391 392 MMRESULT 393 MmeSetVolume( 394 _In_ MMDEVICE_TYPE DeviceType, 395 _In_ DWORD DeviceId, 396 _In_ DWORD_PTR PrivateHandle, 397 _In_ DWORD_PTR dwVolume); 398 399 MMRESULT 400 MmeGetDeviceInterfaceString( 401 IN MMDEVICE_TYPE DeviceType, 402 IN DWORD DeviceId, 403 IN LPWSTR Interface, 404 IN DWORD InterfaceLength, 405 OUT DWORD * InterfaceSize); 406 407 408 MMRESULT 409 MmeSetState( 410 IN DWORD_PTR PrivateHandle, 411 IN BOOL bStart); 412 413 414 #define MmePrepareWaveHeader(private_handle, header) \ 415 PrepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header) 416 417 #define MmeUnprepareWaveHeader(private_handle, header) \ 418 UnprepareWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header) 419 420 #define MmeWriteWaveHeader(private_handle, header) \ 421 WriteWaveHeader((PSOUND_DEVICE_INSTANCE)private_handle, (PWAVEHDR)header) 422 423 MMRESULT 424 MmeResetWavePlayback( 425 IN DWORD_PTR PrivateHandle); 426 427 428 /* 429 capabilities.c 430 */ 431 432 MMRESULT 433 GetSoundDeviceCapabilities( 434 IN PSOUND_DEVICE SoundDevice, 435 IN DWORD DeviceId, 436 OUT PVOID Capabilities, 437 IN DWORD CapabilitiesSize); 438 439 440 /* 441 devicelist.c 442 */ 443 444 ULONG 445 GetSoundDeviceCount( 446 IN MMDEVICE_TYPE DeviceType); 447 448 BOOLEAN 449 IsValidSoundDevice( 450 IN PSOUND_DEVICE SoundDevice); 451 452 MMRESULT 453 ListSoundDevice( 454 IN MMDEVICE_TYPE DeviceType, 455 IN PVOID Identifier OPTIONAL, 456 OUT PSOUND_DEVICE* SoundDevice OPTIONAL); 457 458 MMRESULT 459 UnlistSoundDevice( 460 IN MMDEVICE_TYPE DeviceType, 461 IN PSOUND_DEVICE SoundDevice); 462 463 MMRESULT 464 UnlistSoundDevices( 465 IN MMDEVICE_TYPE DeviceType); 466 467 VOID 468 UnlistAllSoundDevices(VOID); 469 470 MMRESULT 471 GetSoundDevice( 472 IN MMDEVICE_TYPE DeviceType, 473 IN DWORD DeviceIndex, 474 OUT PSOUND_DEVICE* Device); 475 476 MMRESULT 477 GetSoundDeviceIdentifier( 478 IN PSOUND_DEVICE SoundDevice, 479 OUT PVOID* Identifier); 480 481 MMRESULT 482 GetSoundDeviceType( 483 IN PSOUND_DEVICE SoundDevice, 484 OUT PMMDEVICE_TYPE DeviceType); 485 486 487 /* 488 functiontable.c 489 */ 490 491 MMRESULT 492 SetSoundDeviceFunctionTable( 493 IN PSOUND_DEVICE SoundDevice, 494 IN PMMFUNCTION_TABLE FunctionTable); 495 496 MMRESULT 497 GetSoundDeviceFunctionTable( 498 IN PSOUND_DEVICE SoundDevice, 499 OUT PMMFUNCTION_TABLE* FunctionTable); 500 501 502 /* 503 deviceinstance.c 504 */ 505 506 BOOLEAN 507 IsValidSoundDeviceInstance( 508 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance); 509 510 MMRESULT 511 CreateSoundDeviceInstance( 512 IN PSOUND_DEVICE SoundDevice, 513 OUT PSOUND_DEVICE_INSTANCE* SoundDeviceInstance); 514 515 MMRESULT 516 DestroySoundDeviceInstance( 517 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance); 518 519 MMRESULT 520 DestroyAllSoundDeviceInstances( 521 IN PSOUND_DEVICE SoundDevice); 522 523 MMRESULT 524 GetSoundDeviceFromInstance( 525 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 526 OUT PSOUND_DEVICE* SoundDevice); 527 528 MMRESULT 529 GetSoundDeviceInstanceHandle( 530 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 531 OUT PVOID* Handle); 532 533 MMRESULT 534 SetSoundDeviceInstanceMmeData( 535 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 536 IN HDRVR MmeHandle, 537 IN DWORD_PTR ClientCallback, 538 IN DWORD_PTR ClientCallbackData, 539 IN DWORD Flags); 540 541 542 /* 543 thread.c 544 */ 545 546 MMRESULT 547 CreateSoundThread( 548 OUT PSOUND_THREAD* Thread); 549 550 MMRESULT 551 DestroySoundThread( 552 IN PSOUND_THREAD Thread); 553 554 MMRESULT 555 CallSoundThread( 556 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 557 IN SOUND_THREAD_REQUEST_HANDLER RequestHandler, 558 IN PVOID Parameter OPTIONAL); 559 560 561 /* 562 utility.c 563 */ 564 565 PVOID 566 AllocateMemory( 567 IN UINT Size); 568 569 VOID 570 FreeMemory( 571 IN PVOID Pointer); 572 573 UINT 574 GetMemoryAllocationCount(VOID); 575 576 UINT 577 GetDigitCount( 578 IN UINT Number); 579 580 MMRESULT 581 Win32ErrorToMmResult( 582 IN UINT ErrorCode); 583 584 MMRESULT 585 TranslateInternalMmResult( 586 IN MMRESULT Result); 587 588 589 /* 590 wave/format.c 591 */ 592 593 MMRESULT 594 QueryWaveDeviceFormatSupport( 595 IN PSOUND_DEVICE SoundDevice, 596 IN LPWAVEFORMATEX Format, 597 IN DWORD FormatSize); 598 599 MMRESULT 600 SetWaveDeviceFormat( 601 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 602 IN DWORD DeviceId, 603 IN LPWAVEFORMATEX Format, 604 IN DWORD FormatSize); 605 606 607 /* 608 wave/header.c 609 */ 610 611 MMRESULT 612 EnqueueWaveHeader( 613 PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 614 IN PVOID Parameter); 615 616 VOID 617 CompleteWaveHeader( 618 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 619 IN PWAVEHDR Header); 620 621 MMRESULT 622 PrepareWaveHeader( 623 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 624 IN PWAVEHDR Header); 625 626 MMRESULT 627 UnprepareWaveHeader( 628 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 629 IN PWAVEHDR Header); 630 631 MMRESULT 632 WriteWaveHeader( 633 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 634 IN PWAVEHDR Header); 635 636 637 /* 638 wave/streaming.c 639 */ 640 641 VOID 642 DoWaveStreaming( 643 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance); 644 645 VOID CALLBACK 646 CompleteIO( 647 IN DWORD dwErrorCode, 648 IN DWORD dwNumberOfBytesTransferred, 649 IN LPOVERLAPPED lpOverlapped); 650 651 MMRESULT 652 CommitWaveHeaderToKernelDevice( 653 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 654 IN PWAVEHDR Header, 655 IN WAVE_COMMIT_FUNC CommitFunction); 656 657 MMRESULT 658 WriteFileEx_Committer( 659 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance, 660 IN PVOID OffsetPtr, 661 IN DWORD Length, 662 IN PSOUND_OVERLAPPED Overlap, 663 IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine); 664 665 MMRESULT 666 StopStreaming( 667 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance); 668 669 VOID 670 InitiateSoundStreaming( 671 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance); 672 673 /* 674 kernel.c 675 */ 676 677 MMRESULT 678 OpenKernelSoundDeviceByName( 679 IN PWSTR DevicePath, 680 IN BOOLEAN ReadOnly, 681 OUT PHANDLE Handle); 682 683 MMRESULT 684 OpenKernelSoundDevice( 685 IN PSOUND_DEVICE SoundDevice, 686 IN BOOLEAN ReadOnly, 687 OUT PHANDLE Handle); 688 689 MMRESULT 690 CloseKernelSoundDevice( 691 IN HANDLE Handle); 692 693 MMRESULT 694 SyncOverlappedDeviceIoControl( 695 IN HANDLE SoundDeviceInstance, 696 IN DWORD IoControlCode, 697 IN LPVOID InBuffer, 698 IN DWORD InBufferSize, 699 OUT LPVOID OutBuffer, 700 IN DWORD OutBufferSize, 701 OUT LPDWORD BytesTransferred OPTIONAL); 702 703 704 #endif 705