1. C++ / Говнокод #27437

    +1

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    _Return_type_success_(return != false) bool CEnumerateSerial::UsingCreateFile(_Inout_ CPortsArray& ports)
    {
      //Reset the output parameter
      ports.clear();
    
      //Up to 255 COM ports are supported so we iterate through all of them seeing
      //if we can open them or if we fail to open them, get an access denied or general error error.
      //Both of these cases indicate that there is a COM port at that number. 
      for (UINT i=1; i<256; i++)
      {
        //Form the Raw device name
        ATL::CAtlString sPort;
        sPort.Format(_T("\\\\.\\COM%u"), i);
    
        //Try to open the port
        bool bSuccess = false;
        ATL::CHandle port(CreateFile(sPort, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr));
        if (port == INVALID_HANDLE_VALUE)
        {
          const DWORD dwError = GetLastError();
    
          //Check to see if the error was because some other app had the port open or a general failure
          if ((dwError == ERROR_ACCESS_DENIED) || (dwError == ERROR_GEN_FAILURE) || (dwError == ERROR_SHARING_VIOLATION) || (dwError == ERROR_SEM_TIMEOUT))
            bSuccess = true;
        }
        else
        {
          //The port was opened successfully
          bSuccess = true;
        }
    
        //Add the port number to the array which will be returned
        if (bSuccess)
    #pragma warning(suppress: 26489)
          ports.push_back(i);
      }
    
      //Return the success indicator
      return true;
    }

    некоторые джавамэны вот таким гордятся

    > Internally the code provides 10 different ways (yes you read that right: Ten)

    еще и выложено под ни с чем не совместимой лицензией

    Запостил: gologub, 23 Мая 2021

    Комментарии (31) RSS

    • ну что, спойлернуть над каким странным утверджением надо задуматься?
      Ответить
      • Предупреждения вырубили и забыли на место вернуть?
        Ответить
        • нет, там всё гораздо проще, щас если гость не угадает - я вскрою и это приведёт к лавине и извержению одновременно
          Ответить
      • >//Check to see if the error was because some other app had the port open or a general failure
        выглядит как говно
        Ответить
        • Да ладно, этот код хотя бы дискетой не скрипит во время перечисления...
          Ответить
          • Если из ``ERROR_GEN_FAILURE`` следует ``bSuccess = true``, то я такой код ебал
            Извините
            Ответить
            • Ну, может, жизнь такая. Мало ли почему не открылся, но порт есть, пользователю надо показать - пусть сам решает. Может, у кого-то именно это значение вернуло.
              Ответить
    • > Up to 255 COM ports are supported
      Вообще-то up to 256.
      Ответить
      • вот это!
        но... если копнуть глубже окажется, что искаропки поддерживается up to 1024 и расширяемо до 4096, а если забить на "com name arbiter" то ∞

        а несчастный примат этот код 23 года вылизывал, а он оказался полной хуйней
        Ответить
        • приведи пример машины с 1024 ком портами

          Это какая-то станция для дайлап пула в крупном провайдере из 1999-го года?
          Ответить
          • блютус их плодит в большом количестве, например
            Ответить
            • Да и мобилки через USB ACM раньше тоже плодились почему-то, у меня что-то в духе COM23 было под конец.
              Ответить
            • Рискну предположить, что ваши USB устройства каждый раз регистрируют новый порт
              Старый можно удалить, если сказать show hidden devices

              Кто настолько старый, что помнит переменную
              DEVMGR_SHOW_NONPRESENT_DEVICES
              Ответить
        • А есть нормальный способ, кстати?

          Ну там через какое-нибудь setupapi запросить по классу "последовательный порт" или что-то подобное...
          Ответить
          • Распарсить вывод mode.com. Ня забудь про кодировку кодовую страницу! ☆*:.。.o(≧▽≦)o.。.:*☆
            Или "change port /QUERY" распарсить, там хотя бы кириллических букв нят.
            Ответить
            • >change port /QUERY
              ебать откуда ты это знаеш
              Ответить
              • Установил
                c:\> change logon /disable
                на знакомом сервере
                Ответить
            • если порт открыт, то mode его не покажет :-P
              Ответить
          • это даже документировано

            https://docs.microsoft.com/en-us/windows-hardware/drivers/serports/external-naming-of-com-ports
            Ответить
          • https://govnokod.ru/27435#comment629231
            Ответить
    • PS C:\> Get-WmiObject Win32_SerialPort | select DeviceID
      Ответить
      • Переведи на "Си".
        Ответить
        • #define _WIN32_DCOM
          
          #include <iostream>
          #include <Windows.h>
          #include <wbemidl.h>
          #pragma comment(lib, "wbemuuid.lib")
          
          int main()
          {
          	if (FAILED(CoInitializeEx(nullptr, COINIT_MULTITHREADED)))
          	{
          		std::cerr << "Failed to init com" << std::endl;
          		return -1;
          	}
          	CoInitializeSecurity(
          		nullptr,
          		-1,
          		nullptr,
          		nullptr,
          		RPC_C_AUTHN_LEVEL_DEFAULT,
          		RPC_C_IMP_LEVEL_IMPERSONATE,
          		nullptr,
          		EOAC_NONE,
          		nullptr);
          
          	IWbemLocator* pLoc = nullptr;
          	HRESULT hr = CoCreateInstance(CLSID_WbemLocator, 0,
          	                              CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast<LPVOID*>(&pLoc));
          	if (FAILED(hr))
          	{
          		std::cerr << "Failed to create com" << std::endl;
          		return -1;
          	}
          	IWbemServices* pSvc = nullptr;
          	hr = pLoc->ConnectServer(L"\\\\.\\root\\cimv2", NULL, NULL, NULL,
          	                         WBEM_FLAG_CONNECT_USE_MAX_WAIT, NULL, NULL, &pSvc);
          	if (FAILED(hr))
          	{
          		std::cerr << "Failed to connect" << std::endl;
          		return -1;
          	}
          	IEnumWbemClassObject* pEnum = nullptr;
          	hr = pSvc->CreateInstanceEnum(L"Win32_SerialPort", 0, nullptr, &pEnum);
          	if (FAILED(hr))
          	{
          		std::wcerr << L"Failed get query" << hr << std::endl;
          		return -1;
          	}
          	IWbemClassObject* pObj;
          	ULONG returned;
          	while (1)
          	{
          		pEnum->Next(WBEM_INFINITE, 1, &pObj, &returned);
          		if (returned)
          		{
          			VARIANT v;
          			pObj->Get(L"Name", 0, &v, nullptr, nullptr);
          			std::wcout << v.bstrVal;
          		}
          		else
          		{
          			break;
          		}
          	}
          }

          собирать под 14-й vc. Под 17-й нужно явно отключать strictString (с ним wbem не собирается, ссаный BSTR виноват) и с unicode строками

          Нужно сделать обработку ошибок, и завернуть наверное комы в ATL, но я пьяный
          Ответить
          • > но я пьяный

            Оно и видно... кто по трезвости полезет ворошить WMI голыми руками...
            Ответить
    • #include <iostream>
      #include <Windows.h>
      #include <sstream>
      
      int main()
      {
      	char buffer[MAX_PATH]{};
      	for (uint16_t i = 1; i <= 1024; i++)
      	{
      		std::stringstream name;
      		name << "COM" << i;
      		const std::string devName{name.str()};
      		if (QueryDosDeviceA(devName.c_str(), buffer, sizeof(buffer)) == 0)
      		{
      			const auto lastError = GetLastError();
      			if (lastError == ERROR_FILE_NOT_FOUND)
      			{
      				break;
      			}
      			std::cerr << "Error: " << lastError << std::endl;
      			return lastError;
      		}
      		std::cout << devName.c_str() << std::endl;
      	}
      	return 0;
      }
      // не работает старше 4
      Ответить
      • > break

        Заебись, с USB COM девайсами это в принципе не работает, я думаю? У них не меньше 5 и дырки в нумерации, емнип.
        Ответить
        • с дырками не рабоатет точно) нужно все проверять
          Ответить
    • Get-Item HKLM:\HARDWARE\DEVICEMAP\SERIALCOMM\ | Format-Table
      Ответить
      • О, а это можня уже через Ви-няпи нярмальным способом распарсить. Правда, это всё равно будет противняя куча RegOpenKey RegQueryValue RegNyaKawaii...
        Ответить
        • тащемто всё что угодно можно сдеоать через win32pi |(кроме WinRT), просто много буков получится. Что с реестром, что с WMI, очень много буков
          Ответить
          • WMI это же говно со скриптосахаром
            сервис может быть отключен
            или хуже, настроен неторопливо стартовать, когда ты туда полезешь
            или даже еще хуже, не успеть обновить список чтобы туда включить девайс, который ты только что воткнул
            Ответить

    Добавить комментарий