/*
 * Implementation of CLSID_SystemDeviceEnum.
 *
 * FIXME - not tested enough.
 *
 * hidenori@a2.ctktv.ne.jp
 */

#include "config.h"

#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winerror.h"
#include "wine/obj_base.h"
#include "objidl.h"
#include "oleidl.h"
#include "ocidl.h"
#include "strmif.h"
#include "control.h"
#include "uuids.h"
#include "wine/unicode.h"

#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(quartz);

#include "quartz_private.h"
#include "devenum.h"
#include "regsvr.h"
#include "enumunk.h"
#include "complist.h"
#include "devmon.h"


/***************************************************************************
 *
 *	new/delete for CLSID_SystemDeviceEnum
 *
 */

/* can I use offsetof safely? - FIXME? */
static QUARTZ_IFEntry IFEntries[] =
{
  { &IID_ICreateDevEnum, offsetof(CSysDevEnum,createdevenum)-offsetof(CSysDevEnum,unk) },
};


static void QUARTZ_DestroySystemDeviceEnum(IUnknown* punk)
{
	CSysDevEnum_THIS(punk,unk);

	CSysDevEnum_UninitICreateDevEnum( This );
}

HRESULT QUARTZ_CreateSystemDeviceEnum(IUnknown* punkOuter,void** ppobj)
{
	CSysDevEnum*	psde;
	HRESULT	hr;

	TRACE("(%p,%p)\n",punkOuter,ppobj);

	psde = (CSysDevEnum*)QUARTZ_AllocObj( sizeof(CSysDevEnum) );
	if ( psde == NULL )
		return E_OUTOFMEMORY;

	QUARTZ_IUnkInit( &psde->unk, punkOuter );

	hr = CSysDevEnum_InitICreateDevEnum( psde );
	if ( FAILED(hr) )
	{
		QUARTZ_FreeObj( psde );
		return hr;
	}

	psde->unk.pEntries = IFEntries;
	psde->unk.dwEntries = sizeof(IFEntries)/sizeof(IFEntries[0]);
	psde->unk.pOnFinalRelease = QUARTZ_DestroySystemDeviceEnum;

	*ppobj = (void*)(&psde->unk);

	return S_OK;
}


/***************************************************************************
 *
 *	CSysDevEnum::ICreateDevEnum
 *
 */


static HRESULT WINAPI
ICreateDevEnum_fnQueryInterface(ICreateDevEnum* iface,REFIID riid,void** ppobj)
{
	CSysDevEnum_THIS(iface,createdevenum);

	TRACE("(%p)->()\n",This);

	return IUnknown_QueryInterface(This->unk.punkControl,riid,ppobj);
}

static ULONG WINAPI
ICreateDevEnum_fnAddRef(ICreateDevEnum* iface)
{
	CSysDevEnum_THIS(iface,createdevenum);

	TRACE("(%p)->()\n",This);

	return IUnknown_AddRef(This->unk.punkControl);
}

static ULONG WINAPI
ICreateDevEnum_fnRelease(ICreateDevEnum* iface)
{
	CSysDevEnum_THIS(iface,createdevenum);

	TRACE("(%p)->()\n",This);

	return IUnknown_Release(This->unk.punkControl);
}

static HRESULT WINAPI
ICreateDevEnum_fnCreateClassEnumerator(ICreateDevEnum* iface,REFCLSID rclsidDeviceClass,IEnumMoniker** ppobj, DWORD dwFlags)
{
	CSysDevEnum_THIS(iface,createdevenum);
	HRESULT	hr;
	HKEY	hKey;
	QUARTZ_CompList*	pMonList;
	IMoniker*	pMon;
	DWORD	dwIndex;
	LONG	lr;
	WCHAR	wszPath[ 1024 ];
	DWORD	dwLen;
	DWORD	dwNameMax;
	DWORD	cbName;
	FILETIME	ftLastWrite;

	TRACE("(%p)->(%s,%p,%08lx)\n",This,
		debugstr_guid(rclsidDeviceClass),ppobj,dwFlags);
	if ( dwFlags != 0 )
	{
		FIXME("unknown flags %08lx\n",dwFlags);
		return E_NOTIMPL;
	}

	if ( ppobj == NULL )
		return E_POINTER;
	*ppobj = NULL;

	hr = QUARTZ_CreateCLSIDPath(
		wszPath, sizeof(wszPath)/sizeof(wszPath[0]),
		rclsidDeviceClass, QUARTZ_wszInstance );
	if ( FAILED(hr) )
		return hr;

	if ( RegOpenKeyExW( HKEY_CLASSES_ROOT, wszPath,
		0, KEY_READ, &hKey ) != ERROR_SUCCESS )
		return E_FAIL;

	dwLen = strlenW(wszPath);
	wszPath[dwLen++] = '\\'; wszPath[dwLen] = 0;
	dwNameMax = sizeof(wszPath)/sizeof(wszPath[0]) - dwLen - 8;

	pMonList = QUARTZ_CompList_Alloc();
	if ( pMonList == NULL )
	{
		hr = E_OUTOFMEMORY;
		goto err;
	}

	/* enumerate all subkeys. */
	dwIndex = 0;
	while ( 1 )
	{
		cbName = dwNameMax;
		lr = RegEnumKeyExW(
			hKey, dwIndex, &wszPath[dwLen], &cbName,
			NULL, NULL, NULL, &ftLastWrite );
		if ( lr == ERROR_NO_MORE_ITEMS )
			break;
		if ( lr != ERROR_SUCCESS )
		{
			hr = E_FAIL;
			goto err;
		}

		hr = QUARTZ_CreateDeviceMoniker(
			HKEY_CLASSES_ROOT, wszPath, &pMon );
		if ( FAILED(hr) )
			goto err;

		hr = QUARTZ_CompList_AddComp(
			pMonList, (IUnknown*)pMon, NULL, 0 );
		IMoniker_Release( pMon );

		if ( FAILED(hr) )
			goto err;

		dwIndex ++;
	}

	/* create an enumerator. */
	hr = QUARTZ_CreateEnumUnknown(
		&IID_IEnumMoniker, (void**)ppobj, pMonList );
	if ( FAILED(hr) )
		goto err;

	hr = S_OK;
err:
	if ( pMonList != NULL )
		QUARTZ_CompList_Free( pMonList );
	RegCloseKey( hKey );

	return hr;
}

static ICOM_VTABLE(ICreateDevEnum) icreatedevenum =
{
	ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
	/* IUnknown fields */
	ICreateDevEnum_fnQueryInterface,
	ICreateDevEnum_fnAddRef,
	ICreateDevEnum_fnRelease,
	/* ICreateDevEnum fields */
	ICreateDevEnum_fnCreateClassEnumerator,
};

HRESULT CSysDevEnum_InitICreateDevEnum( CSysDevEnum* psde )
{
	TRACE("(%p)\n",psde);
	ICOM_VTBL(&psde->createdevenum) = &icreatedevenum;

	return NOERROR;
}

void CSysDevEnum_UninitICreateDevEnum( CSysDevEnum* psde )
{
	TRACE("(%p)\n",psde);
}
