dsound8.c 56.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/*
 * Tests basic sound playback in DirectSound.
 * In particular we test each standard Windows sound format to make sure
 * we handle the sound card/driver quirks correctly.
 *
 * Part of this test involves playing test tones. But this only makes
 * sense if someone is going to carefully listen to it, and would only
 * bother everyone else.
 * So this is only done if the test is being run in interactive mode.
 *
 * Copyright (c) 2002-2004 Francois Gouget
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
25
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 27
 */

28 29
#define COBJMACROS
#define NONAMELESSUNION
30
#include <windows.h>
31
#include <stdio.h>
32 33

#include "wine/test.h"
34
#include "mmsystem.h"
35 36
#include "dsound.h"
#include "dsconf.h"
37 38
#include "ks.h"
#include "ksmedia.h"
39

40
#include "initguid.h"
41 42

#include "mediaobj.h"
43 44 45 46 47 48
#include "wingdi.h"
#include "mmdeviceapi.h"
#include "audioclient.h"
#include "propkey.h"
#include "devpkey.h"

49 50
#include "dsound_test.h"

51
static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA,LPVOID)=NULL;
52 53
static HRESULT (WINAPI *pDirectSoundCreate8)(LPCGUID,LPDIRECTSOUND8*,LPUNKNOWN)=NULL;

54 55 56 57 58
int align(int length, int align)
{
    return (length / align) * align;
}

59 60 61 62 63 64 65 66 67
static void IDirectSound8_test(LPDIRECTSOUND8 dso, BOOL initialized,
                               LPCGUID lpGuid)
{
    HRESULT rc;
    DSCAPS dscaps;
    int ref;
    IUnknown * unknown;
    IDirectSound * ds;
    IDirectSound8 * ds8;
68
    DWORD speaker_config, new_speaker_config, ref_speaker_config;
69 70 71 72
    DWORD certified;

    /* Try to Query for objects */
    rc=IDirectSound8_QueryInterface(dso,&IID_IUnknown,(LPVOID*)&unknown);
73
    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IUnknown) failed: %08x\n", rc);
74 75 76 77
    if (rc==DS_OK)
        IDirectSound8_Release(unknown);

    rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound,(LPVOID*)&ds);
78
    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound) failed: %08x\n", rc);
79 80 81 82 83
    if (rc==DS_OK)
        IDirectSound_Release(ds);

    rc=IDirectSound8_QueryInterface(dso,&IID_IDirectSound8,(LPVOID*)&ds8);
    ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSound8) "
84
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
85 86 87 88
    if (rc==DS_OK)
        IDirectSound8_Release(ds8);

    if (initialized == FALSE) {
89
        /* try uninitialized object */
90 91
        rc=IDirectSound8_GetCaps(dso,0);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps(NULL) "
92
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
93 94 95

        rc=IDirectSound8_GetCaps(dso,&dscaps);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetCaps() "
96
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
97 98 99

        rc=IDirectSound8_Compact(dso);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_Compact() "
100
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
101 102 103

        rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_GetSpeakerConfig() "
104
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
105 106 107

        rc=IDirectSound8_VerifyCertification(dso, &certified);
        ok(rc==DSERR_UNINITIALIZED,"IDirectSound8_VerifyCertification() "
108
           "should have returned DSERR_UNINITIALIZED, returned: %08x\n", rc);
109 110

        rc=IDirectSound8_Initialize(dso,lpGuid);
111
        ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
112
           "IDirectSound8_Initialize() failed: %08x\n",rc);
113 114
        if (rc==DSERR_NODRIVER) {
            trace("  No Driver\n");
115
            goto EXIT;
116 117
        } else if (rc==E_FAIL) {
            trace("  No Device\n");
118
            goto EXIT;
119
        } else if (rc==DSERR_ALLOCATED) {
120
            trace("  Already In Use\n");
121
            goto EXIT;
Jakob Eriksson's avatar
Jakob Eriksson committed
122
        }
123 124
    }

125 126
    rc=IDirectSound8_Initialize(dso,lpGuid);
    ok(rc==DSERR_ALREADYINITIALIZED, "IDirectSound8_Initialize() "
127
       "should have returned DSERR_ALREADYINITIALIZED: %08x\n", rc);
128

129 130 131
    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSound8_GetCaps(dso,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
132
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
133 134 135 136 137 138

    ZeroMemory(&dscaps, sizeof(dscaps));

    /* DSOUND: Error: Invalid caps buffer */
    rc=IDirectSound8_GetCaps(dso,&dscaps);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetCaps() "
139
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
140 141 142 143 144

    dscaps.dwSize=sizeof(dscaps);

    /* DSOUND: Running on a certified driver */
    rc=IDirectSound8_GetCaps(dso,&dscaps);
145
    ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
146 147

    rc=IDirectSound8_Compact(dso);
148
    ok(rc==DSERR_PRIOLEVELNEEDED,"IDirectSound8_Compact() failed: %08x\n", rc);
149 150

    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
151
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
152 153

    rc=IDirectSound8_Compact(dso);
154
    ok(rc==DS_OK,"IDirectSound8_Compact() failed: %08x\n",rc);
155 156 157

    rc=IDirectSound8_GetSpeakerConfig(dso,0);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_GetSpeakerConfig(NULL) "
158
       "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
159 160

    rc=IDirectSound8_GetSpeakerConfig(dso,&speaker_config);
161
    ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %08x\n", rc);
162
    ref_speaker_config = speaker_config;
163 164 165

    speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
                                        DSSPEAKER_GEOMETRY_WIDE);
166 167 168 169 170 171 172
    if (speaker_config == ref_speaker_config)
        speaker_config = DSSPEAKER_COMBINED(DSSPEAKER_STEREO,
                                            DSSPEAKER_GEOMETRY_NARROW);
    if(rc==DS_OK) {
        rc=IDirectSound8_SetSpeakerConfig(dso,speaker_config);
        ok(rc==DS_OK,"IDirectSound8_SetSpeakerConfig() failed: %08x\n", rc);
    }
173 174
    if (rc==DS_OK) {
        rc=IDirectSound8_GetSpeakerConfig(dso,&new_speaker_config);
175
        ok(rc==DS_OK,"IDirectSound8_GetSpeakerConfig() failed: %08x\n", rc);
176
        if (rc==DS_OK && speaker_config!=new_speaker_config && ref_speaker_config!=new_speaker_config)
177
               trace("IDirectSound8_GetSpeakerConfig() failed to set speaker "
178 179
               "config: expected 0x%08x or 0x%08x, got 0x%08x\n",
               speaker_config,ref_speaker_config,new_speaker_config);
180
        IDirectSound8_SetSpeakerConfig(dso,ref_speaker_config);
181 182 183
    }

    rc=IDirectSound8_VerifyCertification(dso, &certified);
184
    ok(rc==DS_OK||rc==E_NOTIMPL,"IDirectSound8_VerifyCertification() failed: %08x\n", rc);
185

186
EXIT:
187 188 189 190
    ref=IDirectSound8_Release(dso);
    ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
}

191
static void IDirectSound8_tests(void)
192 193 194
{
    HRESULT rc;
    LPDIRECTSOUND8 dso=NULL;
195
    LPCLASSFACTORY cf=NULL;
196 197 198

    trace("Testing IDirectSound8\n");

199 200 201
    rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
                        &IID_IClassFactory, (void**)&cf);
    ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IClassFactory) "
202
       "failed: %08x\n", rc);
203 204 205 206

    rc=CoGetClassObject(&CLSID_DirectSound8, CLSCTX_INPROC_SERVER, NULL,
                        &IID_IUnknown, (void**)&cf);
    ok(rc==S_OK,"CoGetClassObject(CLSID_DirectSound8, IID_IUnknown) "
207
       "failed: %08x\n", rc);
208

209 210 211
    /* try the COM class factory method of creation with no device specified */
    rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
                        &IID_IDirectSound8, (void**)&dso);
212
    ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG,"CoCreateInstance() failed: %08x\n", rc);
213 214 215 216
    if (rc==REGDB_E_CLASSNOTREG) {
        trace("  Class Not Registered\n");
        return;
    }
217 218 219 220 221 222 223
    if (dso)
        IDirectSound8_test(dso, FALSE, NULL);

    /* try the COM class factory method of creation with default playback
     *  device specified */
    rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
                        &IID_IDirectSound8, (void**)&dso);
224
    ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %08x\n", rc);
225 226 227 228 229 230 231
    if (dso)
        IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultPlayback);

    /* try the COM class factory method of creation with default voice
     * playback device specified */
    rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
                        &IID_IDirectSound8, (void**)&dso);
232
    ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound8) failed: %08x\n", rc);
233 234 235 236 237 238 239 240 241
    if (dso)
        IDirectSound8_test(dso, FALSE, &DSDEVID_DefaultVoicePlayback);

    /* try the COM class factory method of creation with a bad
     * IID specified */
    rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
                        &CLSID_DirectSoundPrivate, (void**)&dso);
    ok(rc==E_NOINTERFACE,
       "CoCreateInstance(CLSID_DirectSound8,CLSID_DirectSoundPrivate) "
242
       "should have failed: %08x\n",rc);
243 244 245 246 247 248 249

    /* try the COM class factory method of creation with a bad
     * GUID and IID specified */
    rc=CoCreateInstance(&CLSID_DirectSoundPrivate, NULL, CLSCTX_INPROC_SERVER,
                        &IID_IDirectSound8, (void**)&dso);
    ok(rc==REGDB_E_CLASSNOTREG,
       "CoCreateInstance(CLSID_DirectSoundPrivate,IID_IDirectSound8) "
250
       "should have failed: %08x\n",rc);
251 252

    /* try with no device specified */
253
    rc=pDirectSoundCreate8(NULL,&dso,NULL);
254
    ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
255
       "DirectSoundCreate8() failed: %08x\n",rc);
256
    if (rc==DS_OK && dso)
257 258 259
        IDirectSound8_test(dso, TRUE, NULL);

    /* try with default playback device specified */
260
    rc=pDirectSoundCreate8(&DSDEVID_DefaultPlayback,&dso,NULL);
261
    ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
262
       "DirectSoundCreate8() failed: %08x\n",rc);
263
    if (rc==DS_OK && dso)
264 265 266
        IDirectSound8_test(dso, TRUE, NULL);

    /* try with default voice playback device specified */
267
    rc=pDirectSoundCreate8(&DSDEVID_DefaultVoicePlayback,&dso,NULL);
268
    ok(rc==S_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
269
       "DirectSoundCreate8() failed: %08x\n",rc);
270
    if (rc==DS_OK && dso)
271 272 273
        IDirectSound8_test(dso, TRUE, NULL);

    /* try with a bad device specified */
274
    rc=pDirectSoundCreate8(&DSDEVID_DefaultVoiceCapture,&dso,NULL);
275
    ok(rc==DSERR_NODRIVER,"DirectSoundCreate8(DSDEVID_DefaultVoiceCapture) "
276
       "should have failed: %08x\n",rc);
277 278 279 280 281 282 283 284 285
}

static HRESULT test_dsound8(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND8 dso=NULL;
    int ref;

    /* DSOUND: Error: Invalid interface buffer */
286
    rc=pDirectSoundCreate8(lpGuid,0,NULL);
287
    ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate8() should have returned "
288
       "DSERR_INVALIDPARAM, returned: %08x\n",rc);
289 290

    /* Create the DirectSound8 object */
291
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
292
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL,
293
       "DirectSoundCreate8() failed: %08x\n",rc);
294 295 296 297 298 299 300 301 302
    if (rc!=DS_OK)
        return rc;

    /* Try the enumerated device */
    IDirectSound8_test(dso, TRUE, lpGuid);

    /* Try the COM class factory method of creation with enumerated device */
    rc=CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
                        &IID_IDirectSound8, (void**)&dso);
303
    ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSound) failed: %08x\n", rc);
304 305 306 307
    if (dso)
        IDirectSound8_test(dso, FALSE, lpGuid);

    /* Create a DirectSound8 object */
308
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
309
    ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
310 311 312 313
    if (rc==DS_OK) {
        LPDIRECTSOUND8 dso1=NULL;

        /* Create a second DirectSound8 object */
314
        rc=pDirectSoundCreate8(lpGuid,&dso1,NULL);
315
        ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
316 317 318
        if (rc==DS_OK) {
            /* Release the second DirectSound8 object */
            ref=IDirectSound8_Release(dso1);
319
            ok(ref==0,"IDirectSound8_Release() has %d references, "
320 321
               "should have 0\n",ref);
            ok(dso!=dso1,"DirectSound8 objects should be unique: "
322
               "dso=%p,dso1=%p\n",dso,dso1);
323 324 325 326
        }

        /* Release the first DirectSound8 object */
        ref=IDirectSound8_Release(dso);
327
        ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
328 329 330 331 332 333 334
           ref);
        if (ref!=0)
            return DSERR_GENERIC;
    } else
        return rc;

    /* Create a DirectSound8 object */
335
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
336
    ok(rc==DS_OK,"DirectSoundCreate8() failed: %08x\n",rc);
337 338 339 340 341 342 343 344 345
    if (rc==DS_OK) {
        LPDIRECTSOUNDBUFFER secondary;
        DSBUFFERDESC bufdesc;
        WAVEFORMATEX wfx;

        init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
        ZeroMemory(&bufdesc, sizeof(bufdesc));
        bufdesc.dwSize=sizeof(bufdesc);
        bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRL3D;
346 347
        bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                    wfx.nBlockAlign);
348 349 350
        bufdesc.lpwfxFormat=&wfx;
        rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
        ok(rc==DS_OK && secondary!=NULL,
351
           "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
352
           "buffer: %08x\n",rc);
353 354 355 356 357 358 359
        if (rc==DS_OK && secondary!=NULL) {
            LPDIRECTSOUND3DBUFFER buffer3d;
            LPDIRECTSOUNDBUFFER8 buffer8;
            rc=IDirectSound8_QueryInterface(secondary,
                                            &IID_IDirectSound3DBuffer,
                                            (void **)&buffer3d);
            ok(rc==DS_OK && buffer3d!=NULL,
360
               "IDirectSound8_QueryInterface() failed: %08x\n", rc);
361 362
            if (rc==DS_OK && buffer3d!=NULL) {
                ref=IDirectSound3DBuffer_AddRef(buffer3d);
363
                ok(ref==2,"IDirectSound3DBuffer_AddRef() has %d references, "
364 365 366 367 368 369
                   "should have 2\n",ref);
            }
            rc=IDirectSound8_QueryInterface(secondary,
                                            &IID_IDirectSoundBuffer8,
                                            (void **)&buffer8);
            if (rc==DS_OK && buffer8!=NULL) {
370 371
                ok(buffer8==(IDirectSoundBuffer8*)secondary,
                   "IDirectSoundBuffer8 iface different from IDirectSoundBuffer.\n");
372
                ref=IDirectSoundBuffer8_AddRef(buffer8);
373
                ok(ref==3,"IDirectSoundBuffer8_AddRef() has %d references, "
374 375 376
                   "should have 3\n",ref);
            }
            ref=IDirectSoundBuffer_AddRef(secondary);
377
            ok(ref==4,"IDirectSoundBuffer_AddRef() has %d references, "
378 379 380 381
               "should have 4\n",ref);
        }
        /* release with buffer */
        ref=IDirectSound8_Release(dso);
382
        ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",
383 384 385 386 387 388 389 390 391 392 393 394 395 396
           ref);
        if (ref!=0)
            return DSERR_GENERIC;
    } else
        return rc;

    return DS_OK;
}

static HRESULT test_primary8(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND8 dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,second=NULL,third=NULL;
397
    LPDIRECTSOUNDBUFFER8 pb8 = NULL;
398 399
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
400
    WAVEFORMATEX wfx;
401 402 403
    int ref;

    /* Create the DirectSound object */
404
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
405
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
406
       "DirectSoundCreate8() failed: %08x\n",rc);
407 408 409 410 411 412 413
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound8_GetCaps(dso,&dscaps);
414
    ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
415 416 417 418 419 420
    if (rc!=DS_OK)
        goto EXIT;

    /* DSOUND: Error: Invalid buffer description pointer */
    rc=IDirectSound8_CreateSoundBuffer(dso,0,0,NULL);
    ok(rc==DSERR_INVALIDPARAM,
421
       "IDirectSound8_CreateSoundBuffer should have returned "
422
       "DSERR_INVALIDPARAM, returned: %08x\n",rc);
423 424 425 426

    /* DSOUND: Error: Invalid buffer description pointer */
    rc=IDirectSound8_CreateSoundBuffer(dso,0,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
427
       "IDirectSound8_CreateSoundBuffer() should have returned "
428 429
       "DSERR_INVALIDPARAM, returned: rc=%08x,dsbo=%p\n",
       rc,primary);
430

431 432 433 434
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize = sizeof(DSBUFFERDESC);

    /* DSOUND: Error: Invalid dsound buffer interface pointer */
435 436
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,0,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
437 438
       "IDirectSound8_CreateSoundBuffer() should have failed: rc=%08x,"
       "dsbo=%p\n",rc,primary);
439 440 441 442 443 444 445

    ZeroMemory(&bufdesc, sizeof(bufdesc));

    /* DSOUND: Error: Invalid size */
    /* DSOUND: Error: Invalid buffer description */
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM && primary==0,
446 447
       "IDirectSound8_CreateSoundBuffer() should have failed: rc=%08x,"
       "primary=%p\n",rc,primary);
448 449 450 451

    /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
452
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
453 454 455 456
    if (rc!=DS_OK)
        goto EXIT;

    /* Testing the primary buffer */
457 458 459 460 461 462 463 464
    primary=NULL;
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
    bufdesc.lpwfxFormat = &wfx;
    init_format(&wfx,WAVE_FORMAT_PCM,11025,8,2);
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() should have "
465
       "returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
466 467 468
    if (rc==DS_OK && primary!=NULL)
        IDirectSoundBuffer_Release(primary);

469 470 471 472 473
    primary=NULL;
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME;
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
474
    ok((rc==DS_OK && primary!=NULL) || (rc==DSERR_CONTROLUNAVAIL),
475
       "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
476
       "%08x\n",rc);
477 478 479
    if (rc==DSERR_CONTROLUNAVAIL)
        trace("  No Primary\n");
    else if (rc==DS_OK && primary!=NULL) {
480 481 482 483 484 485 486
        LONG vol;

        /* Try to create a second primary buffer */
        /* DSOUND: Error: The primary buffer already exists.
         * Any changes made to the buffer description will be ignored. */
        rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&second,NULL);
        ok(rc==DS_OK && second==primary,
487
           "IDirectSound8_CreateSoundBuffer() should have returned original "
488
           "primary buffer: %08x\n",rc);
489
        ref=IDirectSoundBuffer_Release(second);
490
        ok(ref==1,"IDirectSoundBuffer_Release() primary has %d references, "
491 492 493 494 495 496
           "should have 1\n",ref);

        /* Try to duplicate a primary buffer */
        /* DSOUND: Error: Can't duplicate primary buffers */
        rc=IDirectSound8_DuplicateSoundBuffer(dso,primary,&third);
        /* rc=0x88780032 */
497
        ok(rc!=DS_OK,"IDirectSound8_DuplicateSoundBuffer() primary buffer "
498
           "should have failed %08x\n",rc);
499

500 501
        /* Primary buffers don't have an IDirectSoundBuffer8 */
        rc = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8, (LPVOID*)&pb8);
502
        ok(FAILED(rc), "Primary buffer does have an IDirectSoundBuffer8: %08x\n", rc);
503

504
        rc=IDirectSoundBuffer_GetVolume(primary,&vol);
505
        ok(rc==DS_OK,"IDirectSoundBuffer_GetVolume() failed: %08x\n", rc);
506 507 508 509

        if (winetest_interactive) {
            trace("Playing a 5 seconds reference tone at the current volume.\n");
            if (rc==DS_OK)
510
                trace("(the current volume is %d according to DirectSound)\n",
511 512 513 514
                      vol);
            trace("All subsequent tones should be identical to this one.\n");
            trace("Listen for stutter, changes in pitch, volume, etc.\n");
        }
515 516 517
        test_buffer8(dso,&primary,TRUE,FALSE,0,FALSE,0,
                     winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),
                     5.0,FALSE,NULL,FALSE,FALSE);
518 519

        ref=IDirectSoundBuffer_Release(primary);
520
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
521 522 523 524 525 526
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
527
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
528 529 530

EXIT:
    ref=IDirectSound8_Release(dso);
531
    ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
532 533 534 535 536 537
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}

538 539 540 541 542 543 544 545 546 547 548 549
/*
 * Test the primary buffer at different formats while keeping the
 * secondary buffer at a constant format.
 */
static HRESULT test_primary_secondary8(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND8 dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
    WAVEFORMATEX wfx, wfx2;
550
    int ref;
551
    unsigned int f, tag;
552 553

    /* Create the DirectSound object */
554
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
555
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
556
       "DirectSoundCreate8() failed: %08x\n",rc);
557 558 559 560 561 562 563
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound8_GetCaps(dso,&dscaps);
564
    ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
