1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 *makepath.c - create path name from components
10 * To provide support for creation of full path names from components
12 *******************************************************************************/
20 *void Makepath() - build path name from components
23 * create a path name from its individual components
26 * CQuickWSTR &szPath - Buffer for constructed path
27 * WCHAR *drive - pointer to drive component, may or may not contain
29 * WCHAR *dir - pointer to subdirectory component, may or may not include
30 * leading and/or trailing '/' or '\' characters
31 * WCHAR *fname - pointer to file base name component
32 * WCHAR *ext - pointer to extension component, may or may not contain
36 * path - pointer to constructed path name
40 *******************************************************************************/
43 __out CQuickWSTR &szPath,
57 SIZE_T maxCount = 4 // Possible separators between components, plus null terminator
58 + (drive != nullptr ? 2 : 0)
59 + (dir != nullptr ? wcslen(dir) : 0)
60 + (fname != nullptr ? wcslen(fname) : 0)
61 + (ext != nullptr ? wcslen(ext) : 0);
62 LPWSTR path = szPath.AllocNoThrow(maxCount);
67 /* we assume that the arguments are in the following form (although we
68 * do not diagnose invalid arguments or illegal filenames (such as
69 * names longer than 8.3 or with illegal characters in them)
75 * \top\next\last\ ; or
76 * /top/next/last/ ; or
77 * either of the above forms with either/both the leading
78 * and trailing / or \ removed. Mixed use of '/' and '\' is
83 * any valid extension (none if empty or null )
88 if (drive && *drive) {
101 _ASSERTE(count < maxCount);
105 if (*(p=_mbsdec(dir,p)) != _T('/') && *p != _T('\\')) {
107 // suppress warning for the following line; this is safe but would require significant code
108 // delta for prefast to understand.
110 #pragma warning( suppress: 26001 )
112 if (*(p-1) != _T('/') && *(p-1) != _T('\\')) {
117 _ASSERTE(count < maxCount);
128 _ASSERTE(count < maxCount);
132 /* copy ext, including 0-terminator - check to see if a '.' needs
137 if (*p && *p != _T('.')) {
141 _ASSERTE(count < maxCount);
144 while ((*path++ = *p++)) {
147 _ASSERTE(count < maxCount);
151 /* better add the 0-terminator */
155 szPath.Shrink(count + 1);
159 // Returns the directory for HMODULE. So, if HMODULE was for "C:\Dir1\Dir2\Filename.DLL",
160 // then this would return "C:\Dir1\Dir2\" (note the trailing backslash).
161 HRESULT GetHModuleDirectory(
173 DWORD dwRet = WszGetModuleFileName(hMod, wszPath);
176 { // Some other error.
177 return HRESULT_FROM_GetLastError();
180 CopySystemDirectory(wszPath, wszPath);
187 // Returns path name from a file name.
188 // Example: For input "C:\Windows\System.dll" returns "C:\Windows\".
189 // Warning: The input file name string might be destroyed.
192 // pPathString - [in] SString with file name
194 // pBuffer - [out] SString .
197 // S_OK - Output buffer contains path name.
198 // other errors - If Sstring throws.
200 HRESULT CopySystemDirectory(const SString& pPathString,
206 pbuffer.Set(pPathString);
207 SString::Iterator iter = pbuffer.End();
208 if (pbuffer.FindBack(iter,DIRECTORY_SEPARATOR_CHAR_W))
211 pbuffer.Truncate(iter);
218 EX_CATCH_HRESULT(hr);