Reactos
1/*
2 * PROJECT: ReactOS Replace Command
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Internal helpers. See cmd/internal.c
5 * COPYRIGHT: Copyright Samuel Erdtman (samuel@erdtman.se)
6 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
7 */
8
9#include "replace.h"
10
11BOOL bCtrlBreak = FALSE; /* Ctrl-Break or Ctrl-C hit */
12
13/*
14 * Helper function for getting the current path from drive
15 * without changing the drive. Return code: 0 = ok, 1 = fail.
16 * 'InPath' can have any size; if the two first letters are
17 * not a drive with ':' it will get the current path on
18 * the current drive exactly as GetCurrentDirectory() does.
19 */
20INT
21GetRootPath(
22 IN LPCTSTR InPath,
23 OUT LPTSTR OutPath,
24 IN INT size)
25{
26 if (InPath[0] && InPath[1] == _T(':'))
27 {
28 INT t = 0;
29
30 if ((InPath[0] >= _T('0')) && (InPath[0] <= _T('9')))
31 {
32 t = (InPath[0] - _T('0')) + 28;
33 }
34 else if ((InPath[0] >= _T('a')) && (InPath[0] <= _T('z')))
35 {
36 t = (InPath[0] - _T('a')) + 1;
37 }
38 else if ((InPath[0] >= _T('A')) && (InPath[0] <= _T('Z')))
39 {
40 t = (InPath[0] - _T('A')) + 1;
41 }
42
43 return (_tgetdcwd(t, OutPath, size) == NULL);
44 }
45
46 /* Get current directory */
47 return !GetCurrentDirectory(size, OutPath);
48}
49
50/*
51 * Takes a path in and returns it with the correct case of the letters
52 */
53VOID GetPathCase( TCHAR * Path, TCHAR * OutPath)
54{
55 UINT i = 0;
56 TCHAR TempPath[MAX_PATH];
57 WIN32_FIND_DATA FindFileData;
58 HANDLE hFind;
59 _tcscpy(TempPath, _T(""));
60 _tcscpy(OutPath, _T(""));
61
62 for(i = 0; i < _tcslen(Path); i++)
63 {
64 if (Path[i] != _T('\\'))
65 {
66 _tcsncat(TempPath, &Path[i], 1);
67 if (i != _tcslen(Path) - 1)
68 continue;
69 }
70 /* Handle the base part of the path different.
71 Because if you put it into findfirstfile, it will
72 return your current folder */
73 if (_tcslen(TempPath) == 2 && TempPath[1] == _T(':'))
74 {
75 _tcscat(OutPath, TempPath);
76 _tcscat(OutPath, _T("\\"));
77 _tcscat(TempPath, _T("\\"));
78 }
79 else
80 {
81 hFind = FindFirstFile(TempPath,&FindFileData);
82 if (hFind == INVALID_HANDLE_VALUE)
83 {
84 _tcscpy(OutPath, Path);
85 return;
86 }
87 _tcscat(TempPath, _T("\\"));
88 _tcscat(OutPath, FindFileData.cFileName);
89 _tcscat(OutPath, _T("\\"));
90 FindClose(hFind);
91 }
92 }
93}
94
95/*
96 * Checks if a file exists (is accessible)
97 */
98BOOL IsExistingFile(IN LPCTSTR pszPath)
99{
100 DWORD attr = GetFileAttributes(pszPath);
101 return ((attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_DIRECTORY));
102}
103
104BOOL IsExistingDirectory(IN LPCTSTR pszPath)
105{
106 DWORD attr = GetFileAttributes(pszPath);
107 return ((attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY));
108}
109
110INT FilePromptYNA (UINT resID)
111{
112 TCHAR szMsg[RC_STRING_MAX_SIZE];
113// TCHAR cKey = 0;
114// LPTSTR szKeys = _T("yna");
115
116 TCHAR szIn[10];
117 LPTSTR p;
118
119 if (resID != 0)
120 ConOutResPrintf (resID);
121
122 /* preliminary fix */
123 ConInString(szIn, 10);
124
125 _tcsupr (szIn);
126 for (p = szIn; _istspace (*p); p++)
127 ;
128
129 LoadString(NULL, STRING_COPY_OPTION, szMsg, ARRAYSIZE(szMsg));
130
131 if (_tcsncmp(p, &szMsg[0], 1) == 0)
132 return PROMPT_YES;
133 else if (_tcsncmp(p, &szMsg[1], 1) == 0)
134 return PROMPT_NO;
135 else if (_tcsncmp(p, &szMsg[2], 1) == 0)
136 return PROMPT_ALL;
137#if 0
138 else if (*p == _T('\03'))
139 return PROMPT_BREAK;
140#endif
141
142 return PROMPT_NO;
143
144 /* unfinished solution */
145#if 0
146 RemoveBreakHandler();
147 ConInDisable();
148
149 do
150 {
151 ConInKey (&ir);
152 cKey = _totlower (ir.Event.KeyEvent.uChar.AsciiChar);
153 if (_tcschr (szKeys, cKey[0]) == NULL)
154 cKey = 0;
155 }
156 while ((ir.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
157 (ir.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
158 (ir.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL));
159
160 AddBreakHandler();
161 ConInEnable();
162
163 if ((ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE) ||
164 ((ir.Event.KeyEvent.wVirtualKeyCode == _T('C')) &&
165 (ir.Event.KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))))
166 return PROMPT_BREAK;
167
168 return PROMPT_YES;
169#endif
170}
171
172VOID ConInString(LPTSTR lpInput, DWORD dwLength)
173{
174 DWORD dwOldMode;
175 DWORD dwRead = 0;
176 HANDLE hFile;
177
178 LPTSTR p;
179 PCHAR pBuf;
180
181#ifdef _UNICODE
182 pBuf = (PCHAR)malloc(dwLength - 1);
183#else
184 pBuf = lpInput;
185#endif
186 ZeroMemory(lpInput, dwLength * sizeof(TCHAR));
187 hFile = GetStdHandle(STD_INPUT_HANDLE);
188 GetConsoleMode(hFile, &dwOldMode);
189
190 SetConsoleMode(hFile, ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
191
192 ReadFile(hFile, (PVOID)pBuf, dwLength - 1, &dwRead, NULL);
193
194#ifdef _UNICODE
195 MultiByteToWideChar(GetConsoleCP(), 0, pBuf, dwRead, lpInput, dwLength - 1);
196 free(pBuf);
197#endif
198 for (p = lpInput; *p; p++)
199 {
200 if (*p == _T('\r')) // Terminate at the carriage-return.
201 {
202 *p = _T('\0');
203 break;
204 }
205 }
206
207 SetConsoleMode(hFile, dwOldMode);
208}
209
210VOID msg_pause(VOID)
211{
212 ConOutResPuts(STRING_ERROR_D_PAUSEMSG);
213}
214
215VOID __cdecl ConFormatMessage(PCON_STREAM Stream, DWORD MessageId, ...)
216{
217 INT Len;
218 va_list arg_ptr;
219
220 va_start(arg_ptr, MessageId);
221 Len = ConMsgPrintfV(Stream,
222 FORMAT_MESSAGE_FROM_SYSTEM,
223 NULL,
224 MessageId,
225 LANG_USER_DEFAULT,
226 &arg_ptr);
227 va_end(arg_ptr);
228
229 if (Len <= 0)
230 ConResPrintf(Stream, STRING_CONSOLE_ERROR, MessageId);
231}
232
233VOID ConOutChar(TCHAR c)
234{
235 ConWrite(StdOut, &c, 1);
236}
237
238/*
239 * get a character out-of-band and honor Ctrl-Break characters
240 */
241TCHAR
242cgetchar (VOID)
243{
244 HANDLE hInput = GetStdHandle (STD_INPUT_HANDLE);
245 INPUT_RECORD irBuffer;
246 DWORD dwRead;
247
248 do
249 {
250 ReadConsoleInput (hInput, &irBuffer, 1, &dwRead);
251 if ((irBuffer.EventType == KEY_EVENT) &&
252 (irBuffer.Event.KeyEvent.bKeyDown != FALSE))
253 {
254 if (irBuffer.Event.KeyEvent.dwControlKeyState &
255 (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
256 {
257 if (irBuffer.Event.KeyEvent.wVirtualKeyCode == 'C')
258 {
259 bCtrlBreak = TRUE;
260 break;
261 }
262 }
263 else if ((irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) ||
264 (irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_MENU) ||
265 (irBuffer.Event.KeyEvent.wVirtualKeyCode == VK_CONTROL))
266 {
267 // Nothing to do
268 }
269 else
270 {
271 break;
272 }
273 }
274 }
275 while (TRUE);
276
277#ifndef _UNICODE
278 return irBuffer.Event.KeyEvent.uChar.AsciiChar;
279#else
280 return irBuffer.Event.KeyEvent.uChar.UnicodeChar;
281#endif /* _UNICODE */
282}