565 566 567 568 569 570
    if (rc!=DS_OK)
        goto EXIT;

    /* We must call SetCooperativeLevel before creating primary buffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
571
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
572 573 574 575 576 577 578 579
    if (rc!=DS_OK)
        goto EXIT;

    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DS_OK && primary!=NULL,
580
       "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
581
       "%08x\n",rc);
582 583 584

    if (rc==DS_OK && primary!=NULL) {
        for (f=0;f<NB_FORMATS;f++) {
585 586 587 588 589
          for (tag=0;tag<NB_TAGS;tag++) {
            /* if float, we only want to test 32-bit */
            if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
                continue;

590 591 592 593
            /* We must call SetCooperativeLevel to be allowed to call
             * SetFormat */
            /* DSOUND: Setting DirectSound cooperative level to
             * DSSCL_PRIORITY */
594
            rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
595
            ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
596 597 598
            if (rc!=DS_OK)
                goto EXIT;

599
            init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
600 601 602
                        formats[f][2]);
            wfx2=wfx;
            rc=IDirectSoundBuffer_SetFormat(primary,&wfx);
603 604 605
            ok(rc==DS_OK
               || rc==DSERR_INVALIDPARAM, /* 2003 */
               "IDirectSoundBuffer_SetFormat(%s) failed: %08x\n",
606
               format_string(&wfx), rc);
607

608
            /* There is no guarantee that SetFormat will actually change the
609 610 611 612
             * format to what we asked for. It depends on what the soundcard
             * supports. So we must re-query the format.
             */
            rc=IDirectSoundBuffer_GetFormat(primary,&wfx,sizeof(wfx),NULL);
613
            ok(rc==DS_OK,"IDirectSoundBuffer_GetFormat() failed: %08x\n", rc);
614 615 616 617 618
            if (rc==DS_OK &&
                (wfx.wFormatTag!=wfx2.wFormatTag ||
                 wfx.nSamplesPerSec!=wfx2.nSamplesPerSec ||
                 wfx.wBitsPerSample!=wfx2.wBitsPerSample ||
                 wfx.nChannels!=wfx2.nChannels)) {
619 620
                trace("Requested primary format tag=0x%04x %dx%dx%d "
                      "avg.B/s=%d align=%d\n",
621 622
                      wfx2.wFormatTag,wfx2.nSamplesPerSec,wfx2.wBitsPerSample,
                      wfx2.nChannels,wfx2.nAvgBytesPerSec,wfx2.nBlockAlign);
623
                trace("Got tag=0x%04x %dx%dx%d avg.B/s=%d align=%d\n",
624 625 626 627 628 629 630
                      wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
                      wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
            }

            /* Set the CooperativeLevel back to normal */
            /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
            rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
631
            ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
632 633 634 635 636 637 638

            init_format(&wfx2,WAVE_FORMAT_PCM,11025,16,2);

            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
639 640
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
641
            bufdesc.lpwfxFormat=&wfx2;
642
            if (winetest_interactive) {
643
                trace("  Testing a primary buffer at %dx%dx%d (fmt=%d) with a "
644
                      "secondary buffer at %dx%dx%d\n",
645
                      wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
646 647
                      wfx2.nSamplesPerSec,wfx2.wBitsPerSample,wfx2.nChannels);
            }
648 649
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary!=NULL,
650
               "IDirectSound_CreateSoundBuffer() failed to create a secondary "
651
               "buffer %08x\n",rc);
652 653

            if (rc==DS_OK && secondary!=NULL) {
654 655
                test_buffer8(dso,&secondary,FALSE,FALSE,0,FALSE,0,
                             winetest_interactive,1.0,FALSE,NULL,FALSE,FALSE);
656 657

                ref=IDirectSoundBuffer_Release(secondary);
658
                ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
659 660
                   "should have 0\n",ref);
            }
661
          }
662 663 664
        }

        ref=IDirectSoundBuffer_Release(primary);
665
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
666 667 668 669 670 671
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
672
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
673 674 675

EXIT:
    ref=IDirectSound8_Release(dso);
676
    ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
677 678 679 680 681 682
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}

683 684 685 686 687 688 689
static HRESULT test_secondary8(LPGUID lpGuid)
{
    HRESULT rc;
    LPDIRECTSOUND8 dso=NULL;
    LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
    DSBUFFERDESC bufdesc;
    DSCAPS dscaps;
690
    WAVEFORMATEX wfx, wfx1;
691
    DWORD f, tag;
692
    int ref;
693 694

    /* Create the DirectSound object */
695
    rc=pDirectSoundCreate8(lpGuid,&dso,NULL);
696
    ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED,
697
       "DirectSoundCreate8() failed: %08x\n",rc);
698 699 700 701 702 703 704
    if (rc!=DS_OK)
        return rc;

    /* Get the device capabilities */
    ZeroMemory(&dscaps, sizeof(dscaps));
    dscaps.dwSize=sizeof(dscaps);
    rc=IDirectSound8_GetCaps(dso,&dscaps);
705
    ok(rc==DS_OK,"IDirectSound8_GetCaps() failed: %08x\n",rc);
706 707 708 709 710 711
    if (rc!=DS_OK)
        goto EXIT;

    /* We must call SetCooperativeLevel before creating primary buffer */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
712
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
713 714 715 716 717 718 719 720
    if (rc!=DS_OK)
        goto EXIT;

    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok(rc==DS_OK && primary!=NULL,
721
       "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer "
722
       "%08x\n",rc);
723 724

    if (rc==DS_OK && primary!=NULL) {
725
        rc=IDirectSoundBuffer_GetFormat(primary,&wfx1,sizeof(wfx1),NULL);
726
        ok(rc==DS_OK,"IDirectSoundBuffer8_Getformat() failed: %08x\n", rc);
727 728 729
        if (rc!=DS_OK)
            goto EXIT1;

730
        for (f=0;f<NB_FORMATS;f++) {
731
          for (tag=0;tag<NB_TAGS;tag++) {
732
            WAVEFORMATEXTENSIBLE wfxe;
733 734 735 736 737 738

            /* if float, we only want to test 32-bit */
            if ((format_tags[tag] == WAVE_FORMAT_IEEE_FLOAT) && (formats[f][1] != 32))
                continue;

            init_format(&wfx,format_tags[tag],formats[f][0],formats[f][1],
739 740 741 742 743
                        formats[f][2]);
            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
744 745
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
746 747
            rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DSERR_INVALIDPARAM,"IDirectSound8_CreateSoundBuffer() "
748
               "should have returned DSERR_INVALIDPARAM, returned: %08x\n", rc);
749 750 751 752 753 754 755
            if (rc==DS_OK && secondary!=NULL)
                IDirectSoundBuffer_Release(secondary);

            secondary=NULL;
            ZeroMemory(&bufdesc, sizeof(bufdesc));
            bufdesc.dwSize=sizeof(bufdesc);
            bufdesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
756 757
            bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                        wfx.nBlockAlign);
758
            bufdesc.lpwfxFormat=&wfx;
759 760
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            if (wfx.wBitsPerSample != 8 && wfx.wBitsPerSample != 16)
761 762 763
                ok(((rc == DSERR_CONTROLUNAVAIL || rc == DSERR_INVALIDCALL || rc == DSERR_INVALIDPARAM /* 2003 */) && !secondary)
                    || rc == DS_OK, /* driver dependent? */
                    "IDirectSound_CreateSoundBuffer() "
764 765
                    "should have returned (DSERR_CONTROLUNAVAIL or DSERR_INVALIDCALL) "
                    "and NULL, returned: %08x %p\n", rc, secondary);
766 767 768
            else
                ok(rc==DS_OK && secondary!=NULL,
                    "IDirectSound_CreateSoundBuffer() failed to create a secondary "
769
                    "buffer %08x\n",rc);
770 771 772 773 774 775 776
            if (secondary)
                IDirectSoundBuffer_Release(secondary);
            secondary = NULL;

            bufdesc.lpwfxFormat=(WAVEFORMATEX*)&wfxe;
            wfxe.Format = wfx;
            wfxe.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
777
            wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
778 779 780 781 782 783
            wfxe.Format.cbSize = 1;
            wfxe.Samples.wValidBitsPerSample = wfx.wBitsPerSample;
            wfxe.dwChannelMask = (wfx.nChannels == 1 ? KSAUDIO_SPEAKER_MONO : KSAUDIO_SPEAKER_STEREO);

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DSERR_INVALIDPARAM && !secondary,
784 785
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
786
            if (secondary)
787
            {
788
                IDirectSoundBuffer_Release(secondary);
789 790
                secondary=NULL;
            }
791 792 793 794

            wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx) + 1;

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
795
            ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL /* 2003 */ || rc==DSERR_INVALIDPARAM) && !secondary)
