[Tizen] Unify dnetmemoryenumlib terms to match the codebase (#291)
[platform/upstream/coreclr.git] / src / utilcode / makepath.cpp
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.
4 /***
5 *makepath.c - create path name from components
6 *
7
8 *
9 *Purpose:
10 *       To provide support for creation of full path names from components
11 *
12 *******************************************************************************/
13 #include "stdafx.h"
14 #include "winwrap.h"
15 #include "utilcode.h"
16 #include "ex.h"
17
18
19 /***
20 *void Makepath() - build path name from components
21 *
22 *Purpose:
23 *       create a path name from its individual components
24 *
25 *Entry:
26 *       CQuickWSTR &szPath - Buffer for constructed path
27 *       WCHAR *drive - pointer to drive component, may or may not contain
28 *                     trailing ':'
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
33 *                     a leading '.'.
34 *
35 *Exit:
36 *       path - pointer to constructed path name
37 *
38 *Exceptions:
39 *
40 *******************************************************************************/
41
42 void MakePath (
43         __out CQuickWSTR &szPath,
44         __in LPCWSTR drive,
45         __in LPCWSTR dir,
46         __in LPCWSTR fname,
47         __in LPCWSTR ext
48         )
49 {
50         CONTRACTL
51         {
52             NOTHROW;
53             GC_NOTRIGGER;
54         }
55         CONTRACTL_END
56
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);
63
64         const WCHAR *p;
65         DWORD count = 0;
66
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)
70          *
71          *  drive:
72          *      A           ; or
73          *      A:
74          *  dir:
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
79          *      also tolerated
80          *  fname:
81          *      any valid file name
82          *  ext:
83          *      any valid extension (none if empty or null )
84          */
85
86         /* copy drive */
87
88         if (drive && *drive) {
89                 *path++ = *drive;
90                 *path++ = _T(':');
91                 count += 2;
92         }
93
94         /* copy dir */
95
96         if ((p = dir)) {
97                 while (*p) {
98                         *path++ = *p++;
99                         count++;
100
101                         _ASSERTE(count < maxCount);
102                 }
103
104 #ifdef _MBCS
105                 if (*(p=_mbsdec(dir,p)) != _T('/') && *p != _T('\\')) {
106 #else  /* _MBCS */
107                 // suppress warning for the following line; this is safe but would require significant code
108                 // delta for prefast to understand.
109 #ifdef _PREFAST_
110                 #pragma warning( suppress: 26001 ) 
111 #endif
112                 if (*(p-1) != _T('/') && *(p-1) != _T('\\')) {
113 #endif  /* _MBCS */
114                         *path++ = _T('\\');
115                         count++;
116
117                         _ASSERTE(count < maxCount);
118                 }
119         }
120
121         /* copy fname */
122
123         if ((p = fname)) {
124                 while (*p) {
125                         *path++ = *p++;
126                         count++;
127
128                         _ASSERTE(count < maxCount);
129                 }
130         }
131
132         /* copy ext, including 0-terminator - check to see if a '.' needs
133          * to be inserted.
134          */
135
136         if ((p = ext)) {
137                 if (*p && *p != _T('.')) {
138                         *path++ = _T('.');
139                         count++;
140
141                         _ASSERTE(count < maxCount);
142                 }
143
144                 while ((*path++ = *p++)) {
145                     count++;
146
147                     _ASSERTE(count < maxCount);
148                 }
149         }
150         else {
151                 /* better add the 0-terminator */
152                 *path = _T('\0');
153         }
154
155         szPath.Shrink(count + 1);
156 }
157
158
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(
162     __in                          HMODULE   hMod,
163     SString&                                 wszPath)
164 {
165     CONTRACTL
166     {
167         NOTHROW;
168         GC_NOTRIGGER;
169         CANNOT_TAKE_LOCK;
170     }
171     CONTRACTL_END;
172
173     DWORD dwRet = WszGetModuleFileName(hMod, wszPath);
174    
175      if (dwRet == 0)
176     {   // Some other error.
177         return HRESULT_FROM_GetLastError();
178     }
179
180      CopySystemDirectory(wszPath, wszPath);
181          
182
183     return S_OK;
184 }
185
186 //
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.
190 // 
191 // Arguments:
192 //    pPathString - [in] SString with file  name
193 //                
194 //    pBuffer    - [out] SString .
195 // 
196 // Return Value:
197 //    S_OK - Output buffer contains path name.
198 //    other errors - If Sstring throws.
199 //
200 HRESULT CopySystemDirectory(const SString& pPathString,
201                             SString& pbuffer)
202 {
203     HRESULT hr = S_OK;
204     EX_TRY
205     {
206         pbuffer.Set(pPathString);
207         SString::Iterator iter = pbuffer.End();
208         if (pbuffer.FindBack(iter,DIRECTORY_SEPARATOR_CHAR_W))
209         {
210             iter++;
211             pbuffer.Truncate(iter);
212         }
213         else
214         {
215             hr = E_UNEXPECTED;
216         }
217     }
218     EX_CATCH_HRESULT(hr);
219
220     return hr;
221 }