TSRM_API int tsrm_win32_access(const char *pathname, int mode) { time_t t; HANDLE thread_token = NULL; PSID token_sid; SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; GENERIC_MAPPING gen_map = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS }; DWORD priv_set_length = sizeof(PRIVILEGE_SET); PRIVILEGE_SET privilege_set = {0}; DWORD sec_desc_length = 0, desired_access = 0, granted_access = 0; BYTE * psec_desc = NULL; BOOL fAccess = FALSE; realpath_cache_bucket * bucket = NULL; char * real_path = NULL; PHP_WIN32_IOUTIL_INIT_W(pathname) if (!pathw) { return -1; } if (mode == 1 /*X_OK*/) { DWORD type; int ret; ret = GetBinaryTypeW(pathw, &type) ? 0 : -1; PHP_WIN32_IOUTIL_CLEANUP_W() return ret; } else {
/* * @implemented */ BOOL WINAPI GetBinaryTypeA(IN LPCSTR lpApplicationName, OUT LPDWORD lpBinaryType) { ANSI_STRING ApplicationNameString; UNICODE_STRING ApplicationNameW; BOOL StringAllocated = FALSE, Result; NTSTATUS Status; RtlInitAnsiString(&ApplicationNameString, lpApplicationName); if (ApplicationNameString.Length * sizeof(WCHAR) >= NtCurrentTeb()->StaticUnicodeString.MaximumLength) { StringAllocated = TRUE; Status = RtlAnsiStringToUnicodeString(&ApplicationNameW, &ApplicationNameString, TRUE); } else { Status = RtlAnsiStringToUnicodeString(&(NtCurrentTeb()->StaticUnicodeString), &ApplicationNameString, FALSE); } if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return FALSE; } if (StringAllocated) { Result = GetBinaryTypeW(ApplicationNameW.Buffer, lpBinaryType); RtlFreeUnicodeString(&ApplicationNameW); } else { Result = GetBinaryTypeW(NtCurrentTeb()->StaticUnicodeString.Buffer, lpBinaryType); } return Result; }
static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process) { PROCESS_INFORMATION pi; STARTUPINFOW si; LPWSTR path = NULL; DWORD size; BOOL r; service_lock_exclusive(service_entry); if (!env) { HANDLE htok; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok)) CreateEnvironmentBlock(&env, htok, FALSE); if (!env) WINE_ERR("failed to create services environment\n"); } size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,NULL,0); path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR)); if (!path) { service_unlock(service_entry); return ERROR_NOT_ENOUGH_SERVER_MEMORY; } ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,path,size); if (service_entry->config.dwServiceType == SERVICE_KERNEL_DRIVER) { static const WCHAR winedeviceW[] = {'\\','w','i','n','e','d','e','v','i','c','e','.','e','x','e',' ',0}; WCHAR system_dir[MAX_PATH]; DWORD type, len; GetSystemDirectoryW( system_dir, MAX_PATH ); if (is_win64) { if (!GetBinaryTypeW( path, &type )) { HeapFree( GetProcessHeap(), 0, path ); service_unlock(service_entry); return GetLastError(); } if (type == SCS_32BIT_BINARY) GetSystemWow64DirectoryW( system_dir, MAX_PATH ); } len = strlenW( system_dir ) + sizeof(winedeviceW)/sizeof(WCHAR) + strlenW(service_entry->name); HeapFree( GetProcessHeap(), 0, path ); if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) { service_unlock(service_entry); return ERROR_NOT_ENOUGH_SERVER_MEMORY; } lstrcpyW( path, system_dir ); lstrcatW( path, winedeviceW ); lstrcatW( path, service_entry->name ); } ZeroMemory(&si, sizeof(STARTUPINFOW)); si.cb = sizeof(STARTUPINFOW); if (!(service_entry->config.dwServiceType & SERVICE_INTERACTIVE_PROCESS)) { static WCHAR desktopW[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n','\\','D','e','f','a','u','l','t',0}; si.lpDesktop = desktopW; } service_entry->status.dwCurrentState = SERVICE_START_PENDING; service_unlock(service_entry); r = CreateProcessW(NULL, path, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, env, NULL, &si, &pi); HeapFree(GetProcessHeap(),0,path); if (!r) { service_lock_exclusive(service_entry); service_entry->status.dwCurrentState = SERVICE_STOPPED; service_unlock(service_entry); return GetLastError(); } service_entry->status.dwProcessId = pi.dwProcessId; service_entry->process = pi.hProcess; *process = pi.hProcess; CloseHandle( pi.hThread ); return ERROR_SUCCESS; }
} QTCREATOR_UTILS_EXPORT bool winIs64BitSystem() { SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); return systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64; } QTCREATOR_UTILS_EXPORT bool winIs64BitBinary(const QString &binaryIn) { QTC_ASSERT(!binaryIn.isEmpty(), return false); #ifdef Q_OS_WIN32 # ifdef __GNUC__ // MinGW lacking some definitions/winbase.h # define SCS_64BIT_BINARY 6 # endif bool isAmd64 = false; DWORD binaryType = 0; const QString binary = QDir::toNativeSeparators(binaryIn); bool success = GetBinaryTypeW(reinterpret_cast<const TCHAR*>(binary.utf16()), &binaryType) != 0; if (success && binaryType == SCS_64BIT_BINARY) isAmd64=true; return isAmd64; #else return false; #endif } } // namespace Utils
static DWORD shgfi_get_exe_type(LPCWSTR szFullPath) { BOOL status = FALSE; HANDLE hfile; DWORD BinaryType; IMAGE_DOS_HEADER mz_header; IMAGE_NT_HEADERS nt; DWORD len; char magic[4]; status = GetBinaryTypeW (szFullPath, &BinaryType); if (!status) return 0; if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY) return 0x4d5a; hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if ( hfile == INVALID_HANDLE_VALUE ) return 0; /* * The next section is adapted from MODULE_GetBinaryType, as we need * to examine the image header to get OS and version information. We * know from calling GetBinaryTypeA that the image is valid and either * an NE or PE, so much error handling can be omitted. * Seek to the start of the file and read the header information. */ SetFilePointer( hfile, 0, NULL, SEEK_SET ); ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL ); SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); ReadFile( hfile, magic, sizeof(magic), &len, NULL ); if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE ) { SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); ReadFile( hfile, &nt, sizeof(nt), &len, NULL ); CloseHandle( hfile ); /* DLL files are not executable and should return 0 */ if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL) return 0; if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { return IMAGE_NT_SIGNATURE | (nt.OptionalHeader.MajorSubsystemVersion << 24) | (nt.OptionalHeader.MinorSubsystemVersion << 16); } return IMAGE_NT_SIGNATURE; } else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE ) { IMAGE_OS2_HEADER ne; SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); ReadFile( hfile, &ne, sizeof(ne), &len, NULL ); CloseHandle( hfile ); if (ne.ne_exetyp == 2) return IMAGE_OS2_SIGNATURE | (ne.ne_expver << 16); return 0; } CloseHandle( hfile ); return 0; }
static void locate_pythons_for_key(HKEY root, REGSAM flags) { HKEY core_root, ip_key; LSTATUS status = RegOpenKeyExW(root, CORE_PATH, 0, flags, &core_root); wchar_t message[MSGSIZE]; DWORD i; size_t n; BOOL ok; DWORD type, data_size, attrs; INSTALLED_PYTHON * ip, * pip; wchar_t ip_version[IP_VERSION_SIZE]; wchar_t ip_path[IP_SIZE]; wchar_t * check; wchar_t ** checkp; wchar_t *key_name = (root == HKEY_LOCAL_MACHINE) ? L"HKLM" : L"HKCU"; if (status != ERROR_SUCCESS) debug(L"locate_pythons_for_key: unable to open PythonCore key in %ls\n", key_name); else { ip = &installed_pythons[num_installed_pythons]; for (i = 0; num_installed_pythons < MAX_INSTALLED_PYTHONS; i++) { status = RegEnumKeyW(core_root, i, ip_version, IP_VERSION_SIZE); if (status != ERROR_SUCCESS) { if (status != ERROR_NO_MORE_ITEMS) { /* unexpected error */ winerror(status, message, MSGSIZE); debug(L"Can't enumerate registry key for version %ls: %ls\n", ip_version, message); } break; } else { wcsncpy_s(ip->version, MAX_VERSION_SIZE, ip_version, MAX_VERSION_SIZE-1); _snwprintf_s(ip_path, IP_SIZE, _TRUNCATE, L"%ls\\%ls\\InstallPath", CORE_PATH, ip_version); status = RegOpenKeyExW(root, ip_path, 0, flags, &ip_key); if (status != ERROR_SUCCESS) { winerror(status, message, MSGSIZE); // Note: 'message' already has a trailing \n debug(L"%ls\\%ls: %ls", key_name, ip_path, message); continue; } data_size = sizeof(ip->executable) - 1; status = RegQueryValueExW(ip_key, NULL, NULL, &type, (LPBYTE)ip->executable, &data_size); RegCloseKey(ip_key); if (status != ERROR_SUCCESS) { winerror(status, message, MSGSIZE); debug(L"%ls\\%ls: %ls\n", key_name, ip_path, message); continue; } if (type == REG_SZ) { data_size = data_size / sizeof(wchar_t) - 1; /* for NUL */ if (ip->executable[data_size - 1] == L'\\') --data_size; /* reg value ended in a backslash */ /* ip->executable is data_size long */ for (checkp = location_checks; *checkp; ++checkp) { check = *checkp; _snwprintf_s(&ip->executable[data_size], MAX_PATH - data_size, MAX_PATH - data_size, L"%ls%ls", check, PYTHON_EXECUTABLE); attrs = GetFileAttributesW(ip->executable); if (attrs == INVALID_FILE_ATTRIBUTES) { winerror(GetLastError(), message, MSGSIZE); debug(L"locate_pythons_for_key: %ls: %ls", ip->executable, message); } else if (attrs & FILE_ATTRIBUTE_DIRECTORY) { debug(L"locate_pythons_for_key: '%ls' is a \ directory\n", ip->executable, attrs); } else if (find_existing_python(ip->executable)) { debug(L"locate_pythons_for_key: %ls: already \ found\n", ip->executable); } else { /* check the executable type. */ ok = GetBinaryTypeW(ip->executable, &attrs); if (!ok) { debug(L"Failure getting binary type: %ls\n", ip->executable); } else { if (attrs == SCS_64BIT_BINARY) ip->bits = 64; else if (attrs == SCS_32BIT_BINARY) ip->bits = 32; else ip->bits = 0; if (ip->bits == 0) { debug(L"locate_pythons_for_key: %ls: \ invalid binary type: %X\n", ip->executable, attrs); } else { if (wcschr(ip->executable, L' ') != NULL) { /* has spaces, so quote */ n = wcslen(ip->executable); memmove(&ip->executable[1], ip->executable, n * sizeof(wchar_t)); ip->executable[0] = L'\"'; ip->executable[n + 1] = L'\"'; ip->executable[n + 2] = L'\0'; } debug(L"locate_pythons_for_key: %ls \ is a %dbit executable\n", ip->executable, ip->bits); ++num_installed_pythons; pip = ip++; if (num_installed_pythons >= MAX_INSTALLED_PYTHONS) break; /* Copy over the attributes for the next */ *ip = *pip; } } } }
int wmain (int argc, WCHAR *argv[]) { SHELLEXECUTEINFOW sei; WCHAR *args = NULL; int i; int unix_mode = 0; int progid_open = 0; WCHAR *dos_filename = NULL; WCHAR *parent_directory = NULL; DWORD binary_type; static const WCHAR openW[] = { 'o', 'p', 'e', 'n', 0 }; static const WCHAR unixW[] = { 'u', 'n', 'i', 'x', 0 }; static const WCHAR progIDOpenW[] = { 'p', 'r', 'o', 'g', 'I', 'D', 'O', 'p', 'e', 'n', 0}; memset(&sei, 0, sizeof(sei)); sei.cbSize = sizeof(sei); sei.lpVerb = openW; sei.nShow = SW_SHOWNORMAL; /* Dunno what these mean, but it looks like winMe's start uses them */ sei.fMask = SEE_MASK_FLAG_DDEWAIT| SEE_MASK_FLAG_NO_UI| SEE_MASK_NO_CONSOLE; /* Canonical Microsoft commandline flag processing: * flags start with /, are case insensitive, * and may be run together in same word. */ for (i=1; i<argc; i++) { int ci; if (argv[i][0] != '/') break; /* Unix paths can start with / so we have to assume anything following /U is not a flag */ if (unix_mode || progid_open) break; /* Handle all options in this word */ for (ci=0; argv[i][ci]; ) { /* Skip slash */ ci++; switch(argv[i][ci]) { case 'b': case 'B': break; /* FIXME: should stop new window from being created */ case 'i': case 'I': break; /* FIXME: should ignore any changes to current environment */ case 'l': case 'L': license(); break; /* notreached */ case 'm': case 'M': if (argv[i][ci+1] == 'a' || argv[i][ci+1] == 'A') sei.nShow = SW_SHOWMAXIMIZED; else sei.nShow = SW_SHOWMINIMIZED; break; case 'r': case 'R': /* sei.nShow = SW_SHOWNORMAL; */ break; case 'u': case 'U': if (strncmpiW(&argv[i][ci], unixW, 4) == 0) unix_mode = 1; else { WINE_ERR("Option '%s' not recognized\n", wine_dbgstr_w( argv[i]+ci-1)); usage(); } break; case 'p': case 'P': if (strncmpiW(&argv[i][ci], progIDOpenW, 17) == 0) progid_open = 1; else { WINE_ERR("Option '%s' not recognized\n", wine_dbgstr_w( argv[i]+ci-1)); usage(); } break; case 'w': case 'W': sei.fMask |= SEE_MASK_NOCLOSEPROCESS; break; default: WINE_ERR("Option '%s' not recognized\n", wine_dbgstr_w( argv[i]+ci-1)); usage(); } /* Skip to next slash */ while (argv[i][ci] && (argv[i][ci] != '/')) ci++; } } if (i == argc) usage(); if (progid_open) { sei.lpClass = argv[i++]; sei.fMask |= SEE_MASK_CLASSNAME; } sei.lpFile = argv[i++]; args = build_args( argc - i, &argv[i] ); sei.lpParameters = args; if (unix_mode || progid_open) { LPWSTR (*CDECL wine_get_dos_file_name_ptr)(LPCSTR); char* multibyte_unixpath; int multibyte_unixpath_len; wine_get_dos_file_name_ptr = (void*)GetProcAddress(GetModuleHandleA("KERNEL32"), "wine_get_dos_file_name"); if (!wine_get_dos_file_name_ptr) fatal_string(STRING_UNIXFAIL); multibyte_unixpath_len = WideCharToMultiByte(CP_UNIXCP, 0, sei.lpFile, -1, NULL, 0, NULL, NULL); multibyte_unixpath = HeapAlloc(GetProcessHeap(), 0, multibyte_unixpath_len); WideCharToMultiByte(CP_UNIXCP, 0, sei.lpFile, -1, multibyte_unixpath, multibyte_unixpath_len, NULL, NULL); dos_filename = wine_get_dos_file_name_ptr(multibyte_unixpath); HeapFree(GetProcessHeap(), 0, multibyte_unixpath); if (!dos_filename) fatal_string(STRING_UNIXFAIL); sei.lpFile = dos_filename; sei.lpDirectory = parent_directory = get_parent_dir(dos_filename); sei.fMask &= ~SEE_MASK_FLAG_NO_UI; if (GetBinaryTypeW(sei.lpFile, &binary_type)) { WCHAR *commandline; STARTUPINFOW startup_info; PROCESS_INFORMATION process_information; static WCHAR commandlineformat[] = {'"','%','s','"','%','s',0}; /* explorer on windows always quotes the filename when running a binary on windows (see bug 5224) so we have to use CreateProcessW in this case */ commandline = HeapAlloc(GetProcessHeap(), 0, (strlenW(sei.lpFile)+3+strlenW(sei.lpParameters))*sizeof(WCHAR)); sprintfW(commandline, commandlineformat, sei.lpFile, sei.lpParameters); ZeroMemory(&startup_info, sizeof(startup_info)); startup_info.cb = sizeof(startup_info); if (!CreateProcessW( NULL, /* lpApplicationName */ commandline, /* lpCommandLine */ NULL, /* lpProcessAttributes */ NULL, /* lpThreadAttributes */ FALSE, /* bInheritHandles */ CREATE_NEW_CONSOLE, /* dwCreationFlags */ NULL, /* lpEnvironment */ sei.lpDirectory, /* lpCurrentDirectory */ &startup_info, /* lpStartupInfo */ &process_information /* lpProcessInformation */ )) { fatal_string_error(STRING_EXECFAIL, GetLastError(), sei.lpFile); } sei.hProcess = process_information.hProcess; goto done; } } if (!ShellExecuteExW(&sei)) fatal_string_error(STRING_EXECFAIL, GetLastError(), sei.lpFile); done: HeapFree( GetProcessHeap(), 0, args ); HeapFree( GetProcessHeap(), 0, dos_filename ); HeapFree( GetProcessHeap(), 0, parent_directory ); if (sei.fMask & SEE_MASK_NOCLOSEPROCESS) { DWORD exitcode; WaitForSingleObject(sei.hProcess, INFINITE); GetExitCodeProcess(sei.hProcess, &exitcode); ExitProcess(exitcode); } ExitProcess(0); }
static BOOL AutoStartupApplications(INT nCSIDL_Folder) { WCHAR szPath[MAX_PATH] = { 0 }; HRESULT hResult; HANDLE hFind; WIN32_FIND_DATAW FoundData; size_t cchPathLen; TRACE("(%d)\n", nCSIDL_Folder); // Get the special folder path hResult = SHGetFolderPathW(NULL, nCSIDL_Folder, NULL, SHGFP_TYPE_CURRENT, szPath); cchPathLen = wcslen(szPath); if (!SUCCEEDED(hResult) || cchPathLen == 0) { WARN("SHGetFolderPath() failed with error %lu\n", GetLastError()); return FALSE; } // Build a path with wildcard StringCbCatW(szPath, sizeof(szPath), L"\\*"); // Start enumeration of files hFind = FindFirstFileW(szPath, &FoundData); if (hFind == INVALID_HANDLE_VALUE) { WARN("FindFirstFile(%s) failed with error %lu\n", debugstr_w(szPath), GetLastError()); return FALSE; } // Enumerate the files do { // Ignore "." and ".." if (wcscmp(FoundData.cFileName, L".") == 0 || wcscmp(FoundData.cFileName, L"..") == 0) { continue; } // Don't run hidden files if (FoundData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) continue; // Build the path szPath[cchPathLen + 1] = UNICODE_NULL; StringCbCatW(szPath, sizeof(szPath), FoundData.cFileName); TRACE("Executing %s in directory %s\n", debugstr_w(FoundData.cFileName), debugstr_w(szPath)); DWORD dwType; if (GetBinaryTypeW(szPath, &dwType)) { runCmd(szPath, NULL, TRUE, FALSE); } else { SHELLEXECUTEINFOW ExecInfo; ZeroMemory(&ExecInfo, sizeof(ExecInfo)); ExecInfo.cbSize = sizeof(ExecInfo); ExecInfo.lpFile = szPath; ShellExecuteExW(&ExecInfo); } } while (FindNextFileW(hFind, &FoundData)); FindClose(hFind); return TRUE; }
// // Tries to call where.exe to find the location of dotnet.exe. // Will check that the bitness of dotnet matches the current // worker process bitness. // Returns true if a valid dotnet was found, else false.R // std::optional<fs::path> HOSTFXR_UTILITY::InvokeWhereToFindDotnet() { HRESULT hr = S_OK; // Arguments to call where.exe STARTUPINFOW startupInfo = { 0 }; PROCESS_INFORMATION processInformation = { 0 }; SECURITY_ATTRIBUTES securityAttributes; CHAR pzFileContents[READ_BUFFER_SIZE]; HandleWrapper<InvalidHandleTraits> hStdOutReadPipe; HandleWrapper<InvalidHandleTraits> hStdOutWritePipe; HandleWrapper<InvalidHandleTraits> hProcess; HandleWrapper<InvalidHandleTraits> hThread; CComBSTR pwzDotnetName = NULL; DWORD dwFilePointer; BOOL fIsWow64Process; BOOL fIsCurrentProcess64Bit; DWORD dwExitCode; STRU struDotnetSubstring; STRU struDotnetLocationsString; DWORD dwNumBytesRead; DWORD dwBinaryType; INT index = 0; INT prevIndex = 0; std::optional<fs::path> result; // Set the security attributes for the read/write pipe securityAttributes.nLength = sizeof(securityAttributes); securityAttributes.lpSecurityDescriptor = NULL; securityAttributes.bInheritHandle = TRUE; LOG_INFO(L"Invoking where.exe to find dotnet.exe"); // Create a read/write pipe that will be used for reading the result of where.exe FINISHED_LAST_ERROR_IF(!CreatePipe(&hStdOutReadPipe, &hStdOutWritePipe, &securityAttributes, 0)); FINISHED_LAST_ERROR_IF(!SetHandleInformation(hStdOutReadPipe, HANDLE_FLAG_INHERIT, 0)); // Set the stdout and err pipe to the write pipes. startupInfo.cb = sizeof(startupInfo); startupInfo.dwFlags |= STARTF_USESTDHANDLES; startupInfo.hStdOutput = hStdOutWritePipe; startupInfo.hStdError = hStdOutWritePipe; // CreateProcess requires a mutable string to be passed to commandline // See https://blogs.msdn.microsoft.com/oldnewthing/20090601-00/?p=18083/ pwzDotnetName = L"\"where.exe\" dotnet.exe"; // Create a process to invoke where.exe FINISHED_LAST_ERROR_IF(!CreateProcessW(NULL, pwzDotnetName, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &processInformation )); // Store handles into wrapper so they get closed automatically hProcess = processInformation.hProcess; hThread = processInformation.hThread; // Wait for where.exe to return WaitForSingleObject(processInformation.hProcess, INFINITE); // // where.exe will return 0 on success, 1 if the file is not found // and 2 if there was an error. Check if the exit code is 1 and set // a new hr result saying it couldn't find dotnet.exe // FINISHED_LAST_ERROR_IF (!GetExitCodeProcess(processInformation.hProcess, &dwExitCode)); // // In this block, if anything fails, we will goto our fallback of // looking in C:/Program Files/ // if (dwExitCode != 0) { FINISHED_IF_FAILED(E_FAIL); } // Where succeeded. // Reset file pointer to the beginning of the file. dwFilePointer = SetFilePointer(hStdOutReadPipe, 0, NULL, FILE_BEGIN); if (dwFilePointer == INVALID_SET_FILE_POINTER) { FINISHED_IF_FAILED(E_FAIL); } // // As the call to where.exe succeeded (dotnet.exe was found), ReadFile should not hang. // TODO consider putting ReadFile in a separate thread with a timeout to guarantee it doesn't block. // FINISHED_LAST_ERROR_IF (!ReadFile(hStdOutReadPipe, pzFileContents, READ_BUFFER_SIZE, &dwNumBytesRead, NULL)); if (dwNumBytesRead >= READ_BUFFER_SIZE) { // This shouldn't ever be this large. We could continue to call ReadFile in a loop, // however if someone had this many dotnet.exes on their machine. FINISHED_IF_FAILED(E_FAIL); } FINISHED_IF_FAILED(struDotnetLocationsString.CopyA(pzFileContents, dwNumBytesRead)); LOG_INFOF(L"where.exe invocation returned: '%ls'", struDotnetLocationsString.QueryStr()); // Check the bitness of the currently running process // matches the dotnet.exe found. FINISHED_LAST_ERROR_IF (!IsWow64Process(GetCurrentProcess(), &fIsWow64Process)); if (fIsWow64Process) { // 32 bit mode fIsCurrentProcess64Bit = FALSE; } else { // Check the SystemInfo to see if we are currently 32 or 64 bit. SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); fIsCurrentProcess64Bit = systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64; } LOG_INFOF(L"Current process bitness type detected as isX64=%d", fIsCurrentProcess64Bit); while (TRUE) { index = struDotnetLocationsString.IndexOf(L"\r\n", prevIndex); if (index == -1) { break; } FINISHED_IF_FAILED(struDotnetSubstring.Copy(&struDotnetLocationsString.QueryStr()[prevIndex], index - prevIndex)); // \r\n is two wchars, so add 2 here. prevIndex = index + 2; LOG_INFOF(L"Processing entry '%ls'", struDotnetSubstring.QueryStr()); if (LOG_LAST_ERROR_IF(!GetBinaryTypeW(struDotnetSubstring.QueryStr(), &dwBinaryType))) { continue; } LOG_INFOF(L"Binary type %d", dwBinaryType); if (fIsCurrentProcess64Bit == (dwBinaryType == SCS_64BIT_BINARY)) { // The bitness of dotnet matched with the current worker process bitness. return std::make_optional(struDotnetSubstring.QueryStr()); } } Finished: return result; }