I have reviewed this excellent answer but I am still confused. Ultimately I will have 10 method all behaving similar. Here is an example of three I have written already:
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetChairman());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetChairman();
pReplacement->SetChairman(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithOpenPrayerAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetOpenPrayer());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetOpenPrayer();
pReplacement->SetOpenPrayer(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithClosePrayerAssignment(UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetClosePrayer());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetClosePrayer();
pReplacement->SetClosePrayer(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
I want to code the code from each of those event handlers into a method.
GetChairman
SetChairman
GetOpenPrayer
SetOpenPrayer
GetClosePrayer
SetClosePrayer
I have tried this:
void CChristianLifeMinistryEditorDlg::SwapAssignments(UINT nID, CString(*GetExistingName), void(*SetReplacementName)(CString))
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->(*GetExistingName));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->(*GetExistingName);
pReplacement->(*SetReplacementName)(strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
I get build errors:
How can pass these methods as parameters?
I see this other answer that I was hoping I could use but the problem is that the method being called is a member of an object. So it won't allow it.
Current Workaround
At the moment I have implemented a couple of functions:
CString CChristianLifeMinistryEntry::GetName(SwapAssignment eAssignment)
{
switch (eAssignment)
{
case SwapAssignment::Chairman:
return GetChairman();
case SwapAssignment::Counsellor1:
return GetAuxiliaryCounsellor1();
case SwapAssignment::Counsellor2:
return GetAuxiliaryCounsellor2();
case SwapAssignment::OpenPrayer:
return GetOpenPrayer();
case SwapAssignment::Treasures1:
return GetTreasures1();
case SwapAssignment::Treasures2:
return GetTreasures2();
case SwapAssignment::Living1:
return GetLiving1();
case SwapAssignment::Living2:
return GetLiving2();
case SwapAssignment::ConductorCBS:
return GetCBSConductor();
case SwapAssignment::ReaderCBS:
return GetCBSReader();
case SwapAssignment::ClosePrayer:
return GetClosePrayer();
}
return _T("");
}
// AJT v18.1.6
void CChristianLifeMinistryEntry::SetName(CString strName, SwapAssignment eAssignment)
{
switch (eAssignment)
{
case SwapAssignment::Chairman:
SetChairman(strName);
break;
case SwapAssignment::Counsellor1:
SetAuxiliaryCounsellor1(strName);
break;
case SwapAssignment::Counsellor2:
SetAuxiliaryCounsellor2(strName);
break;
case SwapAssignment::OpenPrayer:
SetOpenPrayer(strName);
break;
case SwapAssignment::Treasures1:
SetTreasures1(strName);
break;
case SwapAssignment::Treasures2:
SetTreasures2(strName);
break;
case SwapAssignment::Living1:
SetLiving1(strName);
break;
case SwapAssignment::Living2:
SetLiving2(strName);
break;
case SwapAssignment::ConductorCBS:
SetCBSConductor(strName);
break;
case SwapAssignment::ReaderCBS:
SetCBSReader(strName);
break;
case SwapAssignment::ClosePrayer:
SetClosePrayer(strName);
break;
}
}
Then I moved the code I mentioned with a little adjustment into a new method:
// AJT v18.1.6
void CChristianLifeMinistryEditorDlg::SwapAssignments(UINT nID, SwapAssignment eAssignment)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetName(eAssignment));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = pReplacement->GetName(eAssignment);
pReplacement->SetName(strExistingName, eAssignment);
if (pReplacement == m_pEntry) // Swapping assignments on same meeting!
SetDlgItemText(IDC_COMBO_OCLM_CBS_READER, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
So now my 11 handlers look similar to this:
// AJT v18.1.6
void CChristianLifeMinistryEditorDlg::OnSwapWithCBSReaderAssignment(UINT nID)
{
SwapAssignments(nID, SwapAssignment::ReaderCBS);
}
It works. But I see a new comment has been added to my question with a link so I will see if I can get anywhere.
So lets refactor the code in stages.
Stage 1:
Isolate the common functionality, first, in a generic function OnSwapWith
template<typename Function>
void CChristianLifeMinistryEditorDlg::OnSwapWith(Function && function,
UINT nID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)pReplacement->GetChairman());
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
function();
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto ChairmanAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetChairman();
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(ChairmanAssignment, nID);
}
void CChristianLifeMinistryEditorDlg::OnSwapWithOpenPrayerAssignment(UINT nID)
{
auto OpenPrayerAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetOpenPrayer();
pReplacement->SetOpenPrayer(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(OpenPrayerAssignment, nID);
}
void CChristianLifeMinistryEditorDlg::OnSwapWithClosePrayerAssignment(UINT nID)
{
auto ClosePrayerAssignment = [&]() // capture by reference (i.e. &)
{
strReplacementName = pReplacement->GetClosePrayer();
pReplacement->SetClosePrayer(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(ClosePrayerAssignment, nID);
}
// and similarly other functions can be defined
After this refactoring, we at least have reduced one level of redundancy.
In this refactoring we have captured everything by reference in the line:
auto ChairmanAssignment = [&]() {};
While capturing by reference, everything is being captured, such as this pointer.
That is why this statement is working :
strReplacementName = pReplacement->GetChairman();
It gets expanded into:
this->strReplacementName = pReplacement->GetChairman();
Stage 2:
Understand that essentially what you are using, were just some generic getters and setters.
So lets refactor it further:
// instead of passing one function, we will pass two : getter and setter
template<typename GetterFunction,
typename SetterFunction>
void CChristianLifeMinistryEditorDlg::OnSwapWith(GetterFunction && getter,
SetterFunction && setter,
UINT nID)
{
...
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = getter(pReplacement);
setter(pReplacement, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
...
}
And the caller side
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto getter = [](CChristianLifeMinistryEntry * pReplacement)
{ // remove the captures now, since we are getting the state with the pointer
return pReplacement->GetChairman();
};
auto setter = [](CChristianLifeMinistryEntry * pReplacement,
CString const & strExistingName)
{
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(getter, setter, nID);
}
Final working code
The 11 menu event handlers look something like:
void CChristianLifeMinistryEditorDlg::OnSwapWithChairmanAssignment(UINT nID)
{
auto getter = [](CChristianLifeMinistryEntry * pReplacement)
{
return pReplacement->GetChairman();
};
auto setter = [](CChristianLifeMinistryEntry * pReplacement,
CString & strExistingName)
{
pReplacement->SetChairman(strExistingName);
};
CChristianLifeMinistryEditorDlg::OnSwapWith(getter, setter,
nID, IDC_COMBO_OCLM_CHAIRMAN);
}
The templated function now looks like:
template<typename GetterFunction, typename SetterFunction>
void CChristianLifeMinistryEditorDlg::OnSwapWith(GetterFunction && getter,
SetterFunction && setter,
UINT nID,
UINT nReplacementCtrlID)
{
// We need to locate the name for this assignment
auto iter = m_mapSwapAssignments.find(nID);
if (iter != m_mapSwapAssignments.end())
{
// We found it
CChristianLifeMinistryEntry *pReplacement = m_mapSwapAssignments[nID];
CString strExistingName = _T(""), strReplacementName = _T("");
GetDlgItemText(m_iSwapAssignmentSourceID, strExistingName);
CString strPrompt = _T("");
strPrompt.Format(_T("Swap assignments:\n\n%s - %s\n%s - %s\n\nPlease confirm."),
m_pEntry->GetMeetingDateAsString(),
(LPCTSTR)strExistingName,
pReplacement->GetMeetingDateAsString(),
(LPCTSTR)getter(pReplacement));
if (AfxMessageBox(strPrompt, MB_ICONQUESTION | MB_YESNO) == IDYES)
{
strReplacementName = getter(pReplacement);
setter(pReplacement, strExistingName);
if (pReplacement == m_pEntry) // Swapping assignments on same meeting!
SetDlgItemText(nReplacementCtrlID, strExistingName);
SetDlgItemText(m_iSwapAssignmentSourceID, strReplacementName);
SetModified(true);
}
}
}
Related
I need to get the pictures in the windows folder and sort them according to the order in which they are displayed. Now there is a method to traverse the entire folder display items through the handle by getting the folder window handle. However, this method has a drawback: it can't get the order of the unopened folder, because there is no open file and no window handle.
Qt is used.
Please forgive my grammatical mistakes.
//Find out the current folder window according to the mouse click position
HWND findOpenFileWindow(const QString& path)
{
Sleep(3 * 1000);
POINT pNow = { 0, 0 };
if (!GetCursorPos(&pNow))
return NULL;
TCHAR szClass[255] = {0};
HWND pMouseChooseHandle = WindowFromPoint(pNow);
HWND pParent = ::GetParent(pMouseChooseHandle);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"SHELLDLL_DefView") == 0 || _tcscmp(szClass, L"NSEViewClass") == 0 )
{
bool bQingDisk = _tcscmp(szClass, L"NSEViewClass") == 0;
pParent = ::GetParent(pParent);
GetClassName(pParent, szClass, 255);
if (_tcscmp(szClass, L"WorkerW"))
{
pParent = pMouseChooseHandle;
for (int i = 0; i < 6; i++)
{
if(pParent != NULL)
pParent = ::GetParent(pParent);
}
HWND pChild = ::GetWindow(pParent, GW_CHILD);
GetClassName(pChild, szClass, 255);
while (pChild != NULL)
{
GetClassName(pChild, szClass, 255);
if (_tcscmp(szClass, TEXT("ShellTabWindowClass")) == 0)
{
pParent = pChild;
break;
}
pChild = ::GetNextWindow(pChild, GW_HWNDNEXT);
}
TCHAR exploreWndName[MAX_PATH] = {0};
::GetWindowText(pParent, exploreWndName, MAX_PATH);
if(QFileInfo(path).fileName() == QString().fromWCharArray(exploreWndName))
return pParent;
}
}
return NULL;
}
//Traverse window display items, get them
QStringList listNormalFolderFile( const QString& path, const QStringList& filter )
{
HWND folderWnd = findOpenFileWindow(path);
HWND hwnd;
IDispatch *pDispatch;
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pShellWindows));
if (FAILED(hr))
{
CoUninitialize();
return QStringList();
}
LONG lCount = 0;
pShellWindows->get_Count(&lCount);
QStringList fileList;
for (LONG i = 0; i < lCount; i++)
{
CComPtr<IShellBrowser> pShellBrowser;
VARIANT var;
var.vt = VT_I4;
var.lVal = i;
if(SUCCEEDED(pShellWindows->Item(var, &pDispatch)))
{
if(SUCCEEDED(IUnknown_QueryService(pDispatch, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser))))
{
if (SUCCEEDED(IUnknown_GetWindow(pShellBrowser, &hwnd)))
{
TCHAR szBuf[256];
GetWindowText(hwnd, szBuf, sizeof(szBuf) / sizeof(TCHAR));
if(QFileInfo(path).fileName() != QString().fromWCharArray(szBuf))
continue;
CComPtr<IShellView> pShellView;
if(FAILED(pShellBrowser->QueryActiveShellView(&pShellView)))
continue;
CComPtr<IFolderView> pFv = NULL;
/*
do something here
*/
CComPtr<IPersistFolder2 > pFolder;
if( FAILED(pFv->GetFolder(IID_IPersistFolder2, (void**) &pFolder)))
continue;
LPITEMIDLIST pidl = nullptr;
if( SUCCEEDED(pFolder->GetCurFolder(&pidl)))
{
wchar_t cPath[32767];
if( ::SHGetPathFromIDList(pidl, cPath))
{
QString filePath;
QFileInfo fileInfo(filePath.fromWCharArray(cPath));
if(fileInfo.absoluteFilePath() == QFileInfo(path).absoluteFilePath())
{
if(folderWnd == NULL || folderWnd == hwnd)
{
fileList = listFileInBrowser(pShellBrowser, filter);
break;
}
}
}
}
}
}
}
}
CoUninitialize();
return fileList;
Hello every one i m trying to develop web filter and i found Win Divert Samples
here the code is i m trying to run in visual Studio 12 and got this error
IntelliSense: argument of type "PVOID" is incompatible with parameter of type "char *"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "windivert.h"
#define MAXBUF 0xFFFF
#define MAXURL 4096
/*
* URL and blacklist representation.
*/
typedef struct
{
char *domain;
char *uri;
} URL, *PURL;
typedef struct
{
UINT size;
UINT length;
PURL *urls;
} BLACKLIST, *PBLACKLIST;
/*
* Pre-fabricated packets.
*/
typedef struct
{
WINDIVERT_IPHDR ip;
WINDIVERT_TCPHDR tcp;
} PACKET, *PPACKET;
typedef struct
{
PACKET header;
UINT8 data[];
} DATAPACKET, *PDATAPACKET;
/*
* THe block page contents.
*/
const char block_data[] =
"HTTP/1.1 200 OK\r\n"
"Connection: close\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<!doctype html>\n"
"<html>\n"
"\t<head>\n"
"\t\t<title>BLOCKED!</title>\n"
"\t</head>\n"
"\t<body>\n"
"\t\t<h1>BLOCKED!</h1>\n"
"\t\t<hr>\n"
"\t\t<p>This URL has been blocked!</p>\n"
"\t</body>\n"
"</html>\n";
/*
* Prototypes
*/
static void PacketInit(PPACKET packet);
static int __cdecl UrlCompare(const void *a, const void *b);
static int UrlMatch(PURL urla, PURL urlb);
static PBLACKLIST BlackListInit(void);
static void BlackListInsert(PBLACKLIST blacklist, PURL url);
static void BlackListSort(PBLACKLIST blacklist);
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url);
static void BlackListRead(PBLACKLIST blacklist, const char *filename);
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data,
UINT16 len);
/*
* Entry.
*/
int __cdecl main(int argc, char **argv)
{
HANDLE handle;
WINDIVERT_ADDRESS addr;
UINT8 packet[MAXBUF];
UINT packet_len;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_TCPHDR tcp_header;
PVOID payload;
UINT payload_len;
PACKET reset0;
PPACKET reset = &reset0;
PACKET finish0;
PPACKET finish = &finish0;
PDATAPACKET blockpage;
UINT16 blockpage_len;
PBLACKLIST blacklist;
unsigned i;
INT16 priority = 404; // Arbitrary.
// Read the blacklists.
if (argc <= 1)
{
fprintf(stderr, "usage: %s blacklist.txt [blacklist2.txt ...]\n",
argv[0]);
exit(EXIT_FAILURE);
}
blacklist = BlackListInit();
for (i = 1; i < (UINT)argc; i++)
{
BlackListRead(blacklist, argv[i]);
}
BlackListSort(blacklist);
// Initialize the pre-frabricated packets:
blockpage_len = sizeof(DATAPACKET)+sizeof(block_data)-1;
blockpage = (PDATAPACKET)malloc(blockpage_len);
if (blockpage == NULL)
{
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
PacketInit(&blockpage->header);
blockpage->header.ip.Length = htons(blockpage_len);
blockpage->header.tcp.SrcPort = htons(80);
blockpage->header.tcp.Psh = 1;
blockpage->header.tcp.Ack = 1;
memcpy(blockpage->data, block_data, sizeof(block_data)-1);
PacketInit(reset);
reset->tcp.Rst = 1;
reset->tcp.Ack = 1;
PacketInit(finish);
finish->tcp.Fin = 1;
finish->tcp.Ack = 1;
// Open the Divert device:
handle = WinDivertOpen(
"outbound && " // Outbound traffic only
"ip && " // Only IPv4 supported
"tcp.DstPort == 80 && " // HTTP (port 80) only
"tcp.PayloadLength > 0", // TCP data packets only
WINDIVERT_LAYER_NETWORK, priority, 0
);
if (handle == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
GetLastError());
exit(EXIT_FAILURE);
}
printf("OPENED WinDivert\n");
// Main loop:
while (TRUE)
{
if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
GetLastError());
continue;
}
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
GetLastError());
}
continue;
}
// The URL matched the blacklist; we block it by hijacking the TCP
// connection.
// (1) Send a TCP RST to the server; immediately closing the
// connection at the server's end.
reset->ip.SrcAddr = ip_header->SrcAddr;
reset->ip.DstAddr = ip_header->DstAddr;
reset->tcp.SrcPort = tcp_header->SrcPort;
reset->tcp.DstPort = htons(80);
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
GetLastError());
}
// (2) Send the blockpage to the browser:
blockpage->header.ip.SrcAddr = ip_header->DstAddr;
blockpage->header.ip.DstAddr = ip_header->SrcAddr;
blockpage->header.tcp.DstPort = tcp_header->SrcPort;
blockpage->header.tcp.SeqNum = tcp_header->AckNum;
blockpage->header.tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, 0);
addr.Direction = !addr.Direction; // Reverse direction.
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, &addr,
NULL))
{
fprintf(stderr, "warning: failed to send block page packet (%d)\n",
GetLastError());
}
// (3) Send a TCP FIN to the browser; closing the connection at the
// browser's end.
finish->ip.SrcAddr = ip_header->DstAddr;
finish->ip.DstAddr = ip_header->SrcAddr;
finish->tcp.SrcPort = htons(80);
finish->tcp.DstPort = tcp_header->SrcPort;
finish->tcp.SeqNum =
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), &addr, NULL))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
GetLastError());
}
}
}
/*
* Initialize a PACKET.
*/
static void PacketInit(PPACKET packet)
{
memset(packet, 0, sizeof(PACKET));
packet->ip.Version = 4;
packet->ip.HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(UINT32);
packet->ip.Length = htons(sizeof(PACKET));
packet->ip.TTL = 64;
packet->ip.Protocol = IPPROTO_TCP;
packet->tcp.HdrLength = sizeof(WINDIVERT_TCPHDR) / sizeof(UINT32);
}
/*
* Initialize an empty blacklist.
*/
static PBLACKLIST BlackListInit(void)
{
PBLACKLIST blacklist = (PBLACKLIST)malloc(sizeof(BLACKLIST));
UINT size;
if (blacklist == NULL)
{
goto memory_error;
}
size = 1024;
blacklist->urls = (PURL *)malloc(size*sizeof(PURL));
if (blacklist->urls == NULL)
{
goto memory_error;
}
blacklist->size = size;
blacklist->length = 0;
return blacklist;
memory_error:
fprintf(stderr, "error: failed to allocate memory\n");
exit(EXIT_FAILURE);
}
/*
* Insert a URL into a blacklist.
*/
static void BlackListInsert(PBLACKLIST blacklist, PURL url)
{
if (blacklist->length >= blacklist->size)
{
blacklist->size = (blacklist->size*3) / 2;
printf("GROW blacklist to %u\n", blacklist->size);
blacklist->urls = (PURL *)realloc(blacklist->urls,
blacklist->size*sizeof(PURL));
if (blacklist->urls == NULL)
{
fprintf(stderr, "error: failed to reallocate memory\n");
exit(EXIT_FAILURE);
}
}
blacklist->urls[blacklist->length++] = url;
}
/*
* Sort the blacklist (for searching).
*/
static void BlackListSort(PBLACKLIST blacklist)
{
qsort(blacklist->urls, blacklist->length, sizeof(PURL), UrlCompare);
}
/*
* Match a URL against the blacklist.
*/
static BOOL BlackListMatch(PBLACKLIST blacklist, PURL url)
{
int lo = 0, hi = ((int)blacklist->length)-1;
while (lo <= hi)
{
INT mid = (lo + hi) / 2;
int cmp = UrlMatch(url, blacklist->urls[mid]);
if (cmp > 0)
{
hi = mid-1;
}
else if (cmp < 0)
{
lo = mid+1;
}
else
{
return TRUE;
}
}
return FALSE;
}
/*
* Read URLs from a file.
*/
static void BlackListRead(PBLACKLIST blacklist, const char *filename)
{
char domain[MAXURL+1];
char uri[MAXURL+1];
int c;
UINT16 i, j;
PURL url;
FILE *file = fopen(filename, "r");
if (file == NULL)
{
fprintf(stderr, "error: could not open blacklist file %s\n",
filename);
exit(EXIT_FAILURE);
}
// Read URLs from the file and add them to the blacklist:
while (TRUE)
{
while (isspace(c = getc(file)))
;
if (c == EOF)
{
break;
}
if (c != '-' && !isalnum(c))
{
while (!isspace(c = getc(file)) && c != EOF)
;
if (c == EOF)
{
break;
}
continue;
}
i = 0;
domain[i++] = (char)c;
while ((isalnum(c = getc(file)) || c == '-' || c == '.') && i < MAXURL)
{
domain[i++] = (char)c;
}
domain[i] = '\0';
j = 0;
if (c == '/')
{
while (!isspace(c = getc(file)) && c != EOF && j < MAXURL)
{
uri[j++] = (char)c;
}
uri[j] = '\0';
}
else if (isspace(c))
{
uri[j] = '\0';
}
else
{
while (!isspace(c = getc(file)) && c != EOF)
;
continue;
}
printf("ADD %s/%s\n", domain, uri);
url = (PURL)malloc(sizeof(URL));
if (url == NULL)
{
goto memory_error;
}
url->domain = (char *)malloc((i+1)*sizeof(char));
url->uri = (char *)malloc((j+1)*sizeof(char));
if (url->domain == NULL || url->uri == NULL)
{
goto memory_error;
}
strcpy(url->uri, uri);
for (j = 0; j < i; j++)
{
url->domain[j] = domain[i-j-1];
}
url->domain[j] = '\0';
BlackListInsert(blacklist, url);
}
fclose(file);
return;
memory_error:
fprintf(stderr, "error: memory allocation failed\n");
exit(EXIT_FAILURE);
}
/*
* Attempt to parse a URL and match it with the blacklist.
*
* BUG:
* - This function makes several assumptions about HTTP requests, such as:
* 1) The URL will be contained within one packet;
* 2) The HTTP request begins at a packet boundary;
* 3) The Host header immediately follows the GET/POST line.
* Some browsers, such as Internet Explorer, violate these assumptions
* and therefore matching will not work.
*/
static BOOL BlackListPayloadMatch(PBLACKLIST blacklist, char *data, UINT16 len)
{
static const char get_str[] = "GET /";
static const char post_str[] = "POST /";
static const char http_host_str[] = " HTTP/1.1\r\nHost: ";
char domain[MAXURL];
char uri[MAXURL];
URL url = {domain, uri};
UINT16 i = 0, j;
BOOL result;
HANDLE console;
if (len <= sizeof(post_str) + sizeof(http_host_str))
{
return FALSE;
}
if (strncmp(data, get_str, sizeof(get_str)-1) == 0)
{
i += sizeof(get_str)-1;
}
else if (strncmp(data, post_str, sizeof(post_str)-1) == 0)
{
i += sizeof(post_str)-1;
}
else
{
return FALSE;
}
for (j = 0; i < len && data[i] != ' '; j++, i++)
{
uri[j] = data[i];
}
uri[j] = '\0';
if (i + sizeof(http_host_str)-1 >= len)
{
return FALSE;
}
if (strncmp(data+i, http_host_str, sizeof(http_host_str)-1) != 0)
{
return FALSE;
}
i += sizeof(http_host_str)-1;
for (j = 0; i < len && data[i] != '\r'; j++, i++)
{
domain[j] = data[i];
}
if (i >= len)
{
return FALSE;
}
if (j == 0)
{
return FALSE;
}
if (domain[j-1] == '.')
{
// Nice try...
j--;
if (j == 0)
{
return FALSE;
}
}
domain[j] = '\0';
printf("URL %s/%s: ", domain, uri);
// Reverse the domain:
for (i = 0; i < j / 2; i++)
{
char t = domain[i];
domain[i] = domain[j-i-1];
domain[j-i-1] = t;
}
// Search the blacklist:
result = BlackListMatch(blacklist, &url);
// Print the verdict:
console = GetStdHandle(STD_OUTPUT_HANDLE);
if (result)
{
SetConsoleTextAttribute(console, FOREGROUND_RED);
puts("BLOCKED!");
}
else
{
SetConsoleTextAttribute(console, FOREGROUND_GREEN);
puts("allowed");
}
SetConsoleTextAttribute(console,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
return result;
}
/*
* URL comparison.
*/
static int __cdecl UrlCompare(const void *a, const void *b)
{
PURL urla = *(PURL *)a;
PURL urlb = *(PURL *)b;
int cmp = strcmp(urla->domain, urlb->domain);
if (cmp != 0)
{
return cmp;
}
return strcmp(urla->uri, urlb->uri);
}
/*
* URL matching
*/
static int UrlMatch(PURL urla, PURL urlb)
{
UINT16 i;
for (i = 0; urla->domain[i] && urlb->domain[i]; i++)
{
int cmp = (int)urlb->domain[i] - (int)urla->domain[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->domain[i] == '\0' && urlb->domain[i] != '\0')
{
return 1;
}
for (i = 0; urla->uri[i] && urlb->uri[i]; i++)
{
int cmp = (int)urlb->uri[i] - (int)urla->uri[i];
if (cmp != 0)
{
return cmp;
}
}
if (urla->uri[i] == '\0' && urlb->uri[i] != '\0')
{
return 1;
}
return 0;
}
This file compiles without errors as C code, so be sure that you compile it as C. If you need to compile it as C++, then add explicit cast to char* at payload parameter in this line:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
Like this:
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
!BlackListPayloadMatch(blacklist, (char*)payload, (UINT16)payload_len))
I used DrawItem () to redraw CListBox. ods_hotlight does not work in win7/win8.
How can I do this CListBox hotlight tracking?
OK ,I solved this now .... ,Code posted below :
extern "C" WINUSERAPI BOOL WINAPI TrackMouseEvent (LPTRACKMOUSEEVENT lpEventTrack);
void CListBoxCS::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
tme.hwndTrack = m_hWnd;
tme.dwHoverTime = 1;
TrackMouseEvent (&tme);
BOOL bOut = TRUE;
short index;
index = (short) ItemFromPoint (point,bOut);
if (FALSE == bOut) {
if (m_ihot != index) {
m_ihot = index;
//printf ("index = %d \n",m_ihot);
Invalidate (FALSE);
}
} else {
//printf ( "out \n" );
}
}
void CListBoxCS::OnMouseLeave (void)
{
//printf ( "mouse leave \n" );
m_ihot = -1;
}
void CListBoxCS::DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// some judgements here .....
// some preparations
// hot light code ...
if ((act & ODA_SELECT) || (act & ODA_DRAWENTIRE)) {
if (lpDIS->itemState & ODS_SELECTED) {
dc.FillSolidRect (&lpDIS->rcItem,(RGB (209, 232, 255)));
} else {
dc.FillSolidRect (&lpDIS->rcItem,(RGB (230, 230, 230)));
}
if (m_ihot == lpDrawItemStruct->itemID) {
dc.FillSolidRect (&lpDIS->rcItem,(RGB (229, 243, 251)));
}
}
// something U like to do ....
}
I started developing a Firefox add-on, however I could not find any IDE specifically for Firefox. For most part it doesn't really matter because I can just open Javascript files and edit them (I use VS2013 and Web Essentials (I think)).
Up to this point everything is acceptable, but when I have to use cmd every time to run this plugin and then read console logs from cmd, it becomes a nightmare.
So my is - is there some way to launch, develop and log Firefox plugin just like any code in Visual Studio 2013? Other IDEs are welcome too.
Well I think it would be possible to create Visual Studio add-on, but it just too much work. However, I managed to partly integrate Firefox add-on creation into VS2013 with c++ code. It redirects cmd window so that means, that you'll output from cmd in "Output" window while debugging.
I'm leaving complete code with steps in case someone else needs this (C++11 is required):
Create Win32 C++ project (not cmd one).
Paste code (below) into cpp file.
Change YOUR_EXTENSION_NAME to your add-on name.
Run code once, it should throw message box with info where to put Add-on SDK.
Copy SDK files to that folder.
Run code again and exit (you may exit however you want, it should terminate remaining windows).
Now there are 3 options for file (.js, .css, etc.) linking:
Create files manually in SDK folder and add them manually to project.
Create files via VS2013 menu and then uncomment and modify, add, delete lines in do while loop.
Create files via VS2013 menu, but choose SDK folders.
Code:
#include <windows.h>
#include <tchar.h>
#include <thread>
#include <chrono>
#include <typeinfo>
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")
// Timer code start
/*
//
//Credit goes to James Daughtry for this piece of code
//
*/
class Timer {
typedef std::chrono::high_resolution_clock high_resolution_clock;
typedef std::chrono::milliseconds milliseconds;
public:
Timer(bool run = false)
{
if (run) Reset();
}
void Reset()
{
_start = high_resolution_clock::now();
}
milliseconds Elapsed() const
{
return std::chrono::duration_cast<milliseconds>(high_resolution_clock::now() - _start);
}
private:
high_resolution_clock::time_point _start;
};
// Timer code end
// Cmd redirection code start
/*
//
//Credit goes to some guys from StackOverflow for directions and Randor from CodeProject for base code
//
*/
struct _JOBWRAPPER
{
HANDLE hJob;
_JOBWRAPPER() : hJob(NULL) {}
~_JOBWRAPPER() { if (this->hJob != NULL) CloseHandle(hJob); }
operator HANDLE() const { return this->hJob; }
}hJob;
typedef void(*TextOutFunction)(LPCSTR);
struct _THREADARGUMENTS
{
HANDLE hOutRead;
clock_t stTimeout;
LPCSTR pchBreakText;
TextOutFunction Function;
bool bGotInfo;
_THREADARGUMENTS() : bGotInfo(false), hOutRead(NULL), stTimeout(NULL), pchBreakText(nullptr), Function(nullptr) {}
};
void ReadCMDThread(_THREADARGUMENTS* Arguments)
{
if (Arguments->hOutRead != NULL)
{
UINT CheckForAnyResponseOnLoop = 5, CurrentLoop = 0;
clock_t ScanInterval = 50;
DWORD dwAvailable = 0;
DWORD bytesRead = 0;
CHAR szOut[4096] = { 0 };
if (Arguments->stTimeout == 0)
{
while (true)
{
CurrentLoop++;
PeekNamedPipe(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, &dwAvailable, NULL);
if (0 != bytesRead)
{
if (ReadFile(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, NULL))
Arguments->bGotInfo = true;
Arguments->Function(szOut);
if (Arguments->pchBreakText != nullptr && Arguments->pchBreakText != "" && strstr(szOut, Arguments->pchBreakText) != nullptr)
break;
memset(szOut, '\0', sizeof(char) * 4096);
}
if (CheckForAnyResponseOnLoop == CurrentLoop && Arguments->pchBreakText == "")
break;
std::this_thread::sleep_for((std::chrono::milliseconds)ScanInterval);
}
}
else
{
Timer timer(true);
while (timer.Elapsed() < (std::chrono::milliseconds)Arguments->stTimeout)
{
CurrentLoop++;
PeekNamedPipe(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, &dwAvailable, NULL);
if (0 != bytesRead)
{
if (ReadFile(Arguments->hOutRead, szOut, sizeof(szOut), &bytesRead, NULL))
Arguments->bGotInfo = true;
Arguments->Function(szOut);
timer.Reset();
if (Arguments->pchBreakText != nullptr && Arguments->pchBreakText != "" && strstr(szOut, Arguments->pchBreakText) != nullptr)
break;
memset(szOut, '\0', sizeof(char) * 4096);
}
if (CheckForAnyResponseOnLoop == CurrentLoop && Arguments->pchBreakText == "")
break;
std::this_thread::sleep_for((std::chrono::milliseconds)ScanInterval);
}
}
}
}
class CMDREDIRECTION{
private:
HANDLE hInRead, hInWrite, hOutRead, hOutWrite;
PROCESS_INFORMATION pi;
STARTUPINFO si;
SECURITY_ATTRIBUTES sa;
TextOutFunction CustomFunction;
public:
CMDREDIRECTION(TextOutFunction Function) : hInRead(NULL), hInWrite(NULL), hOutRead(NULL),
hOutWrite(NULL), CustomFunction(Function) {}
~CMDREDIRECTION(){
if (hInRead != NULL)
CloseHandle(hInRead);
if (hInWrite != NULL)
CloseHandle(hInWrite);
if (hOutRead != NULL)
CloseHandle(hOutRead);
if (hOutWrite != NULL)
CloseHandle(hOutWrite);
}
DWORD WriteToCmd(LPSTR pchString, bool PressEnter = false)
{
DWORD dwWritten = 0;
size_t GivenStringLength = strlen(pchString);
LPSTR TemporaryString = pchString;
bool bSuccess = false;
if (GivenStringLength != 0)
{
if (PressEnter)
{
size_t StringSize = GivenStringLength + 2;
TemporaryString = new CHAR[StringSize];
for (size_t i = 0; i < GivenStringLength; i++)
TemporaryString[i] = pchString[i];
TemporaryString[StringSize - 2] = '\n';
TemporaryString[StringSize - 1] = '\0';
bSuccess = (WriteFile(hInWrite, TemporaryString, strlen(TemporaryString), &dwWritten, NULL) && dwWritten);
delete[] TemporaryString;
}
else
bSuccess = (WriteFile(hInWrite, TemporaryString, strlen(TemporaryString), &dwWritten, NULL) && dwWritten);
}
return bSuccess;
}
bool GetAnswer(clock_t stTimeout, LPCSTR pchBreakText)
{
_THREADARGUMENTS Arguments;
Arguments.hOutRead = hOutRead;
Arguments.pchBreakText = pchBreakText;
Arguments.stTimeout = stTimeout;
Arguments.Function = CustomFunction;
std::thread CMDWatcher(ReadCMDThread, &Arguments);
CMDWatcher.join();
return Arguments.bGotInfo;
}
bool WriteToCmdAndWaitForAnswer(LPSTR pchString, clock_t stTimeout, LPCSTR pchBreakText, bool PressEnter = false)
{
if (WriteToCmd(pchString, PressEnter))
{
return (GetAnswer(stTimeout, pchBreakText));
}
else
{
return false;
}
}
bool Start()
{
if (hJob.hJob == NULL)
{
hJob.hJob = CreateJobObject(NULL, NULL);
if (hJob.hJob != NULL)
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (!SetInformationJobObject((HANDLE)hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
{
return false;
}
}
else
{
return false;
}
}
ZeroMemory(&sa, sizeof(sa));
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
CreatePipe(&hInRead, &hInWrite, &sa, 0);
CreatePipe(&hOutRead, &hOutWrite, &sa, 0);
ZeroMemory(&si, sizeof(si));
GetStartupInfo(&si);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.hStdOutput = hOutWrite;
si.hStdError = hOutWrite;
si.hStdInput = hInRead;
si.wShowWindow = SW_HIDE;
TCHAR Path[MAX_PATH] = { 0 };
GetSystemDirectory(Path, MAX_PATH);
_tcscat_s(Path, TEXT("\\cmd.exe"));
if (CreateProcess(Path, NULL, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
{
BOOL bResult = AssignProcessToJobObject(hJob, pi.hProcess);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return (bResult != 0);
}
else
{
return false;
}
}
};
// Cmd redirection code end
// TString code start
#ifdef UNICODE
#define TCat TCatW
#define TString _TString<WCHAR>
#else
#define TCat TCatA
#define TString _TString<CHAR>
#endif
struct AnyString
{
PVOID String;
bool bWide;
AnyString(LPSTR String)
{
this->String = String;
bWide = false;
}
AnyString(LPWSTR String)
{
this->String = String;
bWide = true;
}
operator LPSTR() { return (LPSTR)String; }
operator LPSTR() const { return (LPSTR)String; }
operator LPWSTR() { return (LPWSTR)String; }
operator LPWSTR() const { return (LPWSTR)String; }
};
template<class T>
class _TString
{
friend void SeAnyString(LPSTR String, _TString<CHAR> &TempString);
T *String;
size_t size;
void free()
{
if (String != nullptr && size != 0)
{
delete[] String;
String = nullptr;
size = 0;
}
}
_TString<CHAR> ToCHAR(LPWSTR wch)
{
_TString<CHAR> TempString;
LPSTR Buffer = nullptr;
size_t size = wcslen(wch),
realsize = size + 1;
if (size != 0)
{
Buffer = new CHAR[realsize];
wcstombs_s(nullptr, Buffer, realsize, wch, size);
TempString.SetAllocatedString(Buffer, size);
}
return TempString;
}
_TString<WCHAR> ToWCHAR(LPSTR ch)
{
_TString<WCHAR> TempString;
LPWSTR Buffer = nullptr;
size_t size = strlen(ch),
realsize = size + 1;
if (size != 0)
{
Buffer = new WCHAR[realsize];
mbstowcs_s(nullptr, Buffer, realsize, ch, size);
TempString.SetAllocatedString(Buffer, size);
}
return TempString;
}
public:
_TString(T *String)
{
free();
if (typeid(T) == typeid(CHAR))
{
size = strlen(String);
if (size != 0)
{
this->String = new T[size + 1];
for (size_t i = 0; i < size; i++)
this->String[i] = String[i];
this->String[size] = '\0';
}
}
else if (typeid(T) == typeid(WCHAR))
{
size = wcslen(String);
if (size != 0)
{
this->String = new T[size + 1];
for (size_t i = 0; i < size; i++)
this->String[i] = String[i];
this->String[size] = L'\0';
}
}
}
_TString() : String(nullptr), size(0) {}
~_TString() { free(); }
_TString(_TString&& OldTempStr)
{
this->String = OldTempStr.String;
this->size = OldTempStr.size;
OldTempStr.size = 0;
OldTempStr.String = nullptr;
}
_TString& operator=(_TString&& OldTempStr)
{
this->String = OldTempStr.String;
this->size = OldTempStr.size;
OldTempStr.size = 0;
OldTempStr.String = nullptr;
return *this;
}
operator T*() const { return String; }
operator T*() { return String; }
T& operator[] (size_t i) { return String[i]; }
void SetAllocatedString(T *String, size_t size)
{
free();
this->String = String;
this->size = size;
}
void join(LPWSTR StringToJoin)
{
join(AnyString(StringToJoin));
}
void join(LPSTR StringToJoin)
{
join(AnyString(StringToJoin));
}
void join(AnyString StringToJoin)
{
if (typeid(T) == typeid(CHAR))
{
size_t length = 0;
_TString<CHAR> TempString;
LPSTR StringLiteral = nullptr;
if (StringToJoin.bWide)
{
TempString = ToCHAR(StringToJoin);
StringLiteral = TempString;
}
else
{
StringLiteral = StringToJoin;
}
if (StringLiteral != nullptr)
length = strlen(StringLiteral);
if (length != 0)
{
size_t newsize = size + length, realsize = newsize + 1;
T *Buffer = new T[realsize];
for (size_t i = 0; i < size; i++)
Buffer[i] = String[i];
for (size_t i = size, j = 0; i < newsize; i++, j++)
Buffer[i] = StringLiteral[j];
Buffer[newsize] = '\0';
free();
size = newsize;
String = Buffer;
}
}
else if (typeid(T) == typeid(WCHAR))
{
size_t length = 0;
_TString<WCHAR> TempString;
LPWSTR StringLiteral = nullptr;
if (StringToJoin.bWide)
{
StringLiteral = StringToJoin;
}
else
{
TempString = ToWCHAR(StringToJoin);
StringLiteral = TempString;
}
if (StringLiteral != nullptr)
length = wcslen(StringLiteral);
if (length != 0)
{
size_t newsize = size + length, realsize = newsize + 1;
T *Buffer = new T[realsize];
for (size_t i = 0; i < size; i++)
Buffer[i] = String[i];
for (size_t i = size, j = 0; i < newsize; i++, j++)
Buffer[i] = StringLiteral[j];
Buffer[newsize] = L'\0';
free();
size = newsize;
String = Buffer;
}
}
}
size_t GetSize() { return size; }
T* GetString() { return String; }
};
_TString<CHAR> TCatA(std::initializer_list<AnyString> list)
{
_TString<CHAR> String;
for (auto iterator = list.begin(), end = list.end(); iterator != end; ++iterator)
String.join(*iterator);
return String;
}
_TString<WCHAR> TCatW(std::initializer_list<AnyString> list)
{
_TString<WCHAR> String;
for (auto iterator = list.begin(), end = list.end(); iterator != end; ++iterator)
String.join(*iterator);
return String;
}
// TString code end
// Main code start
#define EXTENSION_NAME YOUR_EXTENSION_NAME //"my-extension" in ANSI
void WriteToOutputWindow(LPCSTR Text) { OutputDebugStringA(Text); }
void GetProjectDirectory(TString &Path)
{
TCHAR MaxPath[MAX_PATH] = { 0 };
GetModuleFileName(NULL, MaxPath, MAX_PATH);
for (int i = _tcslen(MaxPath), ch = 0; i > 0; i--)
{
if (MaxPath[i] == TEXT('\\') && ++ch == 2)
break;
else
MaxPath[i] = TEXT('\0');
}
Path.join(MaxPath);
}
void GetDataDirectory(TString &Path)
{
GetProjectDirectory(Path);
TCHAR TempBuffer[MAX_PATH] = { 0 }, FinalBuffer[MAX_PATH] = { 0 };
for (size_t i = Path.GetSize() - 1, ch = 0, j = 0; i > 0; i--, j++)
{
if (Path[i] == TEXT('\\') && ++ch == 2)
break;
else
TempBuffer[j] = Path[i];
}
for (size_t i = _tcslen(TempBuffer), j = 0; i > 0; i--, j++)
FinalBuffer[j] = TempBuffer[i - 1];
Path.join(FinalBuffer);
}
bool Restart()
{
int msgboxID = MessageBox(NULL, TEXT("Firefox has been closed. Save changes and press \"Yes\" to run again."), TEXT("Run again?"), MB_YESNO | MB_ICONQUESTION);
switch (msgboxID)
{
case IDYES:
return true;
case IDNO:
return false;
}
}
int WINAPI _tWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrev, _In_ LPTSTR lpCmdLine, _In_ int nCmdShow)
{
CMDREDIRECTION Window(WriteToOutputWindow);
TString ExtensionDir;
TString DataDir;
if (Window.Start())
{
GetProjectDirectory(ExtensionDir);
GetDataDirectory(DataDir);
ExtensionDir.join(TEXT("Firefox SDK\\"));
if (!PathIsDirectory(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer(TCatA({ "mkdir \"", ExtensionDir.GetString(), "\"" }), 0, "", true);
if (PathIsDirectoryEmpty(ExtensionDir))
{
MessageBox(NULL, TCat({ TEXT("Firefox SDK directory is empty, please copy SDK files to this directory: "), ExtensionDir.GetString() }), TEXT("Failure!"), MB_ICONINFORMATION);
return EXIT_FAILURE;
}
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", ExtensionDir.GetString() }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer("bin\\activate", 0, "", true);
ExtensionDir.join(TCat({ TEXT(EXTENSION_NAME), TEXT("\\") }));
if (!PathIsDirectory(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer(TCatA({ "mkdir ", EXTENSION_NAME }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", EXTENSION_NAME }), 0, "", true);
if (PathIsDirectoryEmpty(ExtensionDir))
Window.WriteToCmdAndWaitForAnswer("cfx init", 0, "", true);
do
{
/*
Window.WriteToCmdAndWaitForAnswer(TCatA({ "cd ", DataDir.GetString() }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"main.js\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\lib\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.js\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y /EXCLUDE:exclude.txt" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.html\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.png\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
Window.WriteToCmdAndWaitForAnswer(TCatA({ "XCOPY \"*.css\" \"", ExtensionDir.GetString(), TEXT(EXTENSION_NAME), "\\data\\\" /Y" }), 0, "", true);
*/
Window.WriteToCmdAndWaitForAnswer("cfx run --profiledir=\"./dir\"", 0, "Program terminated successfully.", true);
} while (Restart());
}
return EXIT_SUCCESS;
}
// Main code end
I'm trying to add the file size to this map. It looks like I'm making a mess of things. Any help is appreciated. Thank you.
int GetFileList(const wchar_t *searchkey, std::map<std::wstring, std::wstring> &map)
{
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(searchkey,&fd);
if(h == INVALID_HANDLE_VALUE)
{
return 0; // no files found
}
while(1)
{
wchar_t buf[128];
FILETIME ft = fd.ftLastWriteTime;
SYSTEMTIME sysTime;
FileTimeToSystemTime(&ft, &sysTime);
wsprintf(buf, L"%d-%02d-%02d",sysTime.wYear, sysTime.wMonth, sysTime.wDay);
map[fd.cFileName] = buf;
map[fd.nFileSizeHigh] = buf;
map[fd.nFileSizeLow] = buf;
if(FindNextFile(h, &fd) == FALSE)
break;
}
return map.size();
}
void main()
{
std::map<std::wstring, std::wstring> map;
int count = GetFileList(L"C:\\Users\\DS\\Downloads\\*.zip", map)
&& GetFileList(L"C:\\Users\\DS\\Downloads\\*.txt", map);
for(std::map<std::wstring, std::wstring>::const_iterator it = map.begin();
it != map.end(); ++it)
{
//MessageBoxW(NULL,it->first.c_str(),L"File Name",MB_OK);
//MessageBoxW(NULL,it->second.c_str(),L"File Date",MB_OK);
}
}
Well, you need to decide what you're mapping from, and what you're mapping to.
Probably you want to map from file-name to struct {file-size, file-time}.
Keeping it similar to your code:
struct file_data
{
wstring sLastAccessTime;
__int64 nFileSize ;
};
int GetFileList(const wchar_t *searchkey, std::map<std::wstring, file_data> &map)
{
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile(searchkey,&fd);
if(h == INVALID_HANDLE_VALUE)
{
return 0; // no files found
}
while(1)
{
wchar_t buf[128];
FILETIME ft = fd.ftLastWriteTime;
SYSTEMTIME sysTime;
FileTimeToSystemTime(&ft, &sysTime);
wsprintf(buf, L"%d-%02d-%02d",sysTime.wYear, sysTime.wMonth, sysTime.wDay);
file_data filedata;
filedata.sLastAccessTime= buf;
filedata.nFileSize = (((__int64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
map[fd.cFileName]= filedata;
if (FindNextFile(h, &fd) == FALSE)
break;
}
return map.size();
}
int main()
{
std::map<std::wstring, file_data> map;
GetFileList(L"C:\\Users\\DS\\Downloads\\*.zip", map);
GetFileList(L"C:\\Users\\DS\\Downloads\\*.txt", map);
for(std::map<std::wstring, file_data>::const_iterator it = map.begin();
it != map.end(); ++it)
{
MessageBoxW(NULL,it->first.c_str(),L"File Name",MB_OK);
MessageBoxW(NULL,it->second.sLastAccessTime.c_str(),L"File Date",MB_OK);
}
return 0;
}