//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

#include <pmimpl.h>
#include <msgqueue.h>

// This routine creates a message queue for receiving notifications from appliations
// and other drivers.  It returns a handle to the queue, or NULL.
HANDLE
PmPolicyCreateNotificationQueue(void)
{
    HANDLE hq;
    MSGQUEUEOPTIONS mqo;
    SETFNAME(_T("PmPolicyCreateNotificationQueue"));

    // set up queue characteristics
    memset(&mqo, 0, sizeof(mqo));
    mqo.dwSize = sizeof(mqo);
    mqo.dwFlags = MSGQUEUE_ALLOW_BROKEN;
    mqo.dwMaxMessages = 10;
    mqo.cbMaxMessage = sizeof(POWERPOLICYMESSAGE);
    mqo.bReadAccess = TRUE;

    // create the queue
    hq = CreateMsgQueue(PMPOLICY_NOTIFICATION_QUEUE, &mqo);
    if(hq == NULL) {
        PMLOGMSG(ZONE_INIT || ZONE_ERROR,
            (_T("%s: CreateMsgQueue() failed %d\r\n"), pszFname, GetLastError()));
    }

    return hq;
}

// This routine closes a message queue opened with CreateNotificationQueue().
void
PmPolicyCloseNotificationQueue(HANDLE hq)
{
    DEBUGCHK(hq != NULL);
    BOOL fOk = CloseMsgQueue(hq);
    DEBUGCHK(fOk);
}

// This routine reads a message from the notification queue.  It returns ERROR_SUCCESS
// on completion when the caller's buffer has been filled in or a Win32 error code
// if there's a problem.
DWORD 
PmPolicyReadNotificationQueue(HANDLE hqNotify, LPVOID pvBuffer, DWORD dwSize)
{
    DWORD dwBytesRead, dwFlags, dwStatus;
    SETFNAME(_T("PmPolicyReadNotificationQueue"));

    DEBUGCHK(pvBuffer != NULL);
    DEBUGCHK(dwSize != 0);

    // determine what's happened
    BOOL fOk = ReadMsgQueue(hqNotify, pvBuffer, dwSize, &dwBytesRead, 0, &dwFlags);
    if(!fOk) {
        dwStatus = GetLastError();
        DEBUGCHK(dwStatus != ERROR_SUCCESS);
        PMLOGMSG(ZONE_WARN, (_T("%s: ReadMsgQueue() failed %d\r\n"), pszFname, dwStatus));
        DEBUGCHK(FALSE);
    } else if(dwBytesRead != dwSize) {
        PMLOGMSG(ZONE_WARN, (_T("%s: ReadMsgQueue() returned %d bytes, expected %d\r\n"),
            pszFname, dwBytesRead, dwSize));
        DEBUGCHK(FALSE);
        dwStatus = ERROR_BAD_LENGTH;
    } else {
        dwStatus = ERROR_SUCCESS;
    }

    return dwStatus;
}
