📄 scutil.cxx
字号:
// Function:
// RTpFormatNameToQueueFormat
//
// Description:
// Convert a format name string to a QUEUE_FORMAT union.
//
//---------------------------------------------------------
static BOOL
RTpFormatNameToQueueFormat(
LPCWSTR pfn, // pointer to format name string
QUEUE_FORMAT* pqf, // pointer to QUEUE_FORMAT
LPWSTR* ppStringToFree // pointer to allocated string need to free at end of use
) // if null, format name will not get expanded
{
LPCWSTR p = pfn;
QUEUE_FORMAT_TYPE qft;
if((p = ParsePrefixString(p, qft)) == 0)
return FALSE;
p = skip_ws(p);
if(*p++ != FN_EQUAL_SIGN_C)
return FALSE;
p = skip_ws(p);
GUID guid;
switch(qft)
{
//
// "PUBLIC=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\0"
//
case QUEUE_FORMAT_TYPE_PUBLIC:
if((p = scutil_ParseGuidString(p, &guid)) == 0)
return FALSE;
pqf->PublicID(guid);
break;
//
// "PRIVATE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\\xxxxxxxx\0"
//
case QUEUE_FORMAT_TYPE_PRIVATE:
if((p = scutil_ParseGuidString(p, &guid)) == 0)
return FALSE;
p = skip_ws(p);
if(*p++ != FN_PRIVATE_SEPERATOR_C)
return FALSE;
p = skip_ws(p);
ULONG uniquifier;
if((p = ParsePrivateIDString(p, &uniquifier)) == 0)
return FALSE;
pqf->PrivateID(guid, uniquifier);
break;
//
// "DIRECT=OS:bla-bla\0"
//
case QUEUE_FORMAT_TYPE_DIRECT:
LPCWSTR pExpandedDirectFormat;
if((p = ParseDirectString(p, &pExpandedDirectFormat, ppStringToFree)) == 0)
return FALSE;
pqf->DirectID(const_cast<LPWSTR>(pExpandedDirectFormat));
break;
//
// "MACHINE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\0"
//
case QUEUE_FORMAT_TYPE_MACHINE:
if((p = scutil_ParseGuidString(p, &guid)) == 0)
return FALSE;
pqf->MachineID(guid);
break;
//
// "CONNECTOR=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\0"
//
case QUEUE_FORMAT_TYPE_CONNECTOR:
if((p = scutil_ParseGuidString(p, &guid)) == 0)
return FALSE;
pqf->ConnectorID(guid);
break;
default:
ASSERT(0);
}
p = skip_ws(p);
//
// We're at end of string, return now.
// N.B. Machine format name *must* have a suffix
//
if(*p == L'\0')
return (qft != QUEUE_FORMAT_TYPE_MACHINE);
if(*p != FN_SUFFIX_DELIMITER_C)
return FALSE;
QUEUE_SUFFIX_TYPE qst;
if((p = ParseSuffixString(p, qst)) == 0)
return FALSE;
p = skip_ws(p);
//
// Only white space padding is allowed.
//
if(*p != L'\0')
return FALSE;
pqf->Suffix(qst);
return pqf->Leagal();
}
int scutil_StringToQF (QUEUE_FORMAT *pqf, WCHAR *lpszName) {
return RTpFormatNameToQueueFormat (lpszName, pqf, NULL);
}
int scutil_GetLanNum (void) {
char name[MSMQ_SC_REGBUFFER];
if (gethostname (name, sizeof(name)))
return 0;
HOSTENT *phe = gethostbyname (name);
if (NULL == phe) {
scerror_DebugOutM (VERBOSE_MASK_FATAL, (L"gethostbyname(%S) fails. WSAGetLastError returns 0x%08x\n",name,WSAGetLastError()));
SVSUTIL_ASSERT(0);
return 0;
}
if ((phe->h_addrtype != AF_INET) || (phe->h_length != sizeof (IN_ADDR)) || (*phe->h_addr_list == NULL))
return 0;
int iRes = 0;
IN_ADDR **ppia = (IN_ADDR **)phe->h_addr_list;
while (*ppia != NULL) {
if (ntohl((**ppia).S_un.S_addr) != INADDR_LOOPBACK)
++iRes;
++ppia;
}
return iRes;
}
int scutil_IsLocalTCP (WCHAR *szHostName) {
static int iTcpAddresses = 0;
static unsigned long aulTcpAddresses[MSMQ_SC_MAX_IP_INTERFACES];
if (! szHostName) {
iTcpAddresses = 0;
char name[MSMQ_SC_REGBUFFER];
if (gethostname (name, sizeof(name)))
return 0;
HOSTENT *phe = gethostbyname (name);
if (NULL == phe) {
scerror_DebugOutM (VERBOSE_MASK_FATAL, (L"gethostbyname(%S) fails. WSAGetLastError returns 0x%08x\n",name,WSAGetLastError()));
SVSUTIL_ASSERT(0);
return 0;
}
if ((phe->h_addrtype != AF_INET) || (phe->h_length != sizeof (IN_ADDR)) || (*phe->h_addr_list == NULL))
return FALSE;
IN_ADDR **ppia = (IN_ADDR **)phe->h_addr_list;
while ((*ppia != NULL) && (iTcpAddresses < MSMQ_SC_MAX_IP_INTERFACES)) {
unsigned long ulInterfaceAddress = (**ppia).S_un.S_addr;
if (ulInterfaceAddress != INADDR_LOOPBACK)
aulTcpAddresses[iTcpAddresses++] = ulInterfaceAddress;
++ppia;
}
return iTcpAddresses;
}
char szaddr[MSMQ_SC_IPBUFFER];
if (! WideCharToMultiByte (CP_ACP, 0, szHostName, -1, szaddr, sizeof(szaddr), NULL, NULL))
return FALSE;
unsigned long ul_addr = inet_addr (szaddr);
if (ul_addr == INADDR_NONE)
return FALSE;
for (int i = 0 ; i < iTcpAddresses ; ++i) {
if (ul_addr == aulTcpAddresses[i])
return TRUE;
}
return FALSE;
}
WCHAR* scutil_StrStrWI(const WCHAR * str1, const WCHAR * str2) {
WCHAR *cp = (WCHAR *) str1;
WCHAR *s1, *s2;
while (*cp) {
s1 = cp;
s2 = (WCHAR *) str2;
while ( *s1 && *s2 && (towlower(*s1) == towlower(*s2)) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
void scutil_ReplaceBackSlashesWithSlashes(WCHAR *a_lpszName) {
for (WCHAR *p = a_lpszName; *p; p++) {
if (*p == '\\')
*p = '/';
}
}
//
// CRemoteAllocMgr implementation
// Handles cases when we need to remotely alloc / dealloc memory in the
// caller process. Note this MUST be done on the PSL thread, and not
// on a servicesd.exe worker.
//
//
// Destroys a remote heap.
void DeleteRemoteHeapInfo(void *pvData) {
SVSUTIL_ASSERT((glServiceState == SERVICE_STATE_OFF) || gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = (REMOTE_HEAP_INFO*)pvData;
if (pRemoteInfo->hHeap)
HeapDestroy(pRemoteInfo->hHeap);
}
// Checks current caller process and determines if heap is associated with it.
BOOL DoesHeapInfoBelongToCaller(void *pvContext, void *pvData) {
SVSUTIL_ASSERT(gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = (REMOTE_HEAP_INFO*)pvContext;
// Passed in pvData, via SVSLinkManager filter mechanism, is the
// result of GetCallerVMProcessId(). Don't call it in each call to
// this fcn to avoid extra PSL calls.
return (pRemoteInfo->hProcess == (HANDLE)pvData);
}
// Finds heap caller process owns, and dereferences its usage count, deleting once 0
BOOL DeRefHeapOnProcessDeInit(void *pvContext, void *pvData) {
SVSUTIL_ASSERT(gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = (REMOTE_HEAP_INFO*)pvContext;
// pvData is result of GetCallerVMProcessId() by caller
if (pRemoteInfo->hProcess != (HANDLE)pvData)
return FALSE;
pRemoteInfo->dwRefs--;
if (pRemoteInfo->dwRefs == 0)
return TRUE; // indicate to SVSLinkManager delete this node now
return FALSE; // don't delete this node
}
// Creates a new entry in m_remoteHeaps for process tying into MSMQ (if it wasn't present already)
BOOL CRemoteAllocMgr::InitForProcess(void) {
if (IsCallerProcSameAsCurrent())
return TRUE;
SVSUTIL_ASSERT(gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = FindRemoteHeapOfCaller();
if (pRemoteInfo) {
// Process already has a remote heap structure allocated; just increment ref count.
SVSUTIL_ASSERT(pRemoteInfo->dwRefs >= 1);
pRemoteInfo->dwRefs++;
return TRUE;
}
pRemoteInfo = (REMOTE_HEAP_INFO *)m_remoteHeaps.AllocEntry();
if (! pRemoteInfo)
return FALSE;
pRemoteInfo->dwRefs = 1;
pRemoteInfo->hProcess = (HANDLE)GetCallerVMProcessId();
pRemoteInfo->hHeap = CeRemoteHeapCreate((DWORD)pRemoteInfo->hProcess,0);
if (!pRemoteInfo->hHeap) {
scerror_DebugOutM(VERBOSE_MASK_FATAL,(L"MSMQ: CeRemoteHeapCreate(callerVM=0x%08x) fails, GLE = 0x%08x\r\n",pRemoteInfo->hProcess,GetLastError()));
m_remoteHeaps.RemoveEntry(pRemoteInfo);
return FALSE;
}
return TRUE;
}
// Destroys associated entry in m_remoteHeaps (if ref count is at 0)
BOOL CRemoteAllocMgr::DeInitForProcess(void) {
SVSUTIL_ASSERT(gMem->IsLocked());
m_remoteHeaps.RemoveEntriesFiltered(DeRefHeapOnProcessDeInit, (void*)GetCallerVMProcessId());
return TRUE;
}
// Duplicates a buffer and translates to appropriate address space
BYTE *CRemoteAllocMgr::DuplicateBufferAndTranslate(const BYTE *pbData, DWORD cbData) {
SVSUTIL_ASSERT(gMem->IsLocked());
BYTE *pbCopy;
if (IsCallerProcSameAsCurrent()) {
pbCopy = (BYTE*)LocalAlloc(0,cbData);
if (! pbCopy)
return NULL;
memcpy(pbCopy,pbData,cbData);
return pbCopy;
}
REMOTE_HEAP_INFO *pRemoteInfo = FindRemoteHeapOfCaller();
if (! pRemoteInfo)
return NULL;
pbCopy = (BYTE*)HeapAlloc(pRemoteInfo->hHeap,0,cbData);
if (! pbCopy)
return NULL;
memcpy(pbCopy,pbData,cbData);
return (BYTE*)CeRemoteHeapTranslatePointer(pRemoteInfo->hHeap,0,pbCopy);
};
// Duplicates a string and translates to appropriate address space
WCHAR *CRemoteAllocMgr::DuplicateStringAndTranslate(const WCHAR *szData) {
return (WCHAR*)DuplicateBufferAndTranslate((BYTE*)szData,sizeof(WCHAR)*(wcslen(szData)+1));
}
// Allocates data on the caller's heap.
BYTE *CRemoteAllocMgr::AllocOnCallerHeap(DWORD dwData) {
SVSUTIL_ASSERT(gMem->IsLocked());
if (IsCallerProcSameAsCurrent())
return (BYTE*)LocalAlloc(0,dwData);
REMOTE_HEAP_INFO *pRemoteInfo = FindRemoteHeapOfCaller();
if (! pRemoteInfo)
return NULL;
return (BYTE*)HeapAlloc(pRemoteInfo->hHeap,0,dwData);
}
// Translates the data to caller process address space
BYTE *CRemoteAllocMgr::TranslateData(BYTE *pbData) {
if (IsCallerProcSameAsCurrent())
return pbData;
SVSUTIL_ASSERT(gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = FindRemoteHeapOfCaller();
if (! pRemoteInfo)
return NULL;
return (BYTE*)CeRemoteHeapTranslatePointer(pRemoteInfo->hHeap,0,pbData);
}
// Frees data allocated on remote heap (HeapFree wrapper)
void CRemoteAllocMgr::FreeData(BYTE *pbData) {
if (IsCallerProcSameAsCurrent()) {
LocalFree(pbData);
return;
}
SVSUTIL_ASSERT(gMem->IsLocked());
REMOTE_HEAP_INFO *pRemoteInfo = FindRemoteHeapOfCaller();
if (! pRemoteInfo)
return;
HeapFree(pRemoteInfo->hHeap,0,pbData);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -