bool IsRelativePath(const string &path) { if(path.empty()) return false; wstring wpath = StringFormat::UTF82Wide(path.c_str()); return PathIsRelativeW(wpath.c_str()) != 0; }
// converts a NT Path to a more familiar (and user mode friendly) path // we can pass to createfile std::wstring NTPathToDosPath(LPCWSTR ntPath) { std::wstring dosPath; static const WCHAR backSlash = L'\\'; dosPath.reserve(MAX_PATH); // if it's a relative path // add on the path to the drivers directory if(PathIsRelativeW(ntPath)) { static const WCHAR driverString[] = L"drivers/"; WCHAR buf[MAX_PATH] = {0}; GetSystemDirectory(buf, MAX_PATH - (ARRAYSIZE(driverString) + 1)); PathAppend(buf, driverString); dosPath = buf; dosPath += ntPath; } else { // otherwise check for various prefixes static const WCHAR* sysRoot = L"\\systemroot\\"; const std::wstring& windir = GetWindowsDirectoryString(); // find the first slash on the windir path const WCHAR* startOfWindirPath = PathSkipRoot(windir.c_str()) - 1; static const WCHAR* dosDevSymLink = L"\\??\\"; // lowercase the input string std::transform(ntPath, ntPath + wcslen(ntPath) + 1, std::back_inserter(dosPath), std::ptr_fun(towlower)); std::wstring::size_type pos = 0; // if the prefix is systemroot if((pos = dosPath.find(sysRoot)) != std::wstring::npos) { // replace the first and last slashes with percent signs dosPath[0] = dosPath[11] = L'%'; // add in a backslash after the last percent dosPath.insert(12, 1, backSlash); // expand the systemroot environment string std::vector<WCHAR> temp(ExpandEnvironmentStrings(dosPath.c_str(), NULL, 0)); ExpandEnvironmentStrings(dosPath.c_str(), &temp[0], temp.size()); temp.pop_back(); // remove the terminating NULL dosPath.assign(temp.begin(), temp.end()); } // if the prefix is the dos device symlink, just remove it else if((pos = dosPath.find(dosDevSymLink)) != std::wstring::npos) { dosPath.erase(0, 4); } // if the prefix is the start of the windows path // add on the drive else if((pos = dosPath.find(startOfWindirPath)) != std::wstring::npos) { // insert the drive and the colon dosPath.insert(0, windir, 0, 2); } // else leave it alone else __assume(0); } return dosPath; }
static VOID TestGetModuleFileNameW(VOID) { WCHAR Buffer[MAX_PATH]; DWORD Length; BOOL Relative; Length = GetModuleFileNameW(NULL, Buffer, sizeof(Buffer) / sizeof(WCHAR)); ok(Length != 0, "Length = %lu\n", Length); ok(Length < sizeof(Buffer) / sizeof(WCHAR), "Length = %lu\n", Length); ok(Buffer[Length] == 0, "Buffer not null terminated\n"); Relative = PathIsRelativeW(Buffer); ok(Relative == FALSE, "GetModuleFileNameW returned relative path: %ls\n", Buffer); }
void Cx_PluginLoader::MakeFullPath(wchar_t* fullpath, HMODULE instance, const wchar_t* path) { if (!path || 0 == path[0] || PathIsRelativeW(path)) { GetModuleFileNameW(instance, fullpath, MAX_PATH); PathRemoveFileSpecW(fullpath); PathAppendW(fullpath, path); } else { wcscpy_s(fullpath, MAX_PATH, path); } ReplaceSlashes(fullpath); PathAddBackslashW(fullpath); }
static HRESULT Folder_Constructor(VARIANT *dir, Folder **ppsdf) { FolderImpl *This; HRESULT ret; *ppsdf = NULL; switch (V_VT(dir)) { case VT_I4: /* FIXME: add some checks */ break; case VT_BSTR: if (PathIsDirectoryW(V_BSTR(dir)) && !PathIsRelativeW(V_BSTR(dir)) && PathFileExistsW(V_BSTR(dir))) break; default: return S_FALSE; } This = HeapAlloc(GetProcessHeap(), 0, sizeof(FolderImpl)); if (!This) return E_OUTOFMEMORY; This->Folder_iface.lpVtbl = &FolderImpl_Vtbl; This->ref = 1; ret = load_type_info(&IID_Folder3, &This->iTypeInfo); if (FAILED(ret)) { HeapFree(GetProcessHeap(), 0, This); return ret; } VariantInit(&This->dir); ret = VariantCopy(&This->dir, dir); if (FAILED(ret)) { ITypeInfo_Release(This->iTypeInfo); HeapFree(GetProcessHeap(), 0, This); return E_OUTOFMEMORY; } *ppsdf = (Folder*)This; return ret; }
/* * Class: com_kenai_jffi_Foreign * Method: dlopen * Signature: (Ljava/lang/String;I)J */ JNIEXPORT jlong JNICALL Java_com_kenai_jffi_Foreign_dlopen(JNIEnv* env, jobject self, jstring jPath, jint jFlags) { #ifdef _WIN32 if (jPath == NULL) { return p2j(GetModuleHandle(NULL)); } else { wchar_t path[PATH_MAX]; DWORD dwFlags; getWideString(env, path, jPath, sizeof(path) / sizeof(path[0])); dwFlags = PathIsRelativeW(path) ? 0 : LOAD_WITH_ALTERED_SEARCH_PATH; return p2j(LoadLibraryExW(path, NULL, dwFlags)); } #else char path_[PATH_MAX]; const char* path = NULL; // Handle dlopen(NULL, flags); void* handle = NULL; int flags = 0; #define F(x) (jFlags & com_kenai_jffi_Foreign_RTLD_##x) != 0 ? RTLD_##x : 0; flags |= F(LAZY); flags |= F(GLOBAL); flags |= F(LOCAL); flags |= F(NOW); #undef F #ifdef _AIX flags |= RTLD_MEMBER; // Needed for AIX #endif if (jPath != NULL) { path = path_; getMultibyteString(env, path_, jPath, sizeof(path_)); } handle = dl_open(path, flags); if (handle == NULL) { char errbuf[1024] = { 0 }; dl_error(errbuf, sizeof(errbuf) - 1); throwException(env, UnsatisfiedLink, "%s", errbuf); } return p2j(handle); #endif }
BOOL PathIsRelativeWrap(LPCWSTR pwzPath) { BOOL bRet = FALSE; ASSERT(pwzPath); if (pwzPath[0] == L'\\' || pwzPath[0] == L'/') { goto Exit; } if (PathIsURLW(pwzPath)) { goto Exit; } bRet = PathIsRelativeW(pwzPath); Exit: return bRet; }
errno_t mkdir(wchar_t const* path) { errno_t r = -1; size_t length; wchar_t const* src; wchar_t* dst; wchar_t* dir = NULL; if (PathIsRelativeW(path)) goto LABEL_ERROR; length = wcslen(path); if (length < 4) goto LABEL_ERROR; dir = malloc((length + 1) * sizeof(wchar_t)); if (dir == NULL) goto LABEL_ERROR; src = path; dst = dir; while (*src) { if (*src == L'\\' || *src == L'/') { if (*(src - 1) != L':') { CreateDirectoryW(dir, NULL); } } *dst++ = *src++; *dst = L'\0'; } CreateDirectoryW(dir, NULL); r = 0; LABEL_ERROR: if (dir) free(dir); return r; }
/* * Check workdir\fname is inside config_dir * The logic here is simple: we may reject some valid paths if ..\ is in any of the strings */ static BOOL CheckConfigPath(const WCHAR *workdir, const WCHAR *fname, const settings_t *s) { WCHAR tmp[MAX_PATH]; const WCHAR *config_file = NULL; const WCHAR *config_dir = NULL; /* convert fname to full path */ if (PathIsRelativeW(fname) ) { snwprintf(tmp, _countof(tmp), L"%s\\%s", workdir, fname); tmp[_countof(tmp)-1] = L'\0'; config_file = tmp; } else { config_file = fname; } #ifdef UNICODE config_dir = s->config_dir; #else if (MultiByteToWideChar(CP_UTF8, 0, s->config_dir, -1, widepath, MAX_PATH) == 0) { MsgToEventLog(M_SYSERR, TEXT("Failed to convert config_dir name to WideChar")); return FALSE; } config_dir = widepath; #endif if (wcsncmp(config_dir, config_file, wcslen(config_dir)) == 0 && wcsstr(config_file + wcslen(config_dir), L"..") == NULL) { return TRUE; } return FALSE; }
/************************************************************************* * SHGetFileInfoW [SHELL32.@] * */ DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags ) { WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH]; int iIndex; DWORD_PTR ret = TRUE; DWORD dwAttributes = 0; IShellFolder * psfParent = NULL; IExtractIconW * pei = NULL; LPITEMIDLIST pidlLast = NULL, pidl = NULL; HRESULT hr = S_OK; BOOL IconNotYetLoaded=TRUE; UINT uGilFlags = 0; HIMAGELIST big_icons, small_icons; TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n", (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags); if (!path) return FALSE; /* windows initializes these values regardless of the flags */ if (psfi != NULL) { psfi->szDisplayName[0] = '\0'; psfi->szTypeName[0] = '\0'; psfi->iIcon = 0; } if (!(flags & SHGFI_PIDL)) { /* SHGetFileInfo should work with absolute and relative paths */ if (PathIsRelativeW(path)) { GetCurrentDirectoryW(MAX_PATH, szLocation); PathCombineW(szFullPath, szLocation, path); } else { lstrcpynW(szFullPath, path, MAX_PATH); } } if (flags & SHGFI_EXETYPE) { if (flags != SHGFI_EXETYPE) return 0; return shgfi_get_exe_type(szFullPath); } /* * psfi is NULL normally to query EXE type. If it is NULL, none of the * below makes sense anyway. Windows allows this and just returns FALSE */ if (psfi == NULL) return FALSE; /* * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES * is not specified. * The pidl functions fail on not existing file names */ if (flags & SHGFI_PIDL) { pidl = ILClone((LPCITEMIDLIST)path); } else if (!(flags & SHGFI_USEFILEATTRIBUTES)) { hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes); } if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES)) { /* get the parent shellfolder */ if (pidl) { hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&pidlLast ); if (SUCCEEDED(hr)) pidlLast = ILClone(pidlLast); ILFree(pidl); } else { ERR("pidl is null!\n"); return FALSE; } } /* get the attributes of the child */ if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES)) { if (!(flags & SHGFI_ATTR_SPECIFIED)) { psfi->dwAttributes = 0xffffffff; } if (psfParent) IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast, &(psfi->dwAttributes) ); } /* get the displayname */ if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME)) { if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath)); } else { STRRET str; hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast, SHGDN_INFOLDER, &str); StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast); } } /* get the type name */ if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME)) { static const WCHAR szFile[] = { 'F','i','l','e',0 }; static const WCHAR szDashFile[] = { '-','f','i','l','e',0 }; if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL)) { char ftype[80]; _ILGetFileType(pidlLast, ftype, 80); MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 ); } else { if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) strcatW (psfi->szTypeName, szFile); else { WCHAR sTemp[64]; lstrcpyW(sTemp,PathFindExtensionW(szFullPath)); if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) && HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE ))) { lstrcpynW (psfi->szTypeName, sTemp, 64); strcatW (psfi->szTypeName, szDashFile); } } } } /* ### icons ###*/ Shell_GetImageLists( &big_icons, &small_icons ); if (flags & SHGFI_OPENICON) uGilFlags |= GIL_OPENICON; if (flags & SHGFI_LINKOVERLAY) uGilFlags |= GIL_FORSHORTCUT; else if ((flags&SHGFI_ADDOVERLAYS) || (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON) { if (SHELL_IsShortcut(pidlLast)) uGilFlags |= GIL_FORSHORTCUT; } if (flags & SHGFI_OVERLAYINDEX) FIXME("SHGFI_OVERLAYINDEX unhandled\n"); if (flags & SHGFI_SELECTED) FIXME("set icon to selected, stub\n"); if (flags & SHGFI_SHELLICONSIZE) FIXME("set icon to shell size, stub\n"); /* get the iconlocation */ if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) { UINT uDummy,uFlags; if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { lstrcpyW(psfi->szDisplayName, swShell32Name); psfi->iIcon = -IDI_SHELL_FOLDER; } else { WCHAR* szExt; static const WCHAR p1W[] = {'%','1',0}; WCHAR sTemp [MAX_PATH]; szExt = PathFindExtensionW(szFullPath); TRACE("szExt=%s\n", debugstr_w(szExt)); if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon)) { if (lstrcmpW(p1W, sTemp)) strcpyW(psfi->szDisplayName, sTemp); else { /* the icon is in the file */ strcpyW(psfi->szDisplayName, szFullPath); } } else ret = FALSE; } } else { hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW, &uDummy, (LPVOID*)&pei); if (SUCCEEDED(hr)) { hr = IExtractIconW_GetIconLocation(pei, uGilFlags, szLocation, MAX_PATH, &iIndex, &uFlags); if (uFlags & GIL_NOTFILENAME) ret = FALSE; else { lstrcpyW (psfi->szDisplayName, szLocation); psfi->iIcon = iIndex; } IExtractIconW_Release(pei); } } } /* get icon index (or load icon)*/ if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX))) { if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) { WCHAR sTemp [MAX_PATH]; WCHAR * szExt; int icon_idx=0; lstrcpynW(sTemp, szFullPath, MAX_PATH); if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0); else { static const WCHAR p1W[] = {'%','1',0}; psfi->iIcon = 0; szExt = PathFindExtensionW(sTemp); if ( szExt && HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx)) { if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */ strcpyW(sTemp, szFullPath); if (flags & SHGFI_SYSICONINDEX) { psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0); if (psfi->iIcon == -1) psfi->iIcon = 0; } else { UINT ret; if (flags & SHGFI_SMALLICON) ret = PrivateExtractIconsW( sTemp,icon_idx, GetSystemMetrics( SM_CXSMICON ), GetSystemMetrics( SM_CYSMICON ), &psfi->hIcon, 0, 1, 0); else ret = PrivateExtractIconsW( sTemp, icon_idx, GetSystemMetrics( SM_CXICON), GetSystemMetrics( SM_CYICON), &psfi->hIcon, 0, 1, 0); if (ret != 0 && ret != (UINT)-1) { IconNotYetLoaded=FALSE; psfi->iIcon = icon_idx; } } } } } else { if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), uGilFlags, &(psfi->iIcon)))) { ret = FALSE; } } if (ret && (flags & SHGFI_SYSICONINDEX)) { if (flags & SHGFI_SMALLICON) ret = (DWORD_PTR)small_icons; else ret = (DWORD_PTR)big_icons; } } /* icon handle */ if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded) { if (flags & SHGFI_SMALLICON) psfi->hIcon = ImageList_GetIcon( small_icons, psfi->iIcon, ILD_NORMAL); else psfi->hIcon = ImageList_GetIcon( big_icons, psfi->iIcon, ILD_NORMAL); } if (flags & ~SHGFI_KNOWN_FLAGS) FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS); if (psfParent) IShellFolder_Release(psfParent); if (hr != S_OK) ret = FALSE; SHFree(pidlLast); TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n", psfi->hIcon, psfi->iIcon, psfi->dwAttributes, debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret); return ret; }
// TODO: can we fail allocating memory? static VALUE fenix_file_expand_path(int argc, VALUE *argv) { size_t size = 0, wpath_len = 0, wdir_len = 0, whome_len = 0; size_t buffer_len = 0; char *fullpath = NULL; wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL, *wdir = NULL; wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL; UINT cp; VALUE result = Qnil, path = Qnil, dir = Qnil; wchar_t wfullpath_buffer[PATH_BUFFER_SIZE]; wchar_t path_drive = L'\0', dir_drive = L'\0'; int ignore_dir = 0; rb_encoding *path_encoding; int tainted = 0; // prepare for rb_file_absolute_path() int abs_mode = 0; // retrieve path and dir from argv rb_scan_args(argc, argv, "11", &path, &dir); /* tainted if path is tainted */ tainted = OBJ_TAINTED(path); // get path encoding if (NIL_P(dir)) { path_encoding = rb_enc_get(path); } else { path_encoding = rb_enc_check(path, dir); } cp = fenix_code_page(path_encoding); // printf("code page: %i\n", cp); // coerce them to string path = fenix_coerce_to_path(path); // convert char * to wchar_t // path fenix_path_to_wchar(path, &wpath, &wpath_pos, &wpath_len, cp); // wprintf(L"wpath: '%s' with (%i) characters long.\n", wpath, wpath_len); /* determine if we need the user's home directory */ /* expand '~' only if NOT rb_file_absolute_path() where `abs_mode` is 1 */ if (abs_mode == 0 && ((wpath_len == 1 && wpath_pos[0] == L'~') || (wpath_len >= 2 && wpath_pos[0] == L'~' && IS_DIR_SEPARATOR_P(wpath_pos[1])))) { /* tainted if expanding '~' */ tainted = 1; // wprintf(L"wpath requires expansion.\n"); whome = fenix_home_dir(); if (whome == NULL) { free(wpath); rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); } whome_len = wcslen(whome); if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) { free(wpath); rb_raise(rb_eArgError, "non-absolute home"); } // wprintf(L"whome: '%s' with (%i) characters long.\n", whome, whome_len); /* ignores dir since we are expading home */ ignore_dir = 1; /* exclude ~ from the result */ wpath_pos++; wpath_len--; /* exclude separator if present */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { // wprintf(L"excluding expansion character and separator\n"); wpath_pos++; wpath_len--; } } else if (wpath_len >= 2 && wpath_pos[1] == L':') { if (wpath_len >= 3 && IS_DIR_SEPARATOR_P(wpath_pos[2])) { /* ignore dir since path contains a drive letter and a root slash */ // wprintf(L"Ignore dir since we have drive letter and root slash\n"); ignore_dir = 1; } else { /* determine if we ignore dir or not later */ path_drive = wpath_pos[0]; } } else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') { wchar_t *wuser = wpath_pos + 1; wchar_t *pos = wuser; char *user; /* tainted if expanding '~' */ tainted = 1; while (!IS_DIR_SEPARATOR_P(*pos) && *pos != '\0') pos++; *pos = '\0'; size = WideCharToMultiByte(cp, 0, wuser, -1, NULL, 0, NULL, NULL); user = (char *)malloc(size * sizeof(char)); WideCharToMultiByte(cp, 0, wuser, -1, user, size, NULL, NULL); /* convert to VALUE and set the path encoding */ result = rb_enc_str_new(user, size - 1, path_encoding); free(wpath); if (user) free(user); rb_raise(rb_eArgError, "can't find user %s", StringValuePtr(result)); } /* convert dir */ if (!ignore_dir && !NIL_P(dir)) { // coerce them to string dir = fenix_coerce_to_path(dir); // convert char * to wchar_t // dir fenix_path_to_wchar(dir, &wdir, NULL, &wdir_len, cp); // wprintf(L"wdir: '%s' with (%i) characters long.\n", wdir, wdir_len); if (wdir_len >= 2 && wdir[1] == L':') { dir_drive = wdir[0]; if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { wdir_len = 2; } } else if (wdir_len >= 2 && IS_DIR_UNC_P(wdir)) { /* UNC path */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { /* cut the UNC path tail to '//host/share' */ size_t separators = 0; size_t pos = 2; while (pos < wdir_len && separators < 2) { if (IS_DIR_SEPARATOR_P(wdir[pos])) { separators++; } pos++; } if (separators == 2) wdir_len = pos - 1; // wprintf(L"UNC wdir: '%s' with (%i) characters.\n", wdir, wdir_len); } } } /* determine if we ignore dir or not */ if (!ignore_dir && path_drive && dir_drive) { if (towupper(path_drive) == towupper(dir_drive)) { /* exclude path drive letter to use dir */ // wprintf(L"excluding path drive letter\n"); wpath_pos += 2; wpath_len -= 2; } else { /* ignore dir since path drive is different from dir drive */ ignore_dir = 1; wdir_len = 0; } } if (!ignore_dir && wpath_len >= 2 && IS_DIR_UNC_P(wpath)) { /* ignore dir since path has UNC root */ ignore_dir = 1; wdir_len = 0; } else if (!ignore_dir && wpath_len >= 1 && IS_DIR_SEPARATOR_P(wpath[0]) && !dir_drive && !(wdir_len >= 2 && IS_DIR_UNC_P(wdir))) { /* ignore dir since path has root slash and dir doesn't have drive or UNC root */ ignore_dir = 1; wdir_len = 0; } // wprintf(L"wpath_len: %i\n", wpath_len); // wprintf(L"wdir_len: %i\n", wdir_len); // wprintf(L"whome_len: %i\n", whome_len); buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1; // wprintf(L"buffer_len: %i\n", buffer_len + 1); buffer = buffer_pos = (wchar_t *)malloc((buffer_len + 1) * sizeof(wchar_t)); /* add home */ if (whome_len) { // wprintf(L"Copying whome...\n"); wcsncpy(buffer_pos, whome, whome_len); buffer_pos += whome_len; } /* Add separator if required */ if (whome_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { // wprintf(L"Adding separator after whome\n"); buffer_pos[0] = L'\\'; buffer_pos++; } if (wdir_len) { /* tainted if dir is used and dir is tainted */ if (!tainted && OBJ_TAINTED(dir)) tainted = 1; // wprintf(L"Copying wdir...\n"); wcsncpy(buffer_pos, wdir, wdir_len); buffer_pos += wdir_len; } /* add separator if required */ if (wdir_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { // wprintf(L"Adding separator after wdir\n"); buffer_pos[0] = L'\\'; buffer_pos++; } /* now deal with path */ if (wpath_len) { // wprintf(L"Copying wpath...\n"); wcsncpy(buffer_pos, wpath_pos, wpath_len); buffer_pos += wpath_len; } /* GetFullPathNameW requires at least "." to determine current directory */ if (wpath_len == 0) { // wprintf(L"Adding '.' to buffer\n"); buffer_pos[0] = L'.'; buffer_pos++; } /* Ensure buffer is NULL terminated */ buffer_pos[0] = L'\0'; /* tainted if path is relative */ if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 && IS_DIR_UNC_P(buffer))) { tainted = 1; } // wprintf(L"buffer: '%s'\n", buffer); // FIXME: Make this more robust // Determine require buffer size size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL); if (size) { if (size > PATH_BUFFER_SIZE) { // allocate enough memory to contain the response wfullpath = (wchar_t *)malloc(size * sizeof(wchar_t)); size = GetFullPathNameW(buffer, size, wfullpath, NULL); } else { wfullpath = wfullpath_buffer; } // wprintf(L"wfullpath: '%s'\n", wfullpath); /* Calculate the new size and leave the garbage out */ // size = wcslen(wfullpath); /* Remove any trailing slashes */ if (IS_DIR_SEPARATOR_P(wfullpath[size - 1]) && wfullpath[size - 2] != L':' && !(size == 2 && IS_DIR_UNC_P(wfullpath))) { // wprintf(L"Removing trailing slash\n"); size -= 1; wfullpath[size] = L'\0'; } // wprintf(L"wfullpath: '%s'\n", wfullpath); /* Remove any trailing dot */ if (wfullpath[size - 1] == L'.') { // wprintf(L"Removing trailing dot\n"); size -= 1; wfullpath[size] = L'\0'; } /* removes trailing invalid ':$DATA' */ size = fenix_remove_invalid_alternative_data(wfullpath, size); // sanitize backslashes with forwardslashes fenix_replace_wchar(wfullpath, L'\\', L'/'); // wprintf(L"wfullpath: '%s'\n", wfullpath); // What CodePage should we use? // cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP; // convert to char * size = WideCharToMultiByte(cp, 0, wfullpath, -1, NULL, 0, NULL, NULL); fullpath = (char *)malloc(size * sizeof(char)); WideCharToMultiByte(cp, 0, wfullpath, -1, fullpath, size, NULL, NULL); /* convert to VALUE and set the path encoding */ result = rb_enc_str_new(fullpath, size - 1, path_encoding); /* makes the result object tainted if expanding tainted strings or returning modified path */ if (tainted) OBJ_TAINT(result); } // TODO: better cleanup if (buffer) free(buffer); if (wpath) free(wpath); if (wdir) free(wdir); if (whome) free(whome); if (wfullpath && wfullpath != wfullpath_buffer) free(wfullpath); if (fullpath) free(fullpath); return result; }
VALUE rb_file_expand_path_internal(VALUE fname, VALUE dname, int abs_mode, int long_name, VALUE result) { size_t size = 0, whome_len = 0; size_t buffer_len = 0; long wpath_len = 0, wdir_len = 0; char *fullpath = NULL; wchar_t *wfullpath = NULL, *wpath = NULL, *wpath_pos = NULL; wchar_t *wdir = NULL, *wdir_pos = NULL; wchar_t *whome = NULL, *buffer = NULL, *buffer_pos = NULL; UINT path_cp, cp; VALUE path = fname, dir = dname; wchar_t wfullpath_buffer[PATH_BUFFER_SIZE]; wchar_t path_drive = L'\0', dir_drive = L'\0'; int ignore_dir = 0; rb_encoding *path_encoding; int tainted = 0; /* tainted if path is tainted */ tainted = OBJ_TAINTED(path); /* get path encoding */ if (NIL_P(dir)) { path_encoding = rb_enc_get(path); } else { path_encoding = rb_enc_check(path, dir); } cp = path_cp = code_page(path_encoding); /* workaround invalid codepage */ if (path_cp == INVALID_CODE_PAGE) { cp = CP_UTF8; if (!NIL_P(path)) { path = fix_string_encoding(path, path_encoding); } } /* convert char * to wchar_t */ if (!NIL_P(path)) { wpath = mbstr_to_wstr(cp, RSTRING_PTR(path), (int)RSTRING_LEN(path), &wpath_len); wpath_pos = wpath; } /* determine if we need the user's home directory */ /* expand '~' only if NOT rb_file_absolute_path() where `abs_mode` is 1 */ if (abs_mode == 0 && wpath_len > 0 && wpath_pos[0] == L'~' && (wpath_len == 1 || IS_DIR_SEPARATOR_P(wpath_pos[1]))) { /* tainted if expanding '~' */ tainted = 1; whome = home_dir(); if (whome == NULL) { xfree(wpath); rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); } whome_len = wcslen(whome); if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) { xfree(wpath); xfree(whome); rb_raise(rb_eArgError, "non-absolute home"); } if (path_cp == INVALID_CODE_PAGE || rb_enc_str_asciionly_p(path)) { /* use filesystem encoding if expanding home dir */ path_encoding = rb_filesystem_encoding(); cp = path_cp = system_code_page(); } /* ignores dir since we are expanding home */ ignore_dir = 1; /* exclude ~ from the result */ wpath_pos++; wpath_len--; /* exclude separator if present */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { wpath_pos++; wpath_len--; } } else if (wpath_len >= 2 && wpath_pos[1] == L':') { if (wpath_len >= 3 && IS_DIR_SEPARATOR_P(wpath_pos[2])) { /* ignore dir since path contains a drive letter and a root slash */ ignore_dir = 1; } else { /* determine if we ignore dir or not later */ path_drive = wpath_pos[0]; wpath_pos += 2; wpath_len -= 2; } } else if (abs_mode == 0 && wpath_len >= 2 && wpath_pos[0] == L'~') { result = rb_str_new_cstr("can't find user "); result = append_wstr(result, wpath_pos + 1, user_length_in_path(wpath_pos + 1, wpath_len - 1), cp, path_cp, path_encoding); if (wpath) xfree(wpath); rb_exc_raise(rb_exc_new_str(rb_eArgError, result)); } /* convert dir */ if (!ignore_dir && !NIL_P(dir)) { /* fix string encoding */ if (path_cp == INVALID_CODE_PAGE) { dir = fix_string_encoding(dir, path_encoding); } /* convert char * to wchar_t */ if (!NIL_P(dir)) { wdir = mbstr_to_wstr(cp, RSTRING_PTR(dir), (int)RSTRING_LEN(dir), &wdir_len); wdir_pos = wdir; } if (abs_mode == 0 && wdir_len > 0 && wdir_pos[0] == L'~' && (wdir_len == 1 || IS_DIR_SEPARATOR_P(wdir_pos[1]))) { /* tainted if expanding '~' */ tainted = 1; whome = home_dir(); if (whome == NULL) { free(wpath); free(wdir); rb_raise(rb_eArgError, "couldn't find HOME environment -- expanding `~'"); } whome_len = wcslen(whome); if (PathIsRelativeW(whome) && !(whome_len >= 2 && IS_DIR_UNC_P(whome))) { free(wpath); free(wdir); xfree(whome); rb_raise(rb_eArgError, "non-absolute home"); } /* exclude ~ from the result */ wdir_pos++; wdir_len--; /* exclude separator if present */ if (wdir_len && IS_DIR_SEPARATOR_P(wdir_pos[0])) { wdir_pos++; wdir_len--; } } else if (wdir_len >= 2 && wdir[1] == L':') { dir_drive = wdir[0]; if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { wdir_len = 2; } } else if (wdir_len >= 2 && IS_DIR_UNC_P(wdir)) { /* UNC path */ if (wpath_len && IS_DIR_SEPARATOR_P(wpath_pos[0])) { /* cut the UNC path tail to '//host/share' */ long separators = 0; long pos = 2; while (pos < wdir_len && separators < 2) { if (IS_DIR_SEPARATOR_P(wdir[pos])) { separators++; } pos++; } if (separators == 2) wdir_len = pos - 1; } } else if (abs_mode == 0 && wdir_len >= 2 && wdir_pos[0] == L'~') { result = rb_str_new_cstr("can't find user "); result = append_wstr(result, wdir_pos + 1, user_length_in_path(wdir_pos + 1, wdir_len - 1), cp, path_cp, path_encoding); if (wpath) free(wpath); if (wdir) free(wdir); rb_exc_raise(rb_exc_new_str(rb_eArgError, result)); } } /* determine if we ignore dir or not */ if (!ignore_dir && path_drive && dir_drive) { if (towupper(path_drive) != towupper(dir_drive)) { /* ignore dir since path drive is different from dir drive */ ignore_dir = 1; wdir_len = 0; dir_drive = 0; } } if (!ignore_dir && wpath_len >= 2 && IS_DIR_UNC_P(wpath)) { /* ignore dir since path has UNC root */ ignore_dir = 1; wdir_len = 0; } else if (!ignore_dir && wpath_len >= 1 && IS_DIR_SEPARATOR_P(wpath[0]) && !dir_drive && !(wdir_len >= 2 && IS_DIR_UNC_P(wdir))) { /* ignore dir since path has root slash and dir doesn't have drive or UNC root */ ignore_dir = 1; wdir_len = 0; } buffer_len = wpath_len + 1 + wdir_len + 1 + whome_len + 1; buffer = buffer_pos = (wchar_t *)xmalloc((buffer_len + 1) * sizeof(wchar_t)); /* add home */ if (whome_len) { wcsncpy(buffer_pos, whome, whome_len); buffer_pos += whome_len; } /* Add separator if required */ if (whome_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { buffer_pos[0] = L'\\'; buffer_pos++; } else if (!dir_drive && path_drive) { *buffer_pos++ = path_drive; *buffer_pos++ = L':'; } if (wdir_len) { /* tainted if dir is used and dir is tainted */ if (!tainted && OBJ_TAINTED(dir)) tainted = 1; wcsncpy(buffer_pos, wdir_pos, wdir_len); buffer_pos += wdir_len; } /* add separator if required */ if (wdir_len && wcsrchr(L"\\/:", buffer_pos[-1]) == NULL) { buffer_pos[0] = L'\\'; buffer_pos++; } /* now deal with path */ if (wpath_len) { wcsncpy(buffer_pos, wpath_pos, wpath_len); buffer_pos += wpath_len; } /* GetFullPathNameW requires at least "." to determine current directory */ if (wpath_len == 0) { buffer_pos[0] = L'.'; buffer_pos++; } /* Ensure buffer is NULL terminated */ buffer_pos[0] = L'\0'; /* tainted if path is relative */ if (!tainted && PathIsRelativeW(buffer) && !(buffer_len >= 2 && IS_DIR_UNC_P(buffer))) tainted = 1; /* FIXME: Make this more robust */ /* Determine require buffer size */ size = GetFullPathNameW(buffer, PATH_BUFFER_SIZE, wfullpath_buffer, NULL); if (size > PATH_BUFFER_SIZE) { /* allocate more memory than alloted originally by PATH_BUFFER_SIZE */ wfullpath = (wchar_t *)xmalloc(size * sizeof(wchar_t)); size = GetFullPathNameW(buffer, size, wfullpath, NULL); } else { wfullpath = wfullpath_buffer; } /* Remove any trailing slashes */ if (IS_DIR_SEPARATOR_P(wfullpath[size - 1]) && wfullpath[size - 2] != L':' && !(size == 2 && IS_DIR_UNC_P(wfullpath))) { size -= 1; wfullpath[size] = L'\0'; } /* Remove any trailing dot */ if (wfullpath[size - 1] == L'.') { size -= 1; wfullpath[size] = L'\0'; } /* removes trailing invalid ':$DATA' */ size = remove_invalid_alternative_data(wfullpath, size); /* Replace the trailing path to long name */ if (long_name) size = replace_to_long_name(&wfullpath, size, (wfullpath != wfullpath_buffer)); /* sanitize backslashes with forwardslashes */ replace_wchar(wfullpath, L'\\', L'/'); /* convert to VALUE and set the path encoding */ rb_str_set_len(result, 0); result = append_wstr(result, wfullpath, size, cp, path_cp, path_encoding); /* makes the result object tainted if expanding tainted strings or returning modified path */ if (tainted) OBJ_TAINT(result); /* TODO: better cleanup */ if (buffer) xfree(buffer); if (wpath) free(wpath); if (wdir) free(wdir); if (whome) xfree(whome); if (wfullpath != wfullpath_buffer) xfree(wfullpath); if (fullpath) xfree(fullpath); rb_enc_associate(result, path_encoding); return result; }
// 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; }
/* 010512 Carl Corcoran */ BOOL CCString::Path_IsRelative() { return PathIsRelativeW(this->wszString); }
bool os_path_absolute(const std::string& path) { return PathIsRelativeW(ConvertToWchar(path).c_str())==FALSE; }
/************************************************************************* * PathIsRelative [SHELL32.40] */ BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath) { if (SHELL_OsIsUnicode()) return PathIsRelativeW( lpszPath ); return PathIsRelativeA( lpszPath ); }