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

    +51

    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
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    96. 96
    97. 97
    98. 98
    99. 99
    DWORD getDirectoryIndex()
    	{
    		STATIC_OBJECT_ATTRIBUTES(oa, "\\");
    		HANDLE hFile;
    		DWORD ObjectTypeIndex = 0;
    
    		if (0 <= ZwOpenDirectoryObject(&hFile, DIRECTORY_QUERY, &oa))
    		{
    			NTSTATUS status;
    			PVOID buf = 0, stack = alloca(guz);
    			DWORD cb = 0, rcb = 0x10000;
    
    			do 
    			{
    				if (cb < rcb) cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
    
    				if (0 <= (status = ZwQuerySystemInformation(SystemExtendedHanfleInformation, buf, cb, &rcb)))
    				{
    					PSYSTEM_HANDLE_INFORMATION_EX pshti = (PSYSTEM_HANDLE_INFORMATION_EX)buf;
    
    					if (ULONG NumberOfHandles = (ULONG)pshti->NumberOfHandles)
    					{
    						PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles = pshti->Handles;
    
    						ULONG_PTR UniqueProcessId = GetCurrentProcessId();
    						do 
    						{
    							if (Handles->UniqueProcessId == UniqueProcessId && Handles->HandleValue == (ULONG_PTR)hFile)
    							{
    								ObjectTypeIndex = Handles->ObjectTypeIndex;
    								break;
    							}
    
    						} while (Handles++, --NumberOfHandles);
    					}
    				}
    			} while (STATUS_INFO_LENGTH_MISMATCH == status);
    
    			ZwClose(hFile);
    		}
    
    		return ObjectTypeIndex;
    	}
    
    	ZOBJECT_ALL_TYPES_INFORMATION()
    	{
    		_TypeInformation = 0, _NumberOfTypes = 0;
    
    		if (DWORD DirectoryTypeIndex = getDirectoryIndex())
    		{
    			PVOID stack = alloca(guz);
    			OBJECT_ALL_TYPES_INFORMATION* poati = 0;
    			DWORD cb = 0, rcb = 0x2000;
    			NTSTATUS status;
    			do 
    			{
    				if (cb < rcb)
    				{
    					cb = RtlPointerToOffset(poati = (OBJECT_ALL_TYPES_INFORMATION*)alloca(rcb - cb), stack);
    				}
    
    				if (0 <= (status = ZwQueryObject(0, ObjectAllTypeInformation, poati, cb, &rcb)))
    				{
    					if (DWORD NumberOfTypes = poati->NumberOfTypes)
    					{
    						if (OBJECT_TYPE_INFORMATION* TypeInformation = (OBJECT_TYPE_INFORMATION*)LocalAlloc(0, rcb))
    						{
    							_NumberOfTypes = NumberOfTypes;
    							_TypeInformation = TypeInformation;
    
    							STATIC_UNICODE_STRING_(Directory);
    							OBJECT_TYPE_INFORMATION* pti = poati->TypeInformation;
    							PWSTR buf = (PWSTR)(TypeInformation + NumberOfTypes);
    							int Index = 0;
    							do 
    							{
    								if (RtlEqualUnicodeString(&Directory, &pti->TypeName, TRUE))
    								{
    									_firstObjectTypeIndex = DirectoryTypeIndex - Index;
    								}
    
    								DWORD Length = pti->TypeName.Length, MaximumLength = pti->TypeName.MaximumLength;
    								memcpy(buf, pti->TypeName.Buffer, Length);
    
    								*TypeInformation = *pti;
    								TypeInformation++->TypeName.Buffer = buf;
    
    								buf = (PWSTR)RtlOffsetToPointer(buf, Length);
    
    								pti = (OBJECT_TYPE_INFORMATION*)
    									(((ULONG_PTR)pti + sizeof(OBJECT_TYPE_INFORMATION) + MaximumLength + sizeof(PVOID)-1) & ~(sizeof(PVOID)-1));
    
    							} while (Index++, --NumberOfTypes);
    						}
    					}
    				}
    			} while (status == STATUS_INFO_LENGTH_MISMATCH);
    		}
    	}

    ObjectTypeIndex

    Запостил: zhukas, 15 Ноября 2014

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

    • >if (0 <= (status = ZwQuerySystemInformation(SystemExtendedH anfleInformation, buf, cb, &rcb))
      Ааааа, опять пидорасы со своим Йодапетухом.
      Ответить
      • Да хрен с ним, с йодой. В обратном порядке будет ничуть не лучше. Зачем вообще сувать присваивание и сравнение в один if?
        Ответить
        • Чтобы хвалиться тем, что в Паскале так нельзя.
          Ответить
        • Портит чтения порядок Йода. Меинтейнить код надо будет, ЕВПОЧЯ.

          А присваивание в if это классика из K&R. Проблема в том, что идиоты суют это куда ни попадя.
          Ответить
          • А в каких примерах присваивание в if можно обосновать?
            Ответить
            • Ни в каких. Сишка* один фиг не даёт объявлять переменные в if'е. Поэтому нет никакого разумного повода тащить присваивание в if**.

              * кресты дают
              ** в while - есть
              Ответить
              • while(*i++ = *j++); или есть более сложные примеры?
                Ответить
                • struct passwd *entry;
                  while (entry = getpwent()) {
                      // ...
                  }
                  endpwent();
                  Ответить
                  • >while (entry = getpwent())
                    А я потом думаю, какого хера компилеры не ругаются на присваивания в условиях.
                    Вот она крестопедерастия: сайд-эффект неявным конвертом погоняет.

                    Кстати в жабах похожая вайл гомосятина тоже в моде:
                    while (null!=(str=inputStream.readLine()))
                    Было б неявное преобразование в булеан писали б так, инфа 100%
                    while ( str=inputStream.readLine() )
                    Ответить
                    • > Было б неявное преобразование в булеан писали б так, инфа 100%
                      Было бы счастье...
                      Ответить
                    • Альтернатива некрасивая :(
                      while (1) {
                          struct passwd *entry = getpwent();
                          if (!entry)
                              break;
                          // ...
                      }
                      Ответить
                    • Так оно же не неявное. true / false с точки зрения логики - как раз самого широкого типа. Т.е. Приведение к bool - это вполне легитимная операция с точки зрения вменяемой системы типов. Неявное, это когда приведение типов происходит между типами между котороыми не существует отношения "А подтип Б" ни в ту ни в другую сторону, например, между строками и числами.
                      Ответить
                      • Ну или неявное еще может быть от более узкого к более широкому типу, но такое ни одна система не позволяет сделать без специального антуража, так что только между несовместимыми типами.
                        Ответить
                      • > Т.е. Приведение к bool - это вполне легитимная операция с точки зрения вменяемой системы типов.
                        И как прикажете приводить строку к bool? true - Если ссылка не равна null?
                        К чему должны привестить во "вменяемой системе типов" такие значения, например: " TrUe ", "On", "Нет", "Maybe".
                        Ответить
                        • Нужен параметризованный оператор приведения к булу.
                          Параметр - строка.
                          Внутри - сравнение с образцом.

                          BoolOperator myB ("str2");
                          if (myB(s))
                          ...


                          Напомнило библиотеку http://www.gamedev.ru/flame/forum/?id=170447 такой же бессмысленный и беспощадный пародийно-быдлоынтерпрайзный код.
                          Ответить
                        • Истина это самый широкий тип, любая строка - это более конкретная истина, т.е. всегда true. Для удобства, ложь есть только одна (потому что нам не интересны разные некогерентные правила / формулы).
                          Ответить
                          • > Для удобства, ложь есть только одна
                            Какая?
                            Ответить
                            • Они все эквивалентны. Ну, как бы это еще показать. Предположим, что наша система типов - это логика нулевого порядка, т.е. без квантификаторов и без функций. И наши типы исчерпываются таблицами истинности для логических операций типа отрицания, и, или, следование и т.д. В такой системе мы можем представить ложь бесконечно разными формулами, но они нам все одинаково не интересны. Например, для нас что (true => true) |= false, что (~false) |= false - одно и то же, не смотря на то, что записаны по-разному.

                              Плохо, что строки не контейнеры? - Ну, я не так понимаю качество. На мой взгляд, плохо, это когда система заведомо некогерентная. А в том, что если мы определили строку как список, и получили, что пустая строка = false, нет ничего плохого. Это непосредственно следует из определения. Есть задачи, где желательно иметь контейнеры, а есть - где лучше без них. Например, с контейнерами, когда пустые контейнеры вдруг оказываются разного типа становится очень неудобно жить. С другой стороны, без контейнеров тяжело со ссылками (как передать куда-то пустой список на модификацию?).
                              Ответить
                              • Я понял что Вы имеете ввиду, оперируя в терминах (есть/нету) но не нахожу в этом особого практического применения.
                                Ответить
                          • > ложь есть только одна
                            А Наутилиус Помпилиус наоборот пел.
                            Ответить
                            • С правдой есть проблема... судя по всему, ее вообще нету. Есть только то, ложность чего еще не доказана.
                              Ответить
                        • Другой способ на это посмотреть. Найти как описываются через лямбда-исчисление числа - есть куча примеров. Строку можно в таком случае описать как список из чисел. Любое число - истина, строка - коль скоро в ней есть числа, тоже истина.

                          Вот дальше уже становится интереснее, т.как в разных языках под строкой понимаются разные вещи. Где-то у строки есть контейнер, и тогда строка никогда не может быть ложью, либо контейнера нет, и тогда пустой список - одна из разновидностей строк, которая может быть ложью.
                          Ответить
                          • >Вот дальше уже становится интереснее, т.как в разных языках под строкой понимаются разные вещи.
                            В сишкоблядских религиях под строкой может пониматься указатель на массив, и до нуля.
                            >Строку можно в таком случае описать как список из чисел.
                            Строку можно описать как указатель. 0 - false, остальное - true.

                            Но выше и ведется речь об том что это не есть хорошо. Пользы особой не вижу.
                            Ведь всё-равно понадобится какой-то parseBool.
                            Ответить
    • А по какой причине эта функция на таком низком уровне работает (Zw*)?

      P.S. А, понял, это драйвер.
      Ответить
      • >это драйвер.
        нет это не может быть драйвером.
        LocalAlloc в коде - уже usermode
        память выделяется в стеке ( alloca ). а стека в ядре 3-5 страниц всего. а там 0x10000 как минимум выделяется. сразу bsod.
        100% user mode
        Ответить
        • В куче , я хотел сказать. А не в сиеке
          Ответить
        • Как-то ты неточно сказал.
          Во-первых таки да: не в стеке, а в куче. В-вторых дело не в количестве страниц, а в том что из ядра негоже обращаться к выгружаемой памяти. Потому для ядра есть специальный невыгружаемый пул (тоесть память которая никогда не засвапица на диск). Почему? Да потому что когда некто обращается к засвоплиной памяти, то случае page fault, обработчик которого запускается и загружает страницы в память. А это во-первых слишком долго для ядра, во-вторых код в ядре может выставить такой Interrupt Request Level, что обработчик пейджфолта обосрется с IRQ_NOT_LESS_OR_EQUAL и упадет в BSOD, как ты правильно сказал.

          Так что в ядре мы почти всегда хотим работать с невыгружаемой памятью, а её (как ты правильно сказал) аллоцируют специальными функциями из WDK вроде ExAllocatePoolWithTag и иже с ними, а не LocalAllocом.

          И вообще LocalAlloc это легаси говно мамонта времен когда были глобальные и локальные кучи отдельно (что-то времен Win16), а теперь вроде как надо юзать HeapAlloc.
          Ответить
          • 1)код типа
            if (cb < rcb) cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
            безусловно выделяет память в стеке а не в куче. и само название функции - http://msdn.microsoft.com/en-us/library/x9sx5da1.aspx и семантика выделения.
            2)а в том что из ядра негоже обращаться к выгружаемой памяти... - безграмотный и идиотский бред
            3)вызов LocalAlloc(0, cb) эквивалентен вызову HeapAlloc(GetProcessHeap(), 0x14000, cb) . так что никакой разницы с HeapAlloc
            Ответить
            • 1)да, ты прав. Я думал речь идет про LocalAlloc, который все таки "Allocates the specified number of bytes from the heap."
              2) Што?;)
              [quote]
              Drivers use the NonPaged Pool for many of their requirements because they can be accessed at any Interrupt Request Level (IRQL). The IRQL defines the hardware priority at which a processor operates at any given time (there's a link to a document covering Scheduling, Thread Context and IRQL's in the Additional Resources section at the end of this post).
              [/quote]. Речь конечно именно о драйверах, а не о ЛЮБОМ коде уровня ядра. (fixed)
              3) да?
              [quote]
              The local functions have greater overhead and provide fewer features than other memory management functions. New applications should use the heap functions unless documentation states that a local function should be used. For more information, see Global and Local Functions.
              [/quote]
              Ответить
              • 2) Што?;) - то
                по пунктам
                1.)из ядра негоже обращаться к выгружаемой памяти - бред. возмите хотя бы любой запрос из юзер мода с буферами - как его выполнить если к выгружаемой памяти негоже обращаться D) ? большинство объектов ядро размещает в выгружаемой памяти. в невыгружаемой - только то что реально необходимо.

                2.)Потому для ядра есть специальный невыгружаемый пул - ну и что ? paged pool(который гораздо больше чем nonpaged) тоже есть. ни и что ??

                3.)А это во-первых слишком долго для ядра - а для не ядра, не слишком долго ? ) к чему все эти рассуждения ? что они доказывают ? да, память иногда выгружается в своп. при обращении к ней page fault (не важно из ядра или не ядра). если адрес корректный - страница загружается (скорость загрузки страницы не зависит от того, кто к ней обратился. и дальше что ??

                4.)во-вторых код в ядре может выставить такой Interrupt Request Level.. - можно много чего сделать. НУ И ЧТО ??? вы увидели в данном коде игры с IRQL ?

                так что код ядра постоянно обращается к выгружаемой памяти. если когда нибудь начнёте писать драйвера, а не просто читать msdn - может быть это поймёте.

                3) да?
                да! именно так ( LocalAlloc(0, cb) эквивалентен вызову HeapAlloc(GetProcessHeap(), 0x14000, cb))
                если умеете пользоваться дебаггером и понимать asm - это очень легко увидеть. и это так от win2000 до win10
                "The local functions have greater overhead" - в случае когда флаги равны 0 - фунции эквиваленты и нет никакого overhead.
                кстати множество системных api - когда выделяют память сами (а пользователь должен затем освободить её) - то используют именно LocalAlloc(0, cb)
                ну например:
                http://msdn.microsoft.com/en-us/library/windows/desktop/aa379912%28v=vs.85%29.aspx (смотри CRYPT_DECODE_ALLOC_FLAG)
                Ответить
                • 2) Да, теперь я вижу что мой комментарий и правда выглядит хуитой, так как покрывает только частный случай с задраным IRQL, не имеющий тем паче отношения к конкретному коду) Спасибо за развёрнутый ответ.

                  3) Вполне верю Вам что получившийся код одинаков.
                  Даже без дебагера можно прочитать "Starting with 32-bit Windows, GlobalAlloc and LocalAlloc are implemented as wrapper functions that call HeapAlloc using a handle to the process's default heap. "
                  Правда всё равно непонятно зачем использовать старое API, про которое сказано что "New applications should use другое API", кроме конечно случаев "documentation states that a local function should be used" (и это видимо как раз приведенный Вами CRYPT_DECODE_ALLOC_FLAG, где "..and the LocalFree function must be called to free the memory.").
                  Какой смысл объявлять API депрекрейтед черте-когда, и все равно предагать пользователю им пользоваться?
                  Ответить
                • ps:
                  Короче говоря достаточно того что LocalAlloc лежит в kernel32.dll, и потому наврядли будет встречен в кернел-спейсе потому что в native его нельзя юзать, и никакие пулы тут не причем, верно?
                  Ответить

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