static const wchar_t *GetLastCharactercW(const wchar_t *string) { if (!string || !*string) return string; return CharPrevW(string, string+lstrlenW(string)); }
static const wchar_t *scanstr_backW(const wchar_t *str, const wchar_t *toscan, const wchar_t *defval) { const wchar_t *s = GetLastCharactercW(str); if (!str[0]) return defval; if (!toscan || !toscan[0]) return defval; while (1) { const wchar_t *t = toscan; while (*t) { if (*t == *s) return s; t = CharNextW(t); } t = CharPrevW(str, s); if (t == s) return defval; s = t; } }
// 1つ目の引数だけファイルとして扱い、実行する。 // // コマンドは こんな感じで連結されます。 // exe linkpath linkarg cmdarg2 cmdarg3 cmdarg4 ... // static HRESULT HookAndExecute(int show) { int argc = 0; LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); if(!argv) { return HresultFromLastError(); } if(argc <= 1) { char buffer [256]; LoadStringA(GetModuleHandleA(NULL), IDS_USAGE, buffer, 256); MessageBoxA(NULL, buffer ,"gdi++", MB_OK|MB_ICONINFORMATION); LocalFree(argv); return S_OK; } int i; size_t length = 1; for(i=2; i<argc; i++) { length += wcslen(argv[i]) + 3; } LPWSTR cmdline = (WCHAR*)calloc(sizeof(WCHAR), length); if(!cmdline) { LocalFree(argv); return E_OUTOFMEMORY; } LPWSTR p = cmdline; *p = L'\0'; for(i=2; i<argc; i++) { const bool dq = !!wcschr(argv[i], L' '); if (dq) { *p++ = '"'; length--; } StringCchCopyExW(p, length, argv[i], &p, &length, STRSAFE_NO_TRUNCATION); if (dq) { *p++ = '"'; length--; } *p++ = L' '; length--; } *CharPrevW(cmdline, p) = L'\0'; WCHAR file[MAX_PATH], dir[MAX_PATH]; GetCurrentDirectoryW(_countof(dir), dir); StringCchCopyW(file, _countof(file), argv[1]); if(PathIsRelativeW(file)) { PathCombineW(file, dir, file); } else { WCHAR gdippDir[MAX_PATH]; GetModuleFileNameW(NULL, gdippDir, _countof(gdippDir)); PathRemoveFileSpec(gdippDir); // カレントディレクトリがgdi++.exeの置かれているディレクトリと同じだったら、 // 起動しようとしているEXEのフルパスから抜き出したディレクトリ名をカレント // ディレクトリとして起動する。(カレントディレクトリがEXEと同じ場所である // 前提で作られているアプリ対策) if (wcscmp(dir, gdippDir) == 0) { StringCchCopyW(dir, _countof(dir), argv[1]); PathRemoveFileSpec(dir); } } LocalFree(argv); argv = NULL; #ifdef _DEBUG if((GetAsyncKeyState(VK_CONTROL) & 0x8000) && MessageBoxW(NULL, cmdline, NULL, MB_YESNO) != IDYES) { free(cmdline); return NOERROR; } #endif LPITEMIDLIST pidl = NULL; HRESULT hr; //fileのアイテムIDリストを取得 hr = _SHILCreateFromPath(file, &pidl, NULL); if(SUCCEEDED(hr) && pidl) { //SEE_MASK_INVOKEIDLISTを使うと //explorerでクリックして起動したのと同じ動作になる SHELLEXECUTEINFOW sei = { sizeof(SHELLEXECUTEINFOW) }; sei.fMask = SEE_MASK_INVOKEIDLIST | SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_DOENVSUBST | SEE_MASK_WAITFORINPUTIDLE; sei.hwnd = GetDesktopWindow(); sei.lpParameters = cmdline; sei.lpDirectory = dir; sei.nShow = show; sei.lpIDList = pidl; //ShellExecuteExWが内部で呼び出すCreateProcessWをフックして //HookChildProcesses相当の処理を行う DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourAttach(&(PVOID&)ORIG_CreateProcessW, IMPL_CreateProcessW); hr = DetourTransactionCommit(); if(hr == NOERROR) { if(ShellExecuteExW(&sei)) { hr = S_OK; } else { hr = HresultFromLastError(); } } DetourTransactionBegin(); DetourUpdateThread(GetCurrentThread()); DetourDetach(&(PVOID&)ORIG_CreateProcessW, IMPL_CreateProcessW); DetourTransactionCommit(); } if(pidl) _SHFree(pidl); free(cmdline); return hr; }
const WChar * String::PrevCharW( const WChar * inStart, const WChar * inStr ) const { return CharPrevW( inStart, inStr ); }
static BOOL _CopyAndUnquoteText(LPCWSTR strFieldSource, LPWSTR strField, size_t cchField) { WCHAR cChar; PWSTR tmpField = strField; size_t lenField = 1; BOOL inQuote = FALSE; // Remove leading whitespace cChar = *strFieldSource; while (cChar == L' ' || cChar == L'\t' || cChar == L'\n' || cChar == L'\r') { strFieldSource = CharNextW(strFieldSource); cChar = *strFieldSource; } while (cChar && cChar != L'=' && cChar != L',') { if (cChar == L'"') { // [1] is always valid read because of null-termination if (inQuote && strFieldSource[1] == L'"') { if (lenField < cchField) { // Append *(tmpField++) = L'"'; ++lenField; } // Skip second quote strFieldSource++; } else { inQuote = !inQuote; } } else { if (inQuote || (cChar != L'=' && cChar != L',')) { if (lenField < cchField) { // Append *(tmpField++) = cChar; ++lenField; } } } strFieldSource = CharNextW(strFieldSource); cChar = *strFieldSource; } // Remove trailing whitespace while (tmpField > strField) { tmpField = CharPrevW(strField, tmpField); cChar = *tmpField; if (cChar != L' ' && cChar != L'\t' && cChar != L'\n' && cChar != L'\r') { tmpField = CharNextW(tmpField); break; } } // Terminate output string *tmpField = 0; return TRUE; }