使用两个 LPTSTR 时发生堆损坏
Heap corruption while working with two LPTSTRs
我一直在使用从过滤器驱动程序接收消息的应用程序。驱动程序运行完美,但我的内存管理有问题,可能是 LPTSTRs user & domain。
调试时我收到有关堆损坏的消息,它们通常指向两个 free 或第二个 LookupAccountSid 调用。我在这里做错了什么?
#include "stdafx.h"
#include "myapp-service.h"
#include <Windows.h>
#include <fltUser.h>
#include <string>
#include <sddl.h>
BOOL
getUser(
_In_ WCHAR* sidstr,
_Inout_ LPTSTR* AcctName,
_Inout_ LPTSTR* DomainName
)
{
PSID sid;
DWORD dwAcctName = 1;
DWORD dwDomainName = 1;
SID_NAME_USE eUse = SidTypeUnknown;
bool success;
if (!ConvertStringSidToSidW(sidstr, &sid))
{
printf_s("ConvertStringSidToSid failed with 0x%08x\n", GetLastError);
return false;
}
// Lookup!
LookupAccountSid(
NULL,
sid,
*AcctName,
(LPDWORD)&dwAcctName,
*DomainName,
(LPDWORD)&dwDomainName,
&eUse);
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName);
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName);
success = LookupAccountSid(
NULL,
sid,
*AcctName,
(LPDWORD)&dwAcctName,
*DomainName,
(LPDWORD)&dwDomainName,
&eUse);
if (success) {
_tprintf(TEXT("Username %s@%s\n"), *AcctName, *DomainName);
}
else {
printf_s("LookupAccountSid failed with 0x%08x\n", GetLastError);
return false;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT status;
HANDLE port;
myapp_USER_MESSAGE msg;
//
// Open a communication channel to the filter
//
printf("myapp-service: Connecting to the filter ...\n");
status = FilterConnectCommunicationPort(myappPortName,
0,
NULL,
0,
NULL,
&port);
if (IS_ERROR(status)) {
printf("ERROR: Connecting to filter port: 0x%08x\n", status);
return 2;
}
//
// Fetch messages & handle them
//
while (TRUE) {
status = FilterGetMessage(port,
&msg.MessageHeader,
sizeof(msg),
NULL
);
if (status == S_OK) {
// Got a message successfully!
// The problem is most likely with these two
LPTSTR user = NULL;
LPTSTR domain = NULL;
if (getUser(msg.Message.Sid, &user, &domain)) {
_tprintf(TEXT("Username %s@%s accessed %ls at %ls\n"), user, domain, &msg.Message.FileName, &msg.Message.TimeStamp);
}
else {
printf("Unable to get user data!");
};
if (user) {
GlobalFree(user);
}
if (domain) {
GlobalFree(domain);
}
}
else {
printf("ERROR: GetMessage: 0x%08x\n", status);
}
printf("\n\n");
}
//
// Close the communication channel to the filter
//
printf("myapp-service: Closing connection ...\n");
CloseHandle(&port);
return 0;
}
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName*sizeof(TCHAR));
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName*sizeof(TCHAR));
因为 LookupAccountSid return 大小以 TCHAR 为单位,而不是以字节为单位
LookupAccountSid are prefixed with cch
(i.e. count of characters). You'll have to account for that when allocating memory, since GlobalAlloc的参数cchName
和cchReferenceDomainName
取字节数:
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName * sizeof(TCHAR));
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName * sizeof(TCHAR));
您还应该在第一次调用之前对大小参数进行零初始化:
DWORD dwAcctName = 0x0;
DWORD dwDomainName = 0x0;
文档中对此进行了概述:
If the function fails because the buffer is too small or if cchName is zero, cchName receives the required buffer size, including the terminating null character.
顺便说一句:您的两个 printf_s
调用都将打印 GetLastError
的 地址 ,而不是它的 return 值。您必须添加括号 (GetLastError()
) 才能调用函数。
我一直在使用从过滤器驱动程序接收消息的应用程序。驱动程序运行完美,但我的内存管理有问题,可能是 LPTSTRs user & domain。
调试时我收到有关堆损坏的消息,它们通常指向两个 free 或第二个 LookupAccountSid 调用。我在这里做错了什么?
#include "stdafx.h"
#include "myapp-service.h"
#include <Windows.h>
#include <fltUser.h>
#include <string>
#include <sddl.h>
BOOL
getUser(
_In_ WCHAR* sidstr,
_Inout_ LPTSTR* AcctName,
_Inout_ LPTSTR* DomainName
)
{
PSID sid;
DWORD dwAcctName = 1;
DWORD dwDomainName = 1;
SID_NAME_USE eUse = SidTypeUnknown;
bool success;
if (!ConvertStringSidToSidW(sidstr, &sid))
{
printf_s("ConvertStringSidToSid failed with 0x%08x\n", GetLastError);
return false;
}
// Lookup!
LookupAccountSid(
NULL,
sid,
*AcctName,
(LPDWORD)&dwAcctName,
*DomainName,
(LPDWORD)&dwDomainName,
&eUse);
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName);
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName);
success = LookupAccountSid(
NULL,
sid,
*AcctName,
(LPDWORD)&dwAcctName,
*DomainName,
(LPDWORD)&dwDomainName,
&eUse);
if (success) {
_tprintf(TEXT("Username %s@%s\n"), *AcctName, *DomainName);
}
else {
printf_s("LookupAccountSid failed with 0x%08x\n", GetLastError);
return false;
}
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT status;
HANDLE port;
myapp_USER_MESSAGE msg;
//
// Open a communication channel to the filter
//
printf("myapp-service: Connecting to the filter ...\n");
status = FilterConnectCommunicationPort(myappPortName,
0,
NULL,
0,
NULL,
&port);
if (IS_ERROR(status)) {
printf("ERROR: Connecting to filter port: 0x%08x\n", status);
return 2;
}
//
// Fetch messages & handle them
//
while (TRUE) {
status = FilterGetMessage(port,
&msg.MessageHeader,
sizeof(msg),
NULL
);
if (status == S_OK) {
// Got a message successfully!
// The problem is most likely with these two
LPTSTR user = NULL;
LPTSTR domain = NULL;
if (getUser(msg.Message.Sid, &user, &domain)) {
_tprintf(TEXT("Username %s@%s accessed %ls at %ls\n"), user, domain, &msg.Message.FileName, &msg.Message.TimeStamp);
}
else {
printf("Unable to get user data!");
};
if (user) {
GlobalFree(user);
}
if (domain) {
GlobalFree(domain);
}
}
else {
printf("ERROR: GetMessage: 0x%08x\n", status);
}
printf("\n\n");
}
//
// Close the communication channel to the filter
//
printf("myapp-service: Closing connection ...\n");
CloseHandle(&port);
return 0;
}
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName*sizeof(TCHAR));
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName*sizeof(TCHAR));
因为 LookupAccountSid return 大小以 TCHAR 为单位,而不是以字节为单位
LookupAccountSid are prefixed with cch
(i.e. count of characters). You'll have to account for that when allocating memory, since GlobalAlloc的参数cchName
和cchReferenceDomainName
取字节数:
*AcctName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwAcctName * sizeof(TCHAR));
*DomainName = (LPTSTR)GlobalAlloc(GMEM_FIXED, dwDomainName * sizeof(TCHAR));
您还应该在第一次调用之前对大小参数进行零初始化:
DWORD dwAcctName = 0x0;
DWORD dwDomainName = 0x0;
文档中对此进行了概述:
If the function fails because the buffer is too small or if cchName is zero, cchName receives the required buffer size, including the terminating null character.
顺便说一句:您的两个
printf_s
调用都将打印 GetLastError
的 地址 ,而不是它的 return 值。您必须添加括号 (GetLastError()
) 才能调用函数。