wchar_t* GetShortFileNameEx(LPCWSTR asLong, BOOL abFavorLength/*=TRUE*/) { if (!asLong) return NULL; int nSrcLen = lstrlenW(asLong); //-V303 wchar_t* pszLong = lstrdup(asLong); int nMaxLen = nSrcLen + MAX_PATH; // "короткое" имя может более MAX_PATH wchar_t* pszShort = (wchar_t*)calloc(nMaxLen, sizeof(wchar_t)); //-V106 wchar_t* pszResult = NULL; wchar_t* pszSrc = pszLong; //wchar_t* pszDst = pszShort; wchar_t* pszSlash; wchar_t* szName = (wchar_t*)malloc((MAX_PATH+1)*sizeof(wchar_t)); bool lbNetwork = false; int nLen, nCurLen = 0; if (!pszLong || !pszShort || !szName) goto wrap; // Если путь сетевой (или UNC?) пропустить префиксы/серверы if (pszSrc[0] == L'\\' && pszSrc[1] == '\\') { // пропуск первых двух слешей pszSrc += 2; // формат "диска" не поддерживаем \\.\Drive\... if (pszSrc[0] == L'.' && pszSrc[1] == L'\\') goto wrap; // UNC if (pszSrc[0] == L'?' && pszSrc[1] == L'\\') { pszSrc += 2; if (pszSrc[0] == L'U' && pszSrc[1] == L'N' && pszSrc[2] == L'C' && pszSrc[3] == L'\\') { // UNC\Server\share\... pszSrc += 4; //-V112 lbNetwork = true; } // иначе - ожидается диск } // Network (\\Server\\Share\...) else { lbNetwork = true; } } if (pszSrc[0] == 0) goto wrap; if (lbNetwork) { pszSlash = wcschr(pszSrc, L'\\'); if (!pszSlash) goto wrap; pszSlash = wcschr(pszSlash+1, L'\\'); if (!pszSlash) goto wrap; pszShort[0] = L'\\'; pszShort[1] = L'\\'; pszShort[2] = 0; _wcscatn_c(pszShort, nMaxLen, pszSrc, (pszSlash-pszSrc+1)); // память выделяется calloc! //-V303 //-V104 } else { // <Drive>:\path... if (pszSrc[1] != L':') goto wrap; if (pszSrc[2] != L'\\' && pszSrc[2] != 0) goto wrap; pszSlash = pszSrc + 2; _wcscatn_c(pszShort, nMaxLen, pszSrc, (pszSlash-pszSrc+1)); // память выделяется calloc! } nCurLen = lstrlenW(pszShort); while (pszSlash && (*pszSlash == L'\\')) { pszSrc = pszSlash; pszSlash = wcschr(pszSrc+1, L'\\'); if (pszSlash) *pszSlash = 0; if (!GetShortFileName(pszLong, MAX_PATH+1, szName, abFavorLength)) goto wrap; nLen = lstrlenW(szName); if ((nLen + nCurLen) >= nMaxLen) goto wrap; //pszShort[nCurLen++] = L'\\'; pszShort[nCurLen] = 0; _wcscpyn_c(pszShort+nCurLen, nMaxLen-nCurLen, szName, nLen); nCurLen += nLen; if (pszSlash) { *pszSlash = L'\\'; pszShort[nCurLen++] = L'\\'; // память выделяется calloc! } } nLen = lstrlenW(pszShort); if ((nLen > 0) && (pszShort[nLen-1] == L'\\')) pszShort[--nLen] = 0; if (nLen <= MAX_PATH) { pszResult = pszShort; pszShort = NULL; goto wrap; } wrap: if (szName) free(szName); if (pszShort) free(pszShort); if (pszLong) free(pszLong); return pszResult; }
bool FindImageSubsystem(const wchar_t *Module, /*wchar_t* pstrDest,*/ DWORD& ImageSubsystem, DWORD& ImageBits, DWORD& FileAttrs) { if (!Module || !*Module) return false; bool Result = false; //ImageSubsystem = IMAGE_SUBSYSTEM_UNKNOWN; // Исключения нас не интересуют - команда уже сформирована и отдана в CreateProcess! //// нулевой проход - смотрим исключения //// Берем "исключения" из реестра, которые должны исполняться директом, //// например, некоторые внутренние команды ком. процессора. //string strExcludeCmds; //GetRegKey(strSystemExecutor,L"ExcludeCmds",strExcludeCmds,L""); //UserDefinedList ExcludeCmdsList; //ExcludeCmdsList.Set(strExcludeCmds); //while (!ExcludeCmdsList.IsEmpty()) //{ // if (!StrCmpI(Module,ExcludeCmdsList.GetNext())) // { // ImageSubsystem=IMAGE_SUBSYSTEM_WINDOWS_CUI; // Result=true; // break; // } //} //string strFullName=Module; LPCWSTR ModuleExt = PointToExt(Module); wchar_t *strPathExt/*[32767]*/ = NULL; //(L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); wchar_t *strPathEnv/*[32767]*/ = NULL; wchar_t *strExpand/*[32767]*/ = NULL; wchar_t *strTmpName/*[32767]*/ = NULL; wchar_t *pszFilePart = NULL; DWORD nPathExtLen = 0; LPCWSTR pszPathExtEnd = NULL; LPWSTR Ext = NULL; typedef LONG (WINAPI *RegOpenKeyExW_t)(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult); RegOpenKeyExW_t _RegOpenKeyEx = NULL; typedef LONG (WINAPI *RegQueryValueExW_t)(HKEY hKey, LPCTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); RegQueryValueExW_t _RegQueryValueEx = NULL; typedef LONG (WINAPI *RegCloseKey_t)(HKEY hKey); RegCloseKey_t _RegCloseKey = NULL; HMODULE hAdvApi = NULL; int cchstrPathExt = 32767; strPathExt = (wchar_t*)malloc(cchstrPathExt*sizeof(wchar_t)); *strPathExt = 0; int cchstrPathEnv = 32767; strPathEnv = (wchar_t*)malloc(cchstrPathEnv*sizeof(wchar_t)); *strPathEnv = 0; int cchstrExpand = 32767; strExpand = (wchar_t*)malloc(cchstrExpand*sizeof(wchar_t)); *strExpand = 0; int cchstrTmpName = 32767; strTmpName = (wchar_t*)malloc(cchstrTmpName*sizeof(wchar_t)); *strTmpName = 0; nPathExtLen = GetEnvironmentVariable(L"PATHEXT", strPathExt, cchstrPathExt-2); if (!nPathExtLen) { _wcscpy_c(strPathExt, cchstrPathExt, L".COM;.EXE;.BAT;.CMD;.VBS;.JS;.WSH"); nPathExtLen = lstrlen(strPathExt); } pszPathExtEnd = strPathExt+nPathExtLen; // Разбить на токены strPathExt[nPathExtLen] = strPathExt[nPathExtLen+1] = 0; Ext = wcschr(strPathExt, L';'); while (Ext) { *Ext = 0; Ext = wcschr(Ext+1, L';'); } TODO("Проверить на превышение длин строк"); // первый проход - в текущем каталоге LPWSTR pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; _wcscpyn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); //-V501 if (!ModuleExt) { if (!*Ext) continue; _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); } if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits/*16/32/64*/, FileAttrs)) { Result = true; goto wrap; } if (ModuleExt) { break; } } // второй проход - по правилам SearchPath // поиск по переменной PATH if (GetEnvironmentVariable(L"PATH", strPathEnv, cchstrPathEnv)) { LPWSTR pszPathEnvEnd = strPathEnv + lstrlen(strPathEnv); LPWSTR pszPathCur = strPathEnv; while (pszPathCur && (pszPathCur < pszPathEnvEnd)) { LPWSTR Path = pszPathCur; LPWSTR pszPathNext = wcschr(pszPathCur, L';'); if (pszPathNext) { *pszPathNext = 0; pszPathCur = pszPathNext+1; } else { pszPathCur = pszPathEnvEnd; } if (!*Path) continue; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(Path, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } } } pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; if (SearchPath(NULL, Module, Ext, cchstrTmpName, strTmpName, &pszFilePart)) { if (GetImageSubsystem(strTmpName, ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } // третий проход - лезем в реестр в "App Paths" if (!wcschr(Module, L'\\')) { hAdvApi = LoadLibrary(L"AdvApi32.dll"); if (!hAdvApi) goto wrap; _RegOpenKeyEx = (RegOpenKeyExW_t)GetProcAddress(hAdvApi, "RegOpenKeyExW"); _RegQueryValueEx = (RegQueryValueExW_t)GetProcAddress(hAdvApi, "RegQueryValueExW"); _RegCloseKey = (RegCloseKey_t)GetProcAddress(hAdvApi, "RegCloseKey"); if (!_RegOpenKeyEx || !_RegQueryValueEx || !_RegCloseKey) goto wrap; LPCWSTR RegPath = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\"; // В строке Module заменить исполняемый модуль на полный путь, который // берется из SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths // Сначала смотрим в HKCU, затем - в HKLM HKEY RootFindKey[] = {HKEY_CURRENT_USER,HKEY_LOCAL_MACHINE,HKEY_LOCAL_MACHINE}; BOOL lbAddExt = FALSE; pszExtCur = strPathExt; while (pszExtCur < pszPathExtEnd) { if (!lbAddExt) { Ext = NULL; lbAddExt = TRUE; } else { Ext = pszExtCur; pszExtCur = pszExtCur + lstrlen(pszExtCur)+1; if (!*Ext) continue; } _wcscpy_c(strTmpName, cchstrTmpName, RegPath); _wcscatn_c(strTmpName, cchstrTmpName, Module, cchstrTmpName); if (Ext) _wcscatn_c(strTmpName, cchstrTmpName, Ext, cchstrTmpName); DWORD samDesired = KEY_QUERY_VALUE; DWORD RedirectionFlag = 0; // App Paths key is shared in Windows 7 and above OSVERSIONINFO osv = {sizeof(OSVERSIONINFO)}; GetVersionEx(&osv); if (osv.dwMajorVersion < 6 || (osv.dwMajorVersion == 6 && osv.dwMinorVersion < 1)) { #ifdef _WIN64 RedirectionFlag = KEY_WOW64_32KEY; #else RedirectionFlag = IsWindows64() ? KEY_WOW64_64KEY : 0; #endif } for (size_t i = 0; i < countof(RootFindKey); i++) { if (i == (countof(RootFindKey)-1)) { if (RedirectionFlag) samDesired |= RedirectionFlag; else break; } HKEY hKey; if (_RegOpenKeyEx(RootFindKey[i], strTmpName, 0, samDesired, &hKey) == ERROR_SUCCESS) { DWORD nType = 0, nSize = sizeof(strTmpName)-2; int RegResult = _RegQueryValueEx(hKey, L"", NULL, &nType, (LPBYTE)strTmpName, &nSize); _RegCloseKey(hKey); if ((RegResult == ERROR_SUCCESS) && (nType == REG_SZ || nType == REG_EXPAND_SZ || nType == REG_MULTI_SZ)) { strTmpName[(nSize >> 1)+1] = 0; if (!ExpandEnvironmentStrings(strTmpName, strExpand, cchstrExpand)) _wcscpy_c(strExpand, cchstrExpand, strTmpName); if (GetImageSubsystem(Unquote(strExpand), ImageSubsystem, ImageBits, FileAttrs)) { Result = true; goto wrap; } } } }