Consultor Eletrônico



Kbase P168572: Errors after dynamically invoking winmm.dll to play a WAV file.
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   24/06/2010
Status: Unverified

SYMPTOM(s):

Errors after dynamically invoking winmm.dll to play a WAV file.

Sound plays, then errors are raised or procedure crashes.

Procedure crashes when run from the command line.

Protrace is generated when procedure is run from the command line.

Errors received when procedure run in OpenEdge Architect.

'C' Call Stack has been compromised after calling in (6069)

** Incomplete write when writing to the server. (735)

FACT(s) (Environment):

No protrace is generated when procedure is run from Architect.
Architect does not crash.
Dynamically invoking sndPlaySoundA method of winmm.dll using call object.
Code is similar to the following:

DEFINE VARIABLE hCall AS HANDLE NO-UNDO .
def var outval as int64 no-undo .
CREATE CALL hCall.
assign
hCall:library = "winmm.dll"
hCall:call-name = "sndPlaySoundA"
hCall:call-type = DLL-CALL-TYPE
hCall:NUM-PARAMETERS = 3
.
hCall:SET-PARAMETER( 1 , "character", "input", "c:\wav\force.wav" ).
hCall:SET-PARAMETER( 2 , "int64", "input", 1 ).
hCall:SET-PARAMETER( 3 , "int64", "output", outval).
hCall:INVOKE.
DELETE OBJECT hCall.
Windows
OpenEdge 10.2B

CAUSE:

The parameters set in the call object do not match the parameters of the method. The signature for sndPlaySoundA() as defined in MMSystem.h of the Windows SDK is
BOOL WINAPI sndPlaySound(LPCSTR pszSound, UINT fuSound);
Two points are key:

The return type must be specified in the RETURN-VALUE-DLL-TYPE attribute of the call object, not in an output parameter.
sndPlaySoundA uses 32-bit parameters and return value, not 64-bit. Furthermore, the second parameter is an unsigned integer, not a signed one.
Because the parameters and return value did not match what was expected, the call stack was corrupted.

FIX:

Correct the parameters and return value in the call object to match the signature of the method being called. The corrected code should look similar to the following:

&SCOPED-DEFINE SND_SYNC 0
DEFINE VARIABLE hCall AS HANDLE NO-UNDO .
DEFINE VARIABLE outval AS INT64 NO-UNDO .
CREATE CALL hCall.
ASSIGN
hCall:LIBRARY = "winmm.dll"
hCall:CALL-NAME = "sndPlaySoundA"
hCall:CALL-TYPE = DLL-CALL-TYPE
hCall:NUM-PARAMETERS = 2
hCall:RETURN-VALUE-DLL-TYPE = "LONG"
.
hCall:SET-PARAMETER( 1 , "character", "input", "c:\wav\force.wav" ).
hCall:SET-PARAMETER( 2 , "UNSIGNED-LONG", "input", {&SND_SYNC} ).
hCall:INVOKE.
DELETE OBJECT hCall.