796
                || rc==DS_OK /* driver dependent? */,
797 798
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
799
            if (secondary)
800
            {
801
                IDirectSoundBuffer_Release(secondary);
802 803
                secondary=NULL;
            }
804 805 806 807

            wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
            wfxe.SubFormat = GUID_NULL;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
808
            ok((rc==DSERR_INVALIDPARAM || rc==DSERR_INVALIDCALL) && !secondary,
809 810
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
811
            if (secondary)
812
            {
813
                IDirectSoundBuffer_Release(secondary);
814 815
                secondary=NULL;
            }
816 817 818

            wfxe.Format.cbSize = sizeof(wfxe);
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
819
            ok((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL || rc==DSERR_INVALIDPARAM) && !secondary,
820 821 822 823 824 825 826 827
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }

828
            wfxe.SubFormat = (format_tags[tag] == WAVE_FORMAT_PCM ? KSDATAFORMAT_SUBTYPE_PCM : KSDATAFORMAT_SUBTYPE_IEEE_FLOAT);
829 830 831 832 833 834 835 836 837
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }
838

839 840
            wfxe.Format.cbSize = sizeof(wfxe) + 1;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
841
            ok(((rc==DSERR_CONTROLUNAVAIL || rc==DSERR_INVALIDCALL /* 2003 */ || rc==DSERR_INVALIDPARAM) && !secondary)
842 843 844 845 846 847 848 849 850 851
                || rc==DS_OK /* driver dependent? */,
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
            if (secondary)
            {
                IDirectSoundBuffer_Release(secondary);
                secondary=NULL;
            }

            wfxe.Format.cbSize = sizeof(wfxe) - sizeof(wfx);
852 853 854
            ++wfxe.Samples.wValidBitsPerSample;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DSERR_INVALIDPARAM && !secondary,
855 856
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
857
            if (secondary)
858
            {
859
                IDirectSoundBuffer_Release(secondary);
860 861
                secondary=NULL;
            }
862 863 864 865 866
            --wfxe.Samples.wValidBitsPerSample;

            wfxe.Samples.wValidBitsPerSample = 0;
            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
            ok(rc==DS_OK && secondary,
867 868
                "IDirectSound_CreateSoundBuffer() returned: %08x %p\n",
                rc, secondary);
869
            if (secondary)
870
            {
871
                IDirectSoundBuffer_Release(secondary);
872 873
                secondary=NULL;
            }
874 875 876
            wfxe.Samples.wValidBitsPerSample = wfxe.Format.wBitsPerSample;

            rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
877
            ok(rc==DS_OK && secondary!=NULL,
878
                "IDirectSound_CreateSoundBuffer() failed to create a secondary "
879
                "buffer %08x\n",rc);
880 881

            if (rc==DS_OK && secondary!=NULL) {
882
                if (winetest_interactive) {
883
                    trace("  Testing a secondary buffer at %dx%dx%d (fmt=%d) "
884
                        "with a primary buffer at %dx%dx%d\n",
885
                        wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels,format_tags[tag],
886 887
                        wfx1.nSamplesPerSec,wfx1.wBitsPerSample,wfx1.nChannels);
                }
888 889
                test_buffer8(dso,&secondary,FALSE,FALSE,0,FALSE,0,
                             winetest_interactive,1.0,FALSE,NULL,FALSE,FALSE);
890 891

                ref=IDirectSoundBuffer_Release(secondary);
892
                ok(ref==0,"IDirectSoundBuffer_Release() has %d references, "
893 894
                   "should have 0\n",ref);
            }
895
          }
896
        }
897
EXIT1:
898
        ref=IDirectSoundBuffer_Release(primary);
899
        ok(ref==0,"IDirectSoundBuffer_Release() primary has %d references, "
900 901 902 903 904 905
           "should have 0\n",ref);
    }

    /* Set the CooperativeLevel back to normal */
    /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
906
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
907 908 909

EXIT:
    ref=IDirectSound8_Release(dso);
910
    ok(ref==0,"IDirectSound8_Release() has %d references, should have 0\n",ref);
911 912 913 914 915 916 917 918 919
    if (ref!=0)
        return DSERR_GENERIC;

    return rc;
}

static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
                                   LPCSTR lpcstrModule, LPVOID lpContext)
{
920
    HRESULT rc;
921
    trace("*** Testing %s - %s ***\n",lpcstrDescription,lpcstrModule);
922 923 924
    rc = test_dsound8(lpGuid);
    if (rc == DSERR_NODRIVER)
        trace("  No Driver\n");
925 926
    else if (rc == DSERR_ALLOCATED)
        trace("  Already In Use\n");
927 928
    else if (rc == E_FAIL)
        trace("  No Device\n");
929 930 931 932 933
    else {
        test_primary8(lpGuid);
        test_primary_secondary8(lpGuid);
        test_secondary8(lpGuid);
    }
934

935
    return TRUE;
936 937
}

938
static void dsound8_tests(void)
939 940
{
    HRESULT rc;
941
    rc=pDirectSoundEnumerateA(&dsenum_callback,NULL);
942
    ok(rc==DS_OK,"DirectSoundEnumerateA() failed: %08x\n",rc);
943 944
}

945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
static void test_hw_buffers(void)
{
    IDirectSound8 *ds;
    IDirectSoundBuffer *primary, *primary2, **secondaries, *secondary;
    IDirectSoundBuffer8 *buf8;
    DSCAPS caps;
    DSBCAPS bufcaps;
    DSBUFFERDESC bufdesc;
    WAVEFORMATEX fmt;
    UINT i;
    HRESULT hr;

    hr = pDirectSoundCreate8(NULL, &ds, NULL);
    ok(hr == S_OK || hr == DSERR_NODRIVER || hr == DSERR_ALLOCATED || hr == E_FAIL,
            "DirectSoundCreate8 failed: %08x\n", hr);
    if(hr != S_OK)
        return;

    caps.dwSize = sizeof(caps);

    hr = IDirectSound8_GetCaps(ds, &caps);
    ok(hr == S_OK, "GetCaps failed: %08x\n", hr);

    ok(caps.dwPrimaryBuffers == 1, "Got wrong number of primary buffers: %u\n",
            caps.dwPrimaryBuffers);

    /* DSBCAPS_LOC* is ignored for primary buffers */
    bufdesc.dwSize = sizeof(bufdesc);
    bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
        DSBCAPS_PRIMARYBUFFER;
    bufdesc.dwBufferBytes = 0;
    bufdesc.dwReserved = 0;
    bufdesc.lpwfxFormat = NULL;
    bufdesc.guid3DAlgorithm = GUID_NULL;

    hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &primary, NULL);
    ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
    if(hr != S_OK){
        IDirectSound8_Release(ds);
        return;
    }

    bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE |
        DSBCAPS_PRIMARYBUFFER;

    hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &primary2, NULL);
    ok(hr == S_OK, "CreateSoundBuffer failed: %08x\n", hr);
    ok(primary == primary2, "Got different primary buffers: %p, %p\n", primary, primary2);
    if(hr == S_OK)
        IDirectSoundBuffer_Release(primary2);

    buf8 = (IDirectSoundBuffer8 *)0xDEADBEEF;
    hr = IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer8,
            (void**)&buf8);
    ok(hr == E_NOINTERFACE, "QueryInterface gave wrong failure: %08x\n", hr);
    ok(buf8 == NULL, "Pointer didn't get set to NULL\n");

    fmt.wFormatTag = WAVE_FORMAT_PCM;
    fmt.nChannels = 2;
    fmt.nSamplesPerSec = 48000;
    fmt.wBitsPerSample = 16;
    fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
    fmt.nAvgBytesPerSec = fmt.nBlockAlign * fmt.nSamplesPerSec;
    fmt.cbSize = 0;

    bufdesc.lpwfxFormat = &fmt;
    bufdesc.dwBufferBytes = fmt.nSamplesPerSec * fmt.nBlockAlign / 10;
    bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE |
        DSBCAPS_CTRLVOLUME;

    secondaries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
            sizeof(IDirectSoundBuffer *) * caps.dwMaxHwMixingAllBuffers);

    /* try to fill all of the hw buffers */
    trace("dwMaxHwMixingAllBuffers: %u\n", caps.dwMaxHwMixingAllBuffers);
    trace("dwMaxHwMixingStaticBuffers: %u\n", caps.dwMaxHwMixingStaticBuffers);
    trace("dwMaxHwMixingStreamingBuffers: %u\n", caps.dwMaxHwMixingStreamingBuffers);
    for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i){
        hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &secondaries[i], NULL);
1024
        ok(hr == S_OK || hr == E_NOTIMPL || broken(hr == DSERR_CONTROLUNAVAIL) || broken(hr == E_FAIL),
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
                "CreateSoundBuffer(%u) failed: %08x\n", i, hr);
        if(hr != S_OK)
            break;

        bufcaps.dwSize = sizeof(bufcaps);
        hr = IDirectSoundBuffer_GetCaps(secondaries[i], &bufcaps);
        ok(hr == S_OK, "GetCaps failed: %08x\n", hr);
        ok((bufcaps.dwFlags & DSBCAPS_LOCHARDWARE) != 0,
                "Buffer wasn't allocated in hardware, dwFlags: %x\n", bufcaps.dwFlags);
    }

    /* see if we can create one more */
    hr = IDirectSound8_CreateSoundBuffer(ds, &bufdesc, &secondary, NULL);
    ok((i == caps.dwMaxHwMixingAllBuffers && hr == DSERR_ALLOCATED) || /* out of hw buffers */
            (caps.dwMaxHwMixingAllBuffers == 0 && hr == DSERR_INVALIDCALL) || /* no hw buffers at all */
            hr == E_NOTIMPL || /* don't support hw buffers */
            broken(hr == DSERR_CONTROLUNAVAIL) || /* vmware winxp, others? */
1042
            broken(hr == E_FAIL) || /* broken AC97 driver */
1043
            broken(hr == S_OK) /* broken driver allows more hw bufs than dscaps claims */,
1044
            "CreateSoundBuffer(%u) gave wrong error: %08x\n", i, hr);
1045 1046 1047 1048 1049 1050 1051
    if(hr == S_OK)
        IDirectSoundBuffer_Release(secondary);

    for(i = 0; i < caps.dwMaxHwMixingAllBuffers; ++i)
        if(secondaries[i])
            IDirectSoundBuffer_Release(secondaries[i]);

1052 1053
    HeapFree(GetProcessHeap(), 0, secondaries);

1054 1055 1056
    IDirectSoundBuffer_Release(primary);
    IDirectSound8_Release(ds);
}
1057

1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100
static struct {
    UINT dev_count;
    GUID guid;
} default_info = { 0 };

static BOOL WINAPI default_device_cb(GUID *guid, const char *desc,
        const char *module, void *user)
{
    trace("guid: %p, desc: %s\n", guid, desc);
    if(!guid)
        ok(default_info.dev_count == 0, "Got NULL GUID not in first position\n");
    else{
        if(default_info.dev_count == 0){
            ok(IsEqualGUID(guid, &default_info.guid), "Expected default device GUID\n");
        }else{
            ok(!IsEqualGUID(guid, &default_info.guid), "Got default GUID at unexpected location: %u\n",
                    default_info.dev_count);
        }

        /* only count real devices */
        ++default_info.dev_count;
    }

    return TRUE;
}

static void test_first_device(void)
{
    IMMDeviceEnumerator *devenum;
    IMMDevice *defdev;
    IPropertyStore *ps;
    PROPVARIANT pv;
    HRESULT hr;

    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL,
            CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, (void**)&devenum);
    if(FAILED(hr)){
        win_skip("MMDevAPI is not available, skipping default device test\n");
        return;
    }

    hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender,
            eMultimedia, &defdev);
1101 1102 1103 1104
    if (hr == E_NOTFOUND) {
        win_skip("No default device found\n");
        return;
    }
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
    ok(hr == S_OK, "GetDefaultAudioEndpoint failed: %08x\n", hr);

    hr = IMMDevice_OpenPropertyStore(defdev, STGM_READ, &ps);
    ok(hr == S_OK, "OpenPropertyStore failed: %08x\n", hr);

    PropVariantInit(&pv);

    hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_GUID, &pv);
    ok(hr == S_OK, "GetValue failed: %08x\n", hr);

    CLSIDFromString(pv.u.pwszVal, &default_info.guid);

    PropVariantClear(&pv);
    IPropertyStore_Release(ps);
    IMMDevice_Release(defdev);
    IMMDeviceEnumerator_Release(devenum);

    hr = pDirectSoundEnumerateA(&default_device_cb, NULL);
    ok(hr == S_OK, "DirectSoundEnumerateA failed: %08x\n", hr);
}

1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
static void test_COM(void)
{
    IDirectSound *ds;
    IDirectSound8 *ds8 = (IDirectSound8*)0xdeadbeef;
    IUnknown *unk, *unk8;
    ULONG refcount;
    HRESULT hr;

    /* COM aggregation */
    hr = CoCreateInstance(&CLSID_DirectSound8, (IUnknown*)&ds, CLSCTX_INPROC_SERVER,
            &IID_IUnknown, (void**)&ds8);
    ok(hr == CLASS_E_NOAGGREGATION,
            "DirectSound create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr);
    ok(!ds8, "ds8 = %p\n", ds8);

    /* Invalid RIID */
    hr = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER,
            &IID_IDirectSound3DBuffer, (void**)&ds8);
    ok(hr == E_NOINTERFACE,
            "DirectSound create failed: %08x, expected E_NOINTERFACE\n", hr);

    /* Same refcount for IDirectSound and IDirectSound8 */
    hr = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8,
            (void**)&ds8);
    ok(hr == S_OK, "DirectSound create failed: %08x, expected S_OK\n", hr);
    refcount = IDirectSound8_AddRef(ds8);
    ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
    hr = IDirectSound8_QueryInterface(ds8, &IID_IDirectSound, (void**)&ds);
    ok(hr == S_OK, "QueryInterface for IID_IDirectSound failed: %08x\n", hr);
    refcount = IDirectSound8_AddRef(ds8);
1156
    ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
1157
    refcount = IDirectSound_AddRef(ds);
1158
    ok(refcount == 5, "refcount == %u, expected 5\n", refcount);
1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169

    /* Separate refcount for IUnknown */
    hr = IDirectSound_QueryInterface(ds, &IID_IUnknown, (void**)&unk);
    ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
    refcount = IUnknown_AddRef(unk);
    ok(refcount == 2, "refcount == %u, expected 2\n", refcount);
    hr = IDirectSound_QueryInterface(ds8, &IID_IUnknown, (void**)&unk8);
    ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr);
    refcount = IUnknown_AddRef(unk8);
    ok(refcount == 4, "refcount == %u, expected 4\n", refcount);
    refcount = IDirectSound_AddRef(ds);
1170
    ok(refcount == 6, "refcount == %u, expected 6\n", refcount);
1171 1172 1173 1174 1175

    while (IDirectSound_Release(ds));
    while (IUnknown_Release(unk));
}

