📄 msmqdev.cxx
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: MSMQD.CXX
Abstract: MSMQ service
--*/
#include <windows.h>
#include <stdio.h>
#include <mq.h>
#include <sc.hxx>
#include <scapi.h>
#include <scsrmp.hxx>
#include <service.h>
#include <mqmgmt.h>
#include <psl_marshaler.hxx>
extern "C" DWORD WINAPI scmain_StartDLL (LPVOID lpParm);
extern "C" HRESULT scmain_StopDLL (void);
static long gs_fApiReady = FALSE;
// static HANDLE gs_hDevice = NULL;
static const WCHAR *gs_MachineToken = MO_MACHINE_TOKEN;
unsigned long glServiceState = SERVICE_STATE_OFF;
#if defined (SC_VERBOSE)
extern unsigned int g_bCurrentMask;
extern unsigned int g_bOutputChannels;
#endif
extern "C" BOOL WINAPI DllEntry( HANDLE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch(fdwReason) {
case DLL_PROCESS_ATTACH: {
DisableThreadLibraryCalls((HMODULE)hInstDll);
svsutil_Initialize ();
gMem = new GlobalMemory;
if ((! gMem) || (! gMem->fInitialized))
return FALSE;
}
break;
case DLL_PROCESS_DETACH:
delete gMem;
svsutil_DeInitialize();
break;
}
return TRUE;
}
extern "C" int MSMQDInitialize(TCHAR *szRegPath)
{
return scmain_StartDLL (NULL) ? TRUE : FALSE;
}
extern "C" int MSMQDUnInitialize(void)
{
return scmain_StopDLL ();
}
int scce_RegisterDLL (void) {
if (InterlockedExchange (&gs_fApiReady, TRUE))
return FALSE;
return gs_fApiReady;
}
int scce_UnregisterDLL (void) {
gs_fApiReady = FALSE;
return TRUE;
}
// Changes whether MSMQ is started or stopped at boot time
void SetRegistryStartup(DWORD dwValue) {
HKEY hKey;
// if registry key doesn't exist, don't create it. "msmqadm -register" needs
// to create it to fill in all the other relevant registry settings.
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, MSMQ_SC_REGISTRY_KEY, 0, KEY_READ | KEY_WRITE, &hKey)) {
RegSetValueEx(hKey, L"CEStartAtBoot", 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
RegCloseKey(hKey);
}
}
// Logic to marshall pointers from user-mode services into services.exe, and vice-versa.
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// EXECUTION THREAD: Client-application!
// These functions are only executed on the caller's thread
// i.e. the thread belongs to the client application
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// @func PVOID | MMQ_Init | Device initialization routine
// @parm DWORD | dwInfo | Info passed to RegisterDevice
// @rdesc Returns a DWORD which will be passed to Open & Deinit or NULL if
// unable to initialize the device.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
// NOTE: Since this function can be called in DllMain it cannot block for
// anything otherwise we run a risk of deadlocking
extern "C" DWORD MMQ_Init (DWORD Index)
{
return MSMQDInitialize(NULL);
}
// @func PVOID | MMQ_Deinit | Device deinitialization routine
// @parm DWORD | dwData | value returned from CON_Init call
// @rdesc Returns TRUE for success, FALSE for failure.
// @remark Routine exported by a device driver. "PRF" is the string
// passed in as lpszType in RegisterDevice
// NOTE: Since this function can be called in DllMain it cannot block for
// anything otherwise we run a risk of deadlocking
extern "C" BOOL MMQ_Deinit(DWORD dwData)
{
return scmain_ForceExit();
}
// @func PVOID | MMQ_Open | Device open routine
// @parm DWORD | dwData | value returned from CON_Init call
// @parm DWORD | dwAccess | requested access (combination of GENERIC_READ
// and GENERIC_WRITE)
// @parm DWORD | dwShareMode | requested share mode (combination of
// FILE_SHARE_READ and FILE_SHARE_WRITE)
// @rdesc Returns a DWORD which will be passed to Read, Write, etc or NULL if
// unable to open device.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" DWORD MMQ_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode)
{
HANDLE *hCallerProc = (HANDLE *)g_funcAlloc (sizeof(HANDLE), g_pvAllocData);
if (hCallerProc == NULL)
return 0;
*hCallerProc = NULL;
gMem->Lock();
// If this call fails, not a fatal error. Just means that those
// few MSMQ API's that require RemoteHeap allocation will fail.
gMem->remoteAlloc.InitForProcess();
gMem->Unlock();
return (DWORD)hCallerProc;
}
// @func BOOL | MMQ_Close | Device close routine
// @parm DWORD | dwOpenData | value returned from MMQ_Open call
// @rdesc Returns TRUE for success, FALSE for failure
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" BOOL MMQ_Close (DWORD dwData)
{
// Security note: We're safe dereferencing dwData because it can only be supplied
// by services.exe. No means for a calling app to modify this.
HANDLE *hCallerProc = (HANDLE *)dwData;
if (hCallerProc && (*hCallerProc))
scapi_ProcExit (*hCallerProc);
if (hCallerProc)
g_funcFree (hCallerProc, g_pvFreeData);
return TRUE;
}
// @func DWORD | MMQ_Write | Device write routine
// @parm DWORD | dwOpenData | value returned from CON_Open call
// @parm LPCVOID | pBuf | buffer containing data
// @parm DWORD | len | maximum length to write [IN BYTES, NOT WORDS!!!]
// @rdesc Returns -1 for error, otherwise the number of bytes written. The
// length returned is guaranteed to be the length requested unless an
// error condition occurs.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
//
extern "C" DWORD MMQ_Write (DWORD dwData, LPCVOID pInBuf, DWORD dwInLen)
{
return -1;
}
// @func DWORD | MMQ_Read | Device read routine
// @parm DWORD | dwOpenData | value returned from CON_Open call
// @parm LPVOID | pBuf | buffer to receive data
// @parm DWORD | len | maximum length to read [IN BYTES, not WORDS!!]
// @rdesc Returns 0 for end of file, -1 for error, otherwise the number of
// bytes read. The length returned is guaranteed to be the length
// requested unless end of file or an error condition occurs.
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
//
extern "C" DWORD MMQ_Read (DWORD dwData, LPVOID pBuf, DWORD Len)
{
return -1;
}
// @func DWORD | MMQ_Seek | Device seek routine
// @parm DWORD | dwOpenData | value returned from CON_Open call
// @parm long | pos | position to seek to (relative to type)
// @parm DWORD | type | FILE_BEGIN, FILE_CURRENT, or FILE_END
// @rdesc Returns current position relative to start of file, or -1 on error
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" DWORD MMQ_Seek (DWORD dwData, long pos, DWORD type)
{
return (DWORD)-1;
}
// Wrapper for StringCchCopy
BOOL MySafeStrcpy(wchar_t* pszDest, size_t cchDest, const wchar_t* pszSrc) {
HRESULT hr;
if (NULL == pszSrc)
return FALSE;
__try {
hr = StringCchCopy(pszDest,cchDest,pszSrc);
}
__except(ReportFault(GetExceptionInformation(),0), EXCEPTION_EXECUTE_HANDLER) {
hr = STRSAFE_E_INVALID_PARAMETER;
}
return SUCCEEDED(hr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -