1. Си / Говнокод #13069

    +108

    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
    bool getSelectedFile(wchar_t *out, bool skip) {
    	HWND hwndFind = GetForegroundWindow();
    
    	TCHAR g_szPath[BUF_SIZE];
    	TCHAR g_szItem[BUF_SIZE];
    	//g_szPath[0] = TEXT('\0');
    	//g_szItem[0] = TEXT('\0');
    	memset(g_szPath, 0, sizeof(TCHAR) * BUF_SIZE);
    	memset(g_szItem, 0, sizeof(TCHAR) * BUF_SIZE);
    
    	IShellWindows *psw;
    	if(CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_IShellWindows, (void**)&psw) != S_OK) return false;
    	
    	VARIANT v;
    	v.vt = VT_I4;
    	IDispatch  *pdisp;
    	bool fFound = false;
    	bool pExtracted = false;
    	bool nExtracted = false;
    	
    	for (V_I4(&v) = 0; !fFound && psw->Item(v, &pdisp) == S_OK; V_I4(&v)++) {
    			IWebBrowserApp *pwba;
    			if(SUCCEEDED(pdisp->QueryInterface(IID_IWebBrowserApp, (void**)&pwba))) {
    				HWND hwndWBA;
    				if (SUCCEEDED(pwba->get_HWND((LONG_PTR*)&hwndWBA)) && hwndWBA == hwndFind) {
    					fFound = true;
    					IServiceProvider *psp;
    					if(SUCCEEDED(pwba->QueryInterface(IID_IServiceProvider, (void**)&psp))) {
    						IShellBrowser *psb;
    						if(SUCCEEDED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, (void**)&psb))) {
    							IShellView *psv;
    							if(SUCCEEDED(psb->QueryActiveShellView(&psv))) {
    								IFolderView *pfv;
    								if(SUCCEEDED(psv->QueryInterface(IID_IFolderView, (void**)&pfv))) {
    									IPersistFolder2 *ppf2;
    									if(SUCCEEDED(pfv->GetFolder(IID_IPersistFolder2, (void**)&ppf2))) {
    										LPITEMIDLIST pidlFolder;
    										if(SUCCEEDED(ppf2->GetCurFolder(&pidlFolder))) {
    											if(SHGetPathFromIDList(pidlFolder, g_szPath)) {
    												pExtracted = true;
    												if(skip) {
    													lstrcpy(out, g_szPath);
    													out[lstrlen(g_szPath)] = 0;
    													return true;
    												}
    											}
    											int iFocus;
    											if(SUCCEEDED(pfv->GetFocusedItem(&iFocus))) {
    												LPITEMIDLIST pidlItem;
    												if (SUCCEEDED(pfv->Item(iFocus, &pidlItem))) {
    													IShellFolder *psf;
    													if (SUCCEEDED(ppf2->QueryInterface(IID_IShellFolder, (void**)&psf))) {
    														STRRET str;
    														if(SUCCEEDED(psf->GetDisplayNameOf(pidlItem, SHGDN_INFOLDER, &str))) {
    															StrRetToBuf(&str, pidlItem, g_szItem, 1024);
    															nExtracted = true;
    															int psz = lstrlen(g_szPath);
    															int isz = lstrlen(g_szItem);
    															if(pExtracted) {
    																lstrcpy(out, g_szPath);
    																out[psz] = '\\';
    															}
    															lstrcpy(out+psz+1, g_szItem);
    															out[psz + isz + 2] = 0;
    														}
    														psf->Release();
    													}
    													CoTaskMemFree(pidlItem);
    												}
    											}
    											CoTaskMemFree(pidlFolder);
    										}
    										ppf2->Release();
    									}
    									pfv->Release();
    								}
    								psv->Release();
    							}
    							psb->Release();
    						}
    						psp->Release();
    					}
    				}
    				pwba->Release();
    			}
    			pdisp->Release();
    	}
    	psw->Release();
    	return (pExtracted && nExtracted);
    }

    Две очаровательных (говно) лестницы из какой-то очередной переназначалки горячих клавиш в Windows.
    Оригинал тут: https://github.com/mapseamoff/KeyBinder/blob/master/ShellHelper/ShellHelper/main.cpp

    Запостил: kovnogod, 29 Мая 2013

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

    • с++ же
      Ответить
    • Деструкторов не хватает
      Ответить
      • Для сишки switch case
        Ответить
        • Чаво? о.О
          Ответить
          • Никогда на сишке не писал чтоль?

            #include <stdio.h>
            #include <stdbool.h>
            bool init1(void){printf("init1\n");return true;}
            bool init2(void){printf("init2\n");return true;}
            bool init3(void){printf("init3 failed\n");return false;}
            void work(void){printf("work\n");}
            void uninit3(void){printf("uninit3\n");}
            void uninit2(void){printf("uninit2\n");}
            void uninit1(void){printf("uninit1\n");}
             
            int main(void) {
                int il=0;
                if (!(
                            init1() &&
                    ++il,   init2() &&
                    ++il,   init3() &&
                    ++il))  goto fsemu_pesec_posoni111;
                        
                work();
             
                fsemu_pesec_posoni111:
                switch(il)
                {
                    default: break;
                    case 3:
                        uninit3();
                    case 2:
                        uninit2();
                    case 1:
                        uninit1();
                }
                    return 0;
            }

            http://ideone.com/SuLk5o

            PS: Обновил, дефекейстра снизу лучше высрал с do while
            Ответить
            • #include <stdio.h>
              #include <stdbool.h>
              bool init1(void){printf("init1\n");return true;}
              bool init2(void){printf("init2\n");return true;}
              bool init3(void){printf("init3 failed\n");return false;}
              void work(void){printf("work\n");}
              void uninit3(void){printf("uninit3\n");}
              void uninit2(void){printf("uninit2\n");}
              void uninit1(void){printf("uninit1\n");}
               
              int main(void) {
                  int il=0;
                          init1() &&
                  ++il,   init2() &&
                  ++il,   init3() &&
                  ++il;
                  
                  switch(il)
                  {
                      case 3:
                          work();
                          uninit3();
                      case 2:
                          uninit2();
                      case 1:
                          uninit1();
                      default:;
                  }
                      return 0;
              }

              http://ideone.com/52YbOs
              Ответить
            • На C89 чуток переписывал/дописывал за кем-то, но на подобный трюк еще ни разу не натыкался; теперь я вижу смысл в твоих предыдущих фразах.
              Ответить
    • Блин, примитивнейший ComPtr пишется за 15-20 минут с отладкой и перекуром. ThrowIfFailed - вообще за 30 секунд. Как будто автор писал для нелюбимой работы, на которой работать заставляют.
      А в эту кашу
      /*...*/wchar_t *out/*...*/
      TCHAR g_szPath[BUF_SIZE];
      out[psz] = '\\';
      думать даже не хочется.
      Ответить
    • А как избавиться от лестницы?
      Я бы так сделал.
      if ( ! init1() ) goto fail_init1;
      //some code
      if ( ! init2() ) goto fail_init2;
      //some code
      if ( ! init3() ) goto fail_init3;
      
      //everything is good
      
      uninit3();
      fail_init3:
      uninit2();
      fail_init2:
      uninit1();
      fail_init1:
      Ответить
      • тебе для с++ или с?
        Ответить
        • Судя по его коду - для C.
          Ответить
          • ну человек увлекается sql, откуда мне знать, какие у него альтернативные интересы :)
            в сишке switch (errlevel) мне нравится гораздо больше goto
            Ответить
            • Да, в использовании errorlevel есть смысл - все равно нам нужно возвращать из функции успех\неуспех. И если мы не делаем errorlevel - все равно придется заводить какой-нибудь флажок/код статуса, чтобы вернуть его после cleanup'а.
              Ответить
        • Мне просто любопытно.
          Но, если не сложно, то и то и другое давай.
          Ответить
          • на с++, как уже @Xom94ok написал выше, нет ничего сложного в том, чтобы написать свой собственный класс smart legacy handle, иногда заюзать shared_ptr (особенно, когда в нем есть дополнительный и нужный профит - передать сраный хендл куда то дальше) - последний позволяет задать "деструктор" для передаваемого вовнутрь указателя
            для COM, в принципе, уже есть библиотечный CComPtr в сраном ATL, который сделает Release в деструкторе

            на сишке - все варианты сводятся к тому, что надо проэмулировать try { ... } finally, это делается либо через goto (я не сторонник этого способа), либо через do { ... } while (0); с бряками

            конкретно пример выше со сферическими initXXX() можно было бы сделать вот так:
            #define BREAK_IF_FAILED(f)  if (!(f)) break
            int error_level = 0;
            do {
                BREAK_IF_FAILED(init1());
                ++error_level;
                BREAK_IF_FAILED(init2());
                ++error_level;
                BREAK_IF_FAILED(init3());
                ++error_level;
                return success;  // or smth else
            } while (0);
            
            switch (error_level) {
            case 3:    uninit3();
            case 2:    uninit2();
            case 1:    uninit1();
            default:   break;
            }
            Ответить
    • У меня в проекте использующем windows cryptoapi вот такое говно есть
      DWORD dwErr = 0;
      HCERTSTORE hStore = OpenStore();
      if(!hStore) {
      	return GetLastError();
      }
      
      PCERT_CONTEXT pCert = GetCert();
      if(!pCert) {
      	dwErr = GetLastError();
      	CloseStore(hStore);
      	return dwErr;
      }
      
      HKEY hKey = GetKey();
      if(!hKey) {
      	dwErr = GetLastError();
      	DestroyCertContext(pCert);
      	CloseStore(hStore);
      	return dwErr;
      }
      
      HHASH hHash = CreateHash();
      if(!hHash) {
      	dwErr = GetLastError();
      	DestroyKey(hKey);
      	DestroyCertContext(pCert);
      	CloseStore(hStore);
      	return dwErr;
      }
      
      BOOL ret = HashData();
      if(!ret) {
      	dwErr = GetLastError();
      	DestroyHash(hHash);
      	DestroyKey(hKey);
      	DestroyCertContext(pCert);
      	CloseStore(hStore);
      	return dwErr;	
      }
      Ответить
      • всему виной отсутствие в примерах на мсдн best practices, так сказать
        чтобы человек изначально приучался к хорошему и понятному
        там вечно какой-то пиздей творится
        Ответить
        • ну тут разве что обернуть в
          do {
            if(...) break;
            ...
            if(...) break;
          } while(false);

          а потом дескрипторы освобождать
          if(hSmth) {
            DestroySmth(hSmth);
          }

          ничего лучше я не видел
          Ответить
          • Ну вместо этой хуйни с do { ... } while (false) лучше поюзать goto.

            Я вот так делал:
            1) сначала в переменные ложим NULL/INVALID_HANDLE_VALUE.
            2) goto cleanup при любой ошибке
            3) На cleanup: проверяем переменные на пустоту и вызываем соотв. функции для освобождения
            Ответить
            • применяю do { ... } while (0);
              Ответить
              • [холивар]С goto, имхо, наглядней ;) И лишний отступ не нужен.[/холивар]
                Ответить
                • xkcd292.png
                  Ответить
                  • Ну к данному случаяю это не относится ;)
                    Тут этот самый do { ... } while (false) с бряками, имхо, ничуть не структурней чем одинокая метка и прыжки вперед.
                    Ответить
                    • Вообще, согласен, но многие просто панически боятся goto
                      Ответить
                      • Ну я его совсем не боюсь (после бейсика то ;), но никогда не юзаю кроме трех случаев:
                        1) эмуляция try ... finally
                        2) бряк из 2-3 вложенных циклов (все лучше чем флагоёбство)
                        3) хардкорный конченный автомат (читается легче чем свич и переменная со стейтом)
                        Ответить
                        • >>после бейсика то
                          Барсик закаляет
                          1391 DO SHIT
                          16450 DO ANOTHER SHIT
                          451 PRINT SHIT4
                          56 INPUT SHIT1
                          633 GOTO 5132
                          REM SHIT
                          Ответить
                          • Да-да. Именно такой. Не богомерзкий структурный визуалбейсик, а истинный бейсик с православными номерами строк.

                            А еще можно было писать GOTO N*10 + 100 ;)
                            Ответить
                            • На Спектруме меня всегда раздражало, что нужно было постоянно придумывать номера строк. На 386-х был турбобейсик, вот там было раздолье.
                              Ответить
                              • а что там думать? 10, 20, 30 и т.д.
                                Ответить
                                • А потом нужно вставить десять строк между уже существующими.
                                  Ответить
                                  • > А потом нужно вставить десять строк между уже существующими.
                                    Ну, как вариант, можно превратить код в вермишель, засунув туда GOTO на свободное место ;)

                                    Или подвинуть пару соседних команд чуть подальше:
                                    Было:
                                    10 PRINT A$
                                    20 PRINT B$
                                    30 PRINT C$
                                    Стало:
                                    10 PRINT A$
                                    11 начало 10 строчного блока
                                    12 ...
                                    20 конец 10 строчного блока
                                    29 PRINT $B
                                    30 PRINT $C
                                    Как видим - пришлось поменять номер только в одной строке.
                                    Ответить
                                  • на практике такого почти никогда не надо было
                                    Ответить
                                    • Мне пару раз таки было, но потом я научился проектированию.
                                      Ответить
                              • На спекки не было GOSUB?
                                Ответить
                                • было
                                  Ответить
                                • Было всё всегда, только городить процедуру там, где нужно раздвинуть - слегка так перебор.
                                  Ответить
                • кстати про отступ
                  с точки зрения говноэмуляции try {} визуальная вложенность кода в некий блок, за которым угадывается специфичный do {} while (0); неплохо намекает само по себе
                  а вот goto cleanup; такого профита не имеет
                  Ответить
                  • А в goto cleanup получается визуальный барьер между исполнением и очисткой - метка cleanup, сдвинутая чуть левее, чем остальной код:
                    int shit() {
                        ...
                        if (!SomeMicrosoftShit(param, param, param)) {
                            result = SHIT_HAPPENED;
                            log_error("Shit happens");
                            goto cleanup;
                        }
                        ...
                    
                    cleanup:
                        if (foo)
                            delete foo;
                        if (bar != INVALID_HANDLE_VALUE)
                            CloseHandle(bar);
                        return result;
                    }
                    Ответить
                    • > if (foo)
                      > delete foo;
                      Ну здрасти.
                      delete foo; хватит всем достаточно
                      Ответить
                      • > if (foo) delete foo;
                        Круто я слился ;) Хотел написать освобождение какого-нибудь сишного ресурса, а написал бессмысленное и беспощадное крестоблядство. Вот к чему приводит спешка.
                        Ответить
                        • во free тоже можно нули передавать
                          Ответить
                          • Я знаю. В мыслях была какая-то функция, которая NULL не переварит, но написал то что написал ;) Собственно поэтому и написал чуть выше - сишного ресурса, а не памяти. Файл какой-нибудь например... Или сессию СУБД.
                            Ответить
                      • > Ну здрасти
                        все мы не без греха, да, LispGovno? :)
                        http://ideone.com/dhg9nz
                        Ответить
                        • А чего оно так себя ведет? Не ленивые && в си?
                          Ответить
                          • SelfAnswer: Приоритет оператора запятая ниже &&
                            Ответить
                          • операции запятая насрать на результат левых операндов, поэтому выполняются все init и инкремент для успешных
                            Ответить
                      • Лишь бы никому такого не попалось. Никогда.
                        http://ideone.com/h6S0k0
                        Ответить
                        • Хуйню написал, делит по стандарту не должен кидать исключения.
                          Ответить
          • Да, типичный msdn-example-style. Лучше дескрипторы проинициализировать в заведомо невалидное значение, а освобождать скопом, игнорируя статусы.
            Ответить
    • #include <stdio.h>
      #include <stdbool.h>
      bool init1(void){return true;}init2, init3;
      int main(void) {
              return 0;
      }

      http://ideone.com/5vHOqv
      Чё это посоны?
      Ответить
    • монументально. и при этом это есть самая короткая реализация (которую я видел) пенетрации виндозного эксплорера.
      Ответить
    • показать все, что скрытоvanished
      Ответить
    • vanished
      Ответить

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