# Baixando símbolos e módulos programaticamente
Caloni, 2025-04-07 <self> <drafts> [up] [copy]Essa semana descobri que é possível baixar não apenas os PDBs do symbol server da Microsoft, mas os binários também. Existem relatos de erros de download para alguns binários específicos, mas em geral é possível baixar qualquer arquivo indexado por eles. Para isso você precisa ter em mãos o timestamp do binário, que antes era um timestamp mesmo, mas após o Windows 10 virou um hash único que identifica o mesmo binário e passível de ser compilado de novo exatamente como era, e o tamanho da imagem. Ambas as informações ficam na header do arquivo PE, mas depois que você consegui-las não precisa mais do binário (teoricamente). O código abaixo demonstra isso:
#include <windows.h> #include <dbghelp.h> #include <algorithm> #include <cstdint> #include <filesystem> #include <iostream> #include <string> #include <vector> #pragma comment(lib, "dbghelp.lib") namespace fs = std::filesystem; int main() { const fs::path RootPath = fs::path("resources"); auto isBinary = [](const fs::path& path) { return path.extension() == ".exe" || path.extension() == ".dll" || path.extension() == ".sys"; }; ::SymInitialize(::GetCurrentProcess(), NULL, FALSE); try { for (const auto& entry : fs::directory_iterator(RootPath)) { std::cout << entry.path().string() << std::endl; try { if (entry.is_regular_file() && isBinary(entry.path())) { auto imageName = entry.path().string(); SYMSRV_INDEX_INFO imageFileInfo = { sizeof(imageFileInfo) }; ::SymSrvGetFileIndexInfo(imageName.c_str(), &imageFileInfo, 0); char downloadedImagePath[MAX_PATH + 1] = { 0 }; if (::SymFindFileInPath(GetCurrentProcess(), NULL, imageName.c_str(), &imageFileInfo.timestamp, imageFileInfo.size, 0, SSRVOPT_DWORDPTR, downloadedImagePath, nullptr, nullptr)) { std::cout << "Image file downloaded to " << downloadedImagePath << std::endl; } char downloadedPdbPath[MAX_PATH + 1] = { 0 }; if (::SymFindFileInPath(GetCurrentProcess(), NULL, imageFileInfo.pdbfile, &imageFileInfo.guid, imageFileInfo.age, 0, SSRVOPT_GUIDPTR, downloadedPdbPath, nullptr, nullptr)) { std::cout << "PDB file downloaded to " << downloadedPdbPath << std::endl; } } } catch (std::exception& e) { std::cerr << entry.path().string() << ": " << e.what() << std::endl; } } } catch (std::filesystem::filesystem_error& e) { std::cout << "No resources directory found; nothing to do here: " << e.what(); } ::SymCleanup(::GetCurrentProcess()); return 0; }
= O desafio de Ulisses
O desafio de Ulisses é sobre o que o personagem de Odisseia fez para conseguir ouvir o canto da sereia sem se render aos seus feitiços e acabar sendo devorado por estas criaturas dos mares. Ele pediu que fosse amarrado ao mastro do navio e que em hipótese alguma fosse solto enquanto passassem pelas sereias. Durante o trajeto ele tentou de todas as formas fazer a tripulação o soltar, mas eles foram fiéis ao que ele havia ordenado antes de adentrarem nas tentações do que antes nem eram mulheres com rabo (era o canto a verdadeira tentação).
Esta história é usada por alguns educadores para demonstrar um comprometimento de alguém sobre algo que este alguém não tem controle. É uma técnica de autodisciplina que não depende da disciplina da pessoa nos momentos de tentação.
Com base nisso proponho o seguinte desafio quando estiver para procrastinar ou devanear e precisar focar em algo naquele momento: se desafie a não se distrair por alguns minutos. Não precisam ser muitos, mas precisam ser precisos: "irei trabalhar unicamente nisso pelo menos até 10:15". Em meus testes eu diria que até menos de meia-hora é suficiente para que o momentum se construa e após este tempo você esteja mais tentado a continuar trabalhando do que se render a alguma distração frívola.
A nossa mente é nosso principal algoz contra tendência fisiológicas e esta estratégia inevitavelmente irá sucumbir em algum momento. Quando isso acontecer o que deve ser feito é diminuir mais ainda o número de minutos até um mínimo inegociável. Não se pode abusar dessa técnica e ficar trabalhando horas a fio apenas "aumentando as apostas". Haverá dias melhores.
A ideia do desafio é apenas dar um tempo para que a mente entre e se acostume com o flow do que deve ser feito a ponto disso ser tão ou mais interessante do que qualquer outra coisa que você quisesse fazer antes. Com isso você compromete pouco e sem precisar perder tempo argumento consigo mesmo de que isso é importante. Você está apostando contra sua própria capacidade de controle. Não é tão fácil quanto estar amarrado a um mastro do navio, impedido de se mexer. Mas é simples e tem o potencial de ser efetivo.
# The Willpower Instinct (Kelly McGonigal)
Caloni, 2025-04-29 <self> books> drafts> [up] [copy]Lendo este livro, mas bem lentamente. Seguem recortes.
I believe that the best way to improve your self-control is to see how and why you lose control.
Self-knowledge—especially of how we find ourselves in willpower trouble—is the foundation of self-control.
These are not individual weaknesses that reveal our personal inadequacies—they are universal experiences and part of the human condition.
You can—and should—make yourself the subject of your own real-world study.
Your willpower challenge could be something you’ve been avoiding (what we’ll call an “I will” power challenge) or a habit you want to break (an “I won’t” power challenge). You could also choose an important goal in your life that you’d like to give more energy and focus to (an “I want” power challenge)—
“I will” power challenge: What is something that you would like to do more of, or stop putting off, because you know that doing it will improve the quality of your life? • “I won’t” power challenge: What is the “stickiest” habit in your life? What would you like to give up or do less of because it’s undermining your health, happiness, or success? • “I want” power challenge: What is the most important long-term goal you’d like to focus your energy on? What immediate “want” is most likely to distract you or tempt you away from this goal?
“I will” and “I won’t” power are the two sides of self-control, but they alone don’t constitute willpower. To say no when you need to say no, and yes when you need to say yes, you need a third power: the ability to remember what you really want.
Otherwise, what’s going to stop you from following your immediate desires?
To exert self-control, you need to find your motivation when it matters. This is “I want” power.
For most of evolutionary history, the prefrontal cortex mainly controlled physical movement: walking, running, reaching, pushing—a kind of proto-self-control.
As the prefrontal cortex grew, it took on new control functions: controlling what you pay attention to, what you think about, even how you feel. This made it even better at controlling what you do.
The prefrontal cortex is not one unified blob of gray matter; it has three key regions that divvy up the jobs of I will, I won’t, and I want.
The third region, just a bit lower and in the middle of the prefrontal cortex, keeps track of your goals and your desires. It decides what you want. The more rapidly its cells fire, the more motivated you are to take action or resist temptation.
our primitive brain was not replaced with some completely new model—the system of self-control was slapped on top of the old system of urges and instincts.
There’s the version of us that acts on impulse and seeks immediate gratification, and the version of us that controls our impulses and delays gratification to protect our long-term goals.
The part of you that wants to give in isn’t bad—it simply has a different point of view about what matters most.
Giving a name to this version of yourself can help you recognize when it is taking over, and also help you call in your wiser self for some willpower support.
You need to recognize when you’re making a choice that requires willpower; otherwise, the brain always defaults to what is easiest.
When your mind is preoccupied, your impulses—not your long-term goals—will guide your choices.
To have more self-control, you first need to develop more self-awareness. A good first step is to notice when you are making choices related to your willpower challenge.
For at least one day, track your choices. At the end of the day, look back and try to analyze when decisions were made that either supported or undermined your goals. Trying to keep track of your choices will also reduce the number of decisions you make while distracted—a guaranteed way to boost your willpower.
This week, commit to watching how the process of giving in to your impulses happens. You don’t even need to set a goal to improve your self-control yet. See if you can catch yourself earlier and earlier in the process, noticing what thoughts, feelings, and situations are most likely to prompt the impulse. What do you think or say to yourself that makes it more likely that you will give in?
Regular meditators have more gray matter in the prefrontal cortex, as well as regions of the brain that support self-awareness.
One study found that just three hours of meditation practice led to improved attention and self-control. After eleven hours, researchers could see those changes in the brain.
It may seem incredible that our brains can reshape themselves so quickly, but meditation increases blood flow to the prefrontal cortex, in much the same way that lifting weights increases blood flow to your muscles.
This simple act of staying still is part of what makes meditation willpower training effective. You’re learning not to automatically follow every single impulse that your brain and body produce.
Notice how it feels to breathe, and notice how the mind wanders.
Most new meditators make this mistake, but the truth is that being “bad” at meditation is exactly what makes the practice effective.
Meditation is not about getting rid of all your thoughts; it’s learning not to get so lost in them that you forget what your goal is.
Imagine yourself facing your willpower challenge, and doing the harder thing. What makes it hard?
What does the impulsive version of you want? What does the wiser version of you want?
# O poder do silêncio (Eckhart Tolle)
Caloni, 2025-04-29 <self> <books> <drafts> [up] [copy]Mais um livro sendo relido parcialmente. Alguns recortes.
Os dogmas são prisões formadas por conceitos coletivos. O que parece estranho é que as pessoas gostam de suas prisões, pois elas lhes dão uma sensação de segurança e uma falsa impressão de que “sabem das coisas”.
O reino da consciência é muito mais vasto do que aquilo que o pensamento é capaz de abranger.
A mente funciona com “voracidade” e por isso está sempre querendo mais. Quando você se identifica com a sua mente, fica facilmente entediado e ansioso. O tédio demonstra que a mente deseja avidamente mais estímulo, mais o que pensar, e que essa fome não está sendo saciada.
O tédio é simplesmente um movimento de energia condicionada dentro de você.
Qualquer tipo de preconceito mostra que você está identificado com a mente pensante. Mostra que você não está vendo o outro ser humano, está vendo apenas seu conceito sobre aquele ser humano. Reduzir uma pessoa a um conceito já é uma forma de violência.
Quem percebe isso? Quem compreende que sua forma física e psicológica é passageira? É o Eu Sou. Esse é o “eu” mais profundo, que não tem nada a ver com o passado e o futuro.
Você trata o momento atual como um obstáculo que precisa ser ultrapassado? Você considera mais importante o momento futuro que quer atingir?
Assumir responsabilidade por este momento presente é estar em harmonia com a vida.
# In Search of the Miraculous (P.D. Ouspensky)
Caloni, 2025-04-29 <self> <books> <drafts> [up] [copy]There was another type of school, with which I was unable to make contact and of which I only heard. These schools promised very much but they also demanded very much. They demanded everything at once. It would have been necessary to stay in India and give up thoughts of returning to Europe, to renounce all my own ideas, aims, and plans, and proceed along a road of which I could know nothing beforehand.
# Multiple peers Wireguard calculation
Caloni, 2025-04-30 <code> [up] [copy]/** Multiple peers Wireguard calculation. Wireguard does not support overlapping allowed ips for multiple peers. To cover all possible ips excluding others for secondary peers some calculation is needed to mount the allowed ips list derived from 0.0.0.0. @author Wanderley Caloni <wanderleycaloni@gmail.com> @date 2024-08 */ using System.Net; public class Program { private static void CalculateWireguardAllowedIps(ref HashSet<IPNetwork2> list, IPNetwork2 ip, IPNetwork2 remove) { if (ip.Cidr == 32) { if (ip != remove) { list.Add(ip); } else { Console.WriteLine("CalculateWireguardAllowedIps: found and skipping" + ip.ToString()); } } else { HashSet<IPNetwork2> split = ip.Subnet((byte)(ip.Cidr + 1)).ToHashSet(); // [0]=left, [1]=right if (split.Count == 2) { List<IPNetwork2> splitList = split.ToList(); if (splitList[0].Overlap(remove)) { list.Add(splitList[1]); CalculateWireguardAllowedIps(ref list, splitList[0], remove); } else { list.Add(splitList[0]); CalculateWireguardAllowedIps(ref list, splitList[1], remove); } } } } private static void CalculateWireguardAllowedIps(ref HashSet<IPNetwork2> ipsToAdd, ref HashSet<IPNetwork2> ipsToRemove, ref HashSet<IPNetwork2> list) { foreach (IPNetwork2 remove in ipsToRemove) { var localIpsToAdd = new HashSet<IPNetwork2>(ipsToAdd); foreach (IPNetwork2 add in localIpsToAdd) { if (add.Overlap(remove)) { CalculateWireguardAllowedIps(ref list, add, remove); } else { list.Add(add); } } ipsToAdd = list; } } private static void AddAllowedIp(ref HashSet<IPNetwork2> allowedIps, IPNetwork2 addThisIp, ref HashSet<IPNetwork2> notAddTheseIps) { if (addThisIp.Cidr == 32) { if( ! notAddTheseIps.Contains(addThisIp)) { allowedIps.Add(addThisIp); } else { Console.WriteLine("AddAllowedIp: found and skipping " + addThisIp.ToString()); } } else { List<IPNetwork2> split = addThisIp.Subnet((byte)(addThisIp.Cidr + 1)).ToList(); // [0]=left, [1]=right if (split.Count == 2) { bool overlapLeft = false, overlapRight = false; foreach(IPNetwork2 notIp in notAddTheseIps) { if (split[0].Overlap(notIp)) { overlapLeft = true; } if (split[1].Overlap(notIp)) { overlapRight = true; } if( overlapLeft && overlapRight) { break; } } if (overlapLeft) { AddAllowedIp(ref allowedIps, split[0], ref notAddTheseIps); } else { allowedIps.Add(split[0]); } if (overlapRight) { AddAllowedIp(ref allowedIps, split[1], ref notAddTheseIps); } else { allowedIps.Add(split[1]); } } } } public static int Main(string[] args) { HashSet<IPNetwork2> twoPeersHashSet = new HashSet<IPNetwork2>(); IPNetwork2 allAllowedIPs = new IPNetwork2(IPAddress.Parse("0.0.0.0"), 0); IPNetwork2 removeIP = new IPNetwork2(IPAddress.Parse("66.22.190.0"), 32); CalculateWireguardAllowedIps(ref twoPeersHashSet, allAllowedIPs, removeIP); HashSet<IPNetwork2> multiplePeersHashSet = new HashSet<IPNetwork2>(); HashSet<IPNetwork2> ipsToRemove = new HashSet<IPNetwork2>(); //ipsToRemove.Add(new IPNetwork2(IPAddress.Parse("66.22.190.0"), 32)); ipsToRemove.Add(new IPNetwork2(IPAddress.Parse("66.22.188.1"), 32)); //ipsToRemove.Add(new IPNetwork2(IPAddress.Parse("66.22.190.1"), 32)); //ipsToRemove.Add(new IPNetwork2(IPAddress.Parse("66.22.188.0"), 32)); AddAllowedIp(ref multiplePeersHashSet, allAllowedIPs, ref ipsToRemove); var inMultipleExceptTwoPeers = multiplePeersHashSet.Except(twoPeersHashSet).ToHashSet(); var inTwoPeersExceptMultiple = twoPeersHashSet.Except(multiplePeersHashSet).ToHashSet(); Console.WriteLine("In multiple peers except two peers:"); foreach (var ip in inMultipleExceptTwoPeers) { string s = "ips in " + ip.ToString() + ": "; foreach(var ip2 in ip.ListIPAddress() ) { s += ip2.ToString() + " "; } Console.WriteLine(s); } Console.WriteLine("In two peers except multiple peers:"); foreach (var ip in inTwoPeersExceptMultiple) { string s = "ips in " + ip.ToString() + ": "; foreach(var ip2 in ip.ListIPAddress() ) { s += ip2.ToString() + " "; } Console.WriteLine(s); } return 0; } }
# Set the Windows console to full screen
Caloni, 2025-04-30 code> [up] [copy]#include <iostream> #include <windows.h> int main() { if( ! SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE), CONSOLE_FULLSCREEN_MODE | CONSOLE_WINDOWED_MODE, NULL) ) { // if GetLastError 120 use this: ::SendMessage(::GetConsoleWindow(), WM_SYSKEYDOWN, VK_RETURN, 0x20000000); } system("chcp 65001"); // utf-8 }
# Desafio 5
Caloni, 2025-04-30 <code> [up] [copy]/** My solution to the infamous desafio05 from the site Os Programadores. @author Wanderley Caloni <wanderleycaloni@gmail.com> @date 2020-06 @see https://osprogramadores.com/desafios/d05/ */ #include <boost/iostreams/device/mapped_file.hpp> #include <fstream> #include <iomanip> #include <iostream> #include <map> #include <memory> #include <set> #include <sstream> #include <string> #include <thread> #include <unordered_map> #include <vector> using namespace std; typedef long long int LongInteger; struct Chunk { const char* begin; const char* end; }; struct Employee { Chunk name; Chunk surname; int salary; Chunk area; bool surname_max = false; }; struct Area { string name; vector<Employee> area_max; vector<Employee> area_min; double avg_salary = 0.0; LongInteger total_employees = 0; LongInteger total_salaries = 0; }; struct ParseChunk { shared_ptr<thread> thread_chunk; Chunk data_chunk; map<string, Area> areas; unordered_map<string, vector<Employee>> surname_max; }; template<typename Cmp> inline bool compare_exchange_employees(vector<const Area*>& lst_change, const Area& area_cmp, Cmp cmp) { if (lst_change.size()) { if (cmp(area_cmp.total_employees, (*lst_change.begin())->total_employees)) lst_change = vector<const Area*>{ &area_cmp }; else if (area_cmp.total_employees == (*lst_change.begin())->total_employees) lst_change.push_back(&area_cmp); return true; } else lst_change = vector<const Area*>{ &area_cmp }; return false; } template<typename Cmp> inline bool compare_exchange_salary(vector<Employee>& lst_change, const Employee& employee, Cmp cmp) { if (lst_change.size()) { if (cmp(employee.salary, lst_change.begin()->salary)) lst_change = vector<Employee>{ employee }; else if (employee.salary == lst_change.begin()->salary) lst_change.push_back(employee); return true; } else lst_change = vector<Employee>{ employee }; return false; } template<typename Cmp> inline bool compare_exchange_salary(vector<Employee>& lst_change, const vector<Employee>& lst_cmp, Cmp cmp) { if (lst_change.size()) { if (lst_cmp.size()) { if (cmp(lst_cmp.begin()->salary, lst_change.begin()->salary)) lst_change = lst_cmp; else if (lst_cmp.begin()->salary == lst_change.begin()->salary) lst_change.insert(lst_change.begin(), lst_cmp.begin(), lst_cmp.end()); return true; } } else lst_change = lst_cmp; return false; } void parse(ParseChunk* data) { Employee employee; string surname; string area_name; Area* area; vector<Employee>* employees; auto mystrchr = [&](const char* str, char ch) { while (*str && *str != ch) ++str; return str; }; auto myatoi = [&](const char* beg, const char* end) { int ret = 0; while (beg < end) { char c = *beg++; if (c == '.') continue; ret = ret * 10 + c - '0'; } return ret; }; const char* curr = mystrchr(data->data_chunk.begin, '"'); const char* end; while (curr && curr < data->data_chunk.end) { switch (curr[1]) { case 'i': // employee curr += 2; curr = mystrchr(curr + 1, ','); curr += 6; curr = mystrchr(mystrchr(curr + 1, ':') + 1, '"') + 1; end = mystrchr(curr, '"'); employee.name = Chunk{ curr, end }; curr = end + 11; curr = mystrchr(mystrchr(curr + 1, ':') + 1, '"') + 1; end = mystrchr(curr, '"'); employee.surname = Chunk{ curr, end }; curr = end + 9; curr = mystrchr(curr + 1, ':') + 1; end = mystrchr(curr, '.') + 3; employee.salary = myatoi(curr, end); curr = end + 6; curr = mystrchr(mystrchr(curr + 1, ':') + 1, '"') + 1; end = mystrchr(curr, '"'); employee.area = Chunk{ curr, end }; curr = end + 1; curr = mystrchr(curr, '}'); area_name = string(employee.area.begin, employee.area.end); area = &data->areas[area_name]; compare_exchange_salary(area->area_max, employee, greater<LongInteger>()); compare_exchange_salary(area->area_min, employee, less<LongInteger>()); surname = string(employee.surname.begin, employee.surname.end); employees = &data->surname_max[surname]; compare_exchange_salary(*employees, employee, greater<LongInteger>()); ++area->total_employees; area->total_salaries += employee.salary; break; case 'c': // area curr += 6; curr = mystrchr(mystrchr(curr + 1, ':') + 1, '"') + 1; end = mystrchr(curr, '"'); area_name = string(curr, end); curr = end + 6; curr = mystrchr(mystrchr(curr + 1, ':') + 1, '"') + 1; end = mystrchr(curr, '"'); data->areas[area_name].name = string(curr, end); curr = end + 1; curr = mystrchr(curr, '}'); break; } curr = mystrchr(curr + 1, '"'); } } int main(int argc, char* argv[]) { if (argc == 2) { const char* fileName = argv[1]; boost::iostreams::mapped_file_source fileMap; fileMap.open(fileName); if (fileMap.is_open()) { const char* data = fileMap.data(); size_t cores = std::thread::hardware_concurrency(); size_t chunkSize = fileMap.size() / cores; vector<ParseChunk> chunks(cores); for( size_t i = 0; i < cores; ++i ) { const char* begin = data + (i * chunkSize); const char* end = data + ( (i+1) * chunkSize); chunks[i].data_chunk = Chunk{ begin, end }; chunks[i].thread_chunk = make_shared<thread>(parse, &chunks[i]); } ParseChunk total; Area global; for (const auto& chunk : chunks) { chunk.thread_chunk->join(); for (const auto& area : chunk.areas) { Area& total_area = total.areas[area.first]; total_area.total_employees += area.second.total_employees; total_area.total_salaries += area.second.total_salaries; compare_exchange_salary(total_area.area_max, area.second.area_max, greater<LongInteger>()); compare_exchange_salary(total_area.area_min, area.second.area_min, less<LongInteger>()); if( area.second.name.size() ) total_area.name = area.second.name; } for (const auto& surname_max : chunk.surname_max ) { const string& surname = surname_max.first; vector<Employee>& total_surname = total.surname_max[surname]; bool exchange = compare_exchange_salary(total_surname, surname_max.second, greater<LongInteger>()); total_surname.begin()->surname_max = exchange; } } vector<const Area*> most_employees, least_employees; for (auto& area : total.areas) { if (area.second.total_employees) { area.second.avg_salary = ( double(area.second.total_salaries) / 100.0 ) / double(area.second.total_employees); global.total_employees += area.second.total_employees; global.total_salaries += area.second.total_salaries; compare_exchange_salary(global.area_max, area.second.area_max, greater<LongInteger>()); compare_exchange_salary(global.area_min, area.second.area_min, less<LongInteger>()); compare_exchange_employees(most_employees, area.second, greater<LongInteger>()); compare_exchange_employees(least_employees, area.second, less<LongInteger>()); } } global.avg_salary = ( double(global.total_salaries) / 100.0 ) / double(global.total_employees); auto out_salary = [](LongInteger salary) -> string { ostringstream os; os << (salary / 100) << '.' << setfill('0') << setw(2) << (salary % 100); return os.str(); }; for (const auto& emp : global.area_max) cout << "global_max|" << string(emp.name.begin, emp.name.end) << ' ' << string(emp.surname.begin, emp.surname.end) << '|' << out_salary(emp.salary) << '\n'; for (const auto& emp : global.area_min) cout << "global_min|" << string(emp.name.begin, emp.name.end) << ' ' << string(emp.surname.begin, emp.surname.end) << '|' << out_salary(emp.salary) << '\n'; cout << "global_avg|" << fixed << setprecision(2) << global.avg_salary << '\n'; for (const auto& area : total.areas) { for (const auto& emp : area.second.area_max) cout << "area_max|" << area.second.name << '|' << string(emp.name.begin, emp.name.end) << ' ' << string(emp.surname.begin, emp.surname.end) << '|' << out_salary(emp.salary) << '\n'; for (const auto& emp : area.second.area_min) cout << "area_min|" << area.second.name << '|' << string(emp.name.begin, emp.name.end) << ' ' << string(emp.surname.begin, emp.surname.end) << '|' << out_salary(emp.salary) << '\n'; if( area.second.total_employees ) cout << "area_avg|" << area.second.name << '|' << fixed << setprecision(2) << area.second.avg_salary << '\n'; } for (const auto& emp : most_employees) cout << "most_employees|" << emp->name << '|' << emp->total_employees << '\n'; for (const auto& emp : least_employees) cout << "least_employees|" << emp->name << '|' << emp->total_employees << '\n'; for (const auto& emps : total.surname_max) { if (emps.second.begin()->surname_max || emps.second.size() > 1) { string surname = string(emps.second.begin()->surname.begin, emps.second.begin()->surname.end); for (const auto& emp : emps.second) cout << "last_name_max|" << surname << '|' << string(emp.name.begin, emp.name.end) << ' ' << surname << '|' << out_salary(emp.salary) << '\n'; } } fileMap.close(); } } else cout << "How to use: program <input-file>\n"; }
# Download PDB symbols
Caloni, 2025-04-30 <code> [up] [copy]#include <windows.h> #include <dbghelp.h> #include <algorithm> #include <cstdint> #include <filesystem> #include <iostream> #include <string> #include <vector> #pragma comment(lib, "dbghelp.lib") namespace fs = std::filesystem; int main() { const fs::path RootPath = fs::path("resources"); auto isBinary = [](const fs::path& path) { return path.extension() == ".exe" || path.extension() == ".dll" || path.extension() == ".sys"; }; ::SymInitialize(::GetCurrentProcess(), NULL, FALSE); try { for (const auto& entry : fs::directory_iterator(RootPath)) { std::cout << entry.path().string() << std::endl; try { if (entry.is_regular_file() && isBinary(entry.path())) { auto imageName = entry.path().string(); SYMSRV_INDEX_INFO imageFileInfo = { sizeof(imageFileInfo) }; ::SymSrvGetFileIndexInfo(imageName.c_str(), &imageFileInfo, 0); char downloadedImagePath[MAX_PATH + 1] = { 0 }; if (::SymFindFileInPath(GetCurrentProcess(), NULL, imageName.c_str(), &imageFileInfo.timestamp, imageFileInfo.size, 0, SSRVOPT_DWORDPTR, downloadedImagePath, nullptr, nullptr)) { std::cout << "Image file downloaded to " << downloadedImagePath << std::endl; } char downloadedPdbPath[MAX_PATH + 1] = { 0 }; if (::SymFindFileInPath(GetCurrentProcess(), NULL, imageFileInfo.pdbfile, &imageFileInfo.guid, imageFileInfo.age, 0, SSRVOPT_GUIDPTR, downloadedPdbPath, nullptr, nullptr)) { std::cout << "PDB file downloaded to " << downloadedPdbPath << std::endl; } } } catch (std::exception& e) { std::cerr << entry.path().string() << ": " << e.what() << std::endl; } } } catch (std::filesystem::filesystem_error& e) { std::cout << "No resources directory found; nothing to do here: " << e.what(); } ::SymCleanup(::GetCurrentProcess()); return 0; }
# Hook using detour
Caloni, 2025-04-30 <code> [up] [copy]#include <detours.h> #include <windows.h> using namespace std; decltype(SendMessageA)* Orig_SendMessageA = ::SendMessageA; decltype(SendMessageW)* Orig_SendMessageW = ::SendMessageW; LRESULT WINAPI Hook_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI Hook_SendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); struct Hook { PVOID& original; PVOID hook; }; static Hook g_installedHooks[] = { { (PVOID&)Orig_SendMessageA, Hook_SendMessageA }, { (PVOID&)Orig_SendMessageW, Hook_SendMessageW }, }; LRESULT WINAPI Hook_SendMessageA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { LRESULT l = Orig_SendMessageA(hWnd, Msg, wParam, lParam); printf("Hook_SendMessageA %x %d", hWnd, Msg); return l; } LRESULT WINAPI Hook_SendMessageW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { LRESULT l = Orig_SendMessageW(hWnd, Msg, wParam, lParam); printf("Hook_SendMessageW %x %d", hWnd, Msg); return l; } static void InstallHooks() { DetourRestoreAfterWith(); DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); for (auto& hook : g_installedHooks) { DetourAttach(&(PVOID&)hook.original, hook.hook); } DetourTransactionCommit(); } static void UninstallHooks() { DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); for (auto& hook : g_installedHooks) { DetourDetach(&hook.original, hook.hook); } DetourTransactionCommit(); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (DetourIsHelperProcess()) { return TRUE; } if (ul_reason_for_call == DLL_PROCESS_ATTACH) { //MessageBoxA(NULL, "Ready to install hooks", "Dll1", 0); LogFormat("Installing hooks"); InstallHooks(); LogFormat("Hooks installed"); } else if (ul_reason_for_call == DLL_PROCESS_DETACH) { LogFormat("Uninstalling hooks"); UninstallHooks(); LogFormat("Hooks uninstalled"); } return TRUE; }
# Subir escadas
Caloni, 2025-04-30 <body> essays> [up] [copy]Subir escadas é o exercício mais simples possível que mantém em forma as partes mais importantes do seu corpo no longo prazo: pernas e coração. Com as pernas em forma você deve conseguir chegar em uma idade avançada podendo se locomover. Com o músculo do coração em dia você deve conseguir suportar bombear sangue com eficiência e sem sobrecarga. Subir escadas é simples porque basta achar uma escada e começar a subir. O ritmo é definido pela sua capacidade física do momento. Pode ser que um dia suba mais rápido, outro dia mais lento. Você deve subir pelo tempo que achar possível para você, sem comprometer o corpo nem a agenda. Você pode alternar o ritmo ao prestar atenção ao coração batendo mais ou menos, a tontura vindo ou as pernas se cansando. Você pode forçar o corpo de vez em quando a subir o platô ouvindo podcast ou música enquanto faz o exercício, conscientemente ignorando alguns avisos do corpo para se lançar alguns degraus a mais. Você não precisa mensurar nada fora do seu corpo. O tempo gasto não importa. O ritmo não importa. A geolocalização não importa. Se mover importa. Portanto se mova e quando achar melhor pare. Repita de vez em quando. Não precisa ser todos os dias. Não exija disciplina de você. Apenas constância. E isso irá adicionar um hábito saudável e regulável por décadas a fio em seu itinerário de atividades. Irá também aos poucos te inspirar a fazer outras atividades, como caminhadas ao ar livre ou até algo mais ousado. Quem definirá serão seus gostos e sua vontade, moldada pelo pequeno degrau inicial que você ousou subir.
# Journaling and coding
Caloni, 2025-04-30 <essays> [up] [copy]Codar e blogar são tarefas equivalentes. Quando digo blogar estou me referindo a escrever em geral. Textos são apenas linguagens de programação naturais que usam símbolos que seres humanos conseguem decodificar. E como somos máquinas de Turing completas, nossas leituras do mundo, textuais ou outros, interferem nas nossas saídas, e assim por diante. Escrever textos em linguagem natural ou linguagens de programação são essencialmente atividades que codificam símbolos em uma certa disposição, modificam símbolos obedecendo determinadas regras da chamada gramática. Quando estou escrevendo código ou um texto para o blogue a atividade deveria seguir exatamente os mesmos passos, assim como a montagem do histórico, o que significa documentar as mudanças no controle de fonte.
# Não é o Ulisses, é o salto (para se comprometer é preciso estar tranquilo)
Caloni, 2025-04-30 <self> <essays> [up] [copy]Um dos meus últimos textos descrevi o conceito do desafio de Ulisses, uma metáfora de um livro grego que pode ser utilizado hoje em dia como dica de produtividade ou de treino de resiliência em qualquer atividade medida em um tempo mínimo de foco. No entanto, após isso descobri que não é o desafio do tempo que importa mais. O que importa mais é realizar o salto. Assim como Neo.
O salto é que te coloca em um outro plano, onde as regras são diferentes. As regras do jogo mudam para o que a atividade se propõe. Toda a forma de pensar muda a partir daí. A transição pode demorar algum tempo, mas é um tempo pequeno o suficiente para conseguirmos focar até que a atividade se torna interessante por si só.
Porém, para saltar e não cair você deve estar tranquilo, centrado. Precisa ser outra pessoa. Assim como Neo. Essa outra pessoa, renascida da primeira, enxerga a realidade sob a ótica das novas regras. E é utilizando essas novas regras que ela deve se movimentar neste novo mundo. O mundo antigo deixa para depois. Um salto de cada vez.