1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260
static void test_effects(void)
{
    HRESULT rc;
    LPDIRECTSOUND8 dso;
    LPDIRECTSOUNDBUFFER primary, secondary;
    LPDIRECTSOUNDBUFFER8 secondary8;
    DSBUFFERDESC bufdesc;
    WAVEFORMATEX wfx;
    DSEFFECTDESC effects[2];
    DWORD resultcodes[2];

    /* Create a DirectSound8 object */
    rc=pDirectSoundCreate8(NULL,&dso,NULL);
    ok(rc==DS_OK||rc==DSERR_NODRIVER,"DirectSoundCreate8() failed: %08x\n",rc);

    if (rc!=DS_OK)
        return;

    rc=IDirectSound8_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
    ok(rc==DS_OK,"IDirectSound8_SetCooperativeLevel() failed: %08x\n", rc);
    if (rc!=DS_OK) {
        IDirectSound_Release(dso);
        return;
    }

    primary=NULL;
    ZeroMemory(&bufdesc, sizeof(bufdesc));
    bufdesc.dwSize=sizeof(bufdesc);
    bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
    rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
    ok((rc==DS_OK && primary!=NULL),
       "IDirectSound8_CreateSoundBuffer() failed to create a primary buffer: "
       "%08x\n",rc);
    if (rc==DS_OK) {
        init_format(&wfx,WAVE_FORMAT_PCM,11025,8,1);
        ZeroMemory(&bufdesc, sizeof(bufdesc));
        bufdesc.dwSize=sizeof(bufdesc);
        bufdesc.dwFlags=0;
        bufdesc.dwBufferBytes=align(wfx.nAvgBytesPerSec*BUFFER_LEN/1000,
                                    wfx.nBlockAlign);
        bufdesc.lpwfxFormat=&wfx;

        ZeroMemory(effects, sizeof(effects));
        effects[0].dwSize=sizeof(effects[0]);
        effects[0].guidDSFXClass=GUID_DSFX_STANDARD_ECHO;
        effects[1].dwSize=sizeof(effects[1]);
        effects[1].guidDSFXClass=GUID_NULL;

        secondary=NULL;
        rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
        ok(rc==DS_OK && secondary!=NULL,
           "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
           "buffer: %08x\n",rc);

        /* Call SetFX on buffer without DSBCAPS_CTRLFX */
        if (rc==DS_OK && secondary!=NULL) {
            secondary8=NULL;
            rc=IDirectSoundBuffer_QueryInterface(secondary,&IID_IDirectSoundBuffer8,(LPVOID*)&secondary8);
            ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface(IID_IDirectSoundBuffer8) failed: %08x\n", rc);

            if (rc==DS_OK && secondary8) {
                rc=IDirectSoundBuffer8_SetFX(secondary8,1,effects,resultcodes);
                ok(rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                "should have returned DSERR_CONTROLUNAVAIL, returned: %08x\n", rc);

                IDirectSoundBuffer8_Release(secondary8);
            }
            IDirectSoundBuffer_Release(secondary);
        }

        secondary=NULL;
        bufdesc.dwFlags=DSBCAPS_CTRLFX;
        rc=IDirectSound8_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
        ok(rc==DS_OK && secondary!=NULL,
           "IDirectSound8_CreateSoundBuffer() failed to create a secondary "
           "buffer: %08x\n",rc);

        if (rc==DS_OK) {
            secondary8=NULL;
            rc=IDirectSoundBuffer_QueryInterface(secondary,&IID_IDirectSoundBuffer8,(LPVOID*)&secondary8);
            ok(rc==DS_OK,"IDirectSoundBuffer_QueryInterface(IID_IDirectSoundBuffer8) failed: %08x\n", rc);

            if (rc==DS_OK && secondary8) {
                LPVOID ptr1,ptr2;
                DWORD bytes1,bytes2;
1261 1262
                IUnknown* obj = NULL;
                HRESULT rc2;
1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313

                /* Call SetFX with dwEffectsCount > 0 and pDSFXDesc == NULL */
                rc=IDirectSoundBuffer8_SetFX(secondary8,1,NULL,NULL);
                ok(rc==E_INVALIDARG||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                "should have returned E_INVALIDARG, returned: %08x\n", rc);

                /* Call SetFX with dwEffectsCount == 0 and pDSFXDesc != NULL */
                rc=IDirectSoundBuffer8_SetFX(secondary8,0,effects,NULL);
                ok(rc==E_INVALIDARG||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                "should have returned E_INVALIDARG, returned: %08x\n", rc);

                /* Call SetFX with dwEffectsCount == 0 and pdwResultCodes != NULL */
                rc=IDirectSoundBuffer8_SetFX(secondary8,0,NULL,resultcodes);
                ok(rc==E_INVALIDARG||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                "should have returned E_INVALIDARG, returned: %08x\n", rc);

                rc=IDirectSoundBuffer8_Lock(secondary8,0,0,&ptr1,&bytes1,&ptr2,&bytes2,DSBLOCK_ENTIREBUFFER);
                ok(rc==DS_OK,"IDirectSoundBuffer8_Lock() failed: %08x\n",rc);

                if (rc==DS_OK) {
                    /* Call SetFX when buffer is locked */
                    rc=IDirectSoundBuffer8_SetFX(secondary8,1,effects,resultcodes);
                    ok(rc==DSERR_INVALIDCALL||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                    "should have returned DSERR_INVALIDCALL, returned: %08x\n", rc);

                    rc=IDirectSoundBuffer8_Unlock(secondary8,ptr1,bytes1,ptr2,bytes2);
                    ok(rc==DS_OK,"IDirectSoundBuffer8_Unlock() failed: %08x\n",rc);
                }

                rc=IDirectSoundBuffer8_Play(secondary8,0,0,DSBPLAY_LOOPING);
                ok(rc==DS_OK,"IDirectSoundBuffer8_Play() failed: %08x\n",rc);

                if (rc==DS_OK) {
                    /* Call SetFX when buffer is playing */
                    rc=IDirectSoundBuffer8_SetFX(secondary8,1,effects,resultcodes);
                    ok(rc==DSERR_INVALIDCALL||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX() "
                    "should have returned DSERR_INVALIDCALL, returned: %08x\n", rc);

                    rc=IDirectSoundBuffer8_Stop(secondary8);
                    ok(rc==DS_OK,"IDirectSoundBuffer8_Stop() failed: %08x\n",rc);
                }

                /* Call SetFX with non-existent filter */
                rc=IDirectSoundBuffer8_SetFX(secondary8,1,&effects[1],resultcodes);
                ok(rc==REGDB_E_CLASSNOTREG||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_SetFX(GUID_NULL) "
                    "should have returned REGDB_E_CLASSNOTREG, returned: %08x\n",rc);
                if (rc!=DSERR_CONTROLUNAVAIL) {
                    ok(resultcodes[0]==DSFXR_UNKNOWN,"result code == %08x, expected DSFXR_UNKNOWN\n",resultcodes[0]);
                }

                /* Call SetFX with standard echo */
1314 1315
                rc2=IDirectSoundBuffer8_SetFX(secondary8,1,&effects[0],resultcodes);
                ok(rc2==DS_OK||rc2==REGDB_E_CLASSNOTREG||rc2==DSERR_CONTROLUNAVAIL,
1316
                   "IDirectSoundBuffer8_SetFX(GUID_DSFX_STANDARD_ECHO) failed: %08x\n",rc);
1317
                if (rc2!=DSERR_CONTROLUNAVAIL) {
1318 1319 1320 1321
                    ok(resultcodes[0]==DSFXR_UNKNOWN||resultcodes[0]==DSFXR_LOCHARDWARE||resultcodes[0]==DSFXR_LOCSOFTWARE,
                        "resultcode == %08x, expected DSFXR_UNKNOWN, DSFXR_LOCHARDWARE, or DSFXR_LOCSOFTWARE\n",resultcodes[0]);
                }

1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
                /* Call GetObjectInPath for out-of-bounds DMO */
                rc=IDirectSoundBuffer8_GetObjectInPath(secondary8,&GUID_All_Objects,2,&IID_IMediaObject,(void**)&obj);
                ok(rc==DSERR_OBJECTNOTFOUND||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                "should have returned DSERR_OBJECTNOTFOUND, returned: %08x\n",rc);

                /* Call GetObjectInPath with NULL ppObject */
                rc=IDirectSoundBuffer8_GetObjectInPath(secondary8,&GUID_All_Objects,0,&IID_IMediaObject,NULL);
                ok(rc==E_INVALIDARG||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                "should have returned E_INVALIDARG, returned: %08x\n",rc);

                /* Call GetObjectInPath for unsupported interface */
                rc=IDirectSoundBuffer8_GetObjectInPath(secondary8,&GUID_All_Objects,0,&GUID_NULL,(void**)&obj);
                ok(rc==E_NOINTERFACE||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                "should have returned E_NOINTERFACE, returned: %08x\n",rc);

                /* Call GetObjectInPath for unloaded DMO */
                rc=IDirectSoundBuffer8_GetObjectInPath(secondary8,&GUID_NULL,0,&IID_IMediaObject,(void**)&obj);
                ok(rc==DSERR_OBJECTNOTFOUND||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                "should have returned DSERR_OBJECTNOTFOUND, returned: %08x\n",rc);

                /* Call GetObjectInPath for first DMO */
                obj=NULL;
                rc=IDirectSoundBuffer8_GetObjectInPath(secondary8,&GUID_All_Objects,0,&IID_IMediaObject,(void**)&obj);
                if (rc2==DS_OK) {
                    ok(rc==DS_OK||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                    "should have returned DS_OK, returned: %08x\n",rc);
                    if (obj) IUnknown_Release(obj);
                } else {
                    ok(rc==DSERR_OBJECTNOTFOUND||rc==DSERR_CONTROLUNAVAIL,"IDirectSoundBuffer8_GetObjectInPath() "
                    "should have returned DSERR_OBJECTNOTFOUND, returned: %08x\n",rc);
                }

1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
                /* Call SetFX with one real filter and one fake one */
                rc=IDirectSoundBuffer8_SetFX(secondary8,2,effects,resultcodes);
                ok(rc==REGDB_E_CLASSNOTREG||rc==DSERR_CONTROLUNAVAIL,
                   "IDirectSoundBuffer8_SetFX(GUID_DSFX_STANDARD_ECHO, GUID_NULL) "
                    "should have returned REGDB_E_CLASSNOTREG, returned: %08x\n",rc);
                if (rc!=DSERR_CONTROLUNAVAIL) {
                    ok(resultcodes[0]==DSFXR_PRESENT||resultcodes[0]==DSFXR_UNKNOWN,
                        "resultcodes[0] == %08x, expected DSFXR_PRESENT or DSFXR_UNKNOWN\n",resultcodes[0]);
                    ok(resultcodes[1]==DSFXR_UNKNOWN,
                        "resultcodes[1] == %08x, expected DSFXR_UNKNOWN\n",resultcodes[1]);
                }

                IDirectSoundBuffer8_Release(secondary8);
            }

            IDirectSoundBuffer_Release(secondary);
        }

        IDirectSoundBuffer_Release(primary);
    }

    while (IDirectSound_Release(dso));
}

1378 1379 1380 1381 1382 1383
START_TEST(dsound8)
{
    HMODULE hDsound;

    CoInitialize(NULL);

1384
    hDsound = LoadLibraryA("dsound.dll");
1385 1386 1387 1388 1389 1390 1391 1392 1393
    if (hDsound)
    {

        pDirectSoundEnumerateA = (void*)GetProcAddress(hDsound,
            "DirectSoundEnumerateA");
        pDirectSoundCreate8 = (void*)GetProcAddress(hDsound,
            "DirectSoundCreate8");
        if (pDirectSoundCreate8)
        {
1394
            test_COM();
1395 1396
            IDirectSound8_tests();
            dsound8_tests();
1397
            test_hw_buffers();
1398
            test_first_device();
1399
            test_effects();
1400 1401
        }
        else
1402
            skip("DirectSoundCreate8 missing - skipping all tests\n");
1403

1404
        FreeLibrary(hDsound);
1405
    }
1406
    else
1407
        skip("dsound.dll not found - skipping all tests\n");
1408 1409

    CoUninitialize();
1410
}