2 * Copyright 2018 Fabian Maurer
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/heap.h"
24 #include "wine/debug.h"
25 #include "resources.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(find
);
29 static BOOL
read_char_from_handle(HANDLE handle
, char *char_out
)
31 static char buffer
[4096];
32 static UINT buffer_max
= 0;
33 static UINT buffer_pos
= 0;
35 /* Read next content into buffer */
36 if (buffer_pos
>= buffer_max
)
38 BOOL success
= ReadFile(handle
, buffer
, 4096, &buffer_max
, NULL
);
39 if (!success
|| !buffer_max
)
44 *char_out
= buffer
[buffer_pos
++];
48 /* Read a line from a handle, returns NULL if the end is reached */
49 static WCHAR
* read_line_from_handle(HANDLE handle
)
53 WCHAR
*line_converted
;
54 int line_converted_length
;
56 char *line
= heap_alloc(line_max
);
61 success
= read_char_from_handle(handle
, &c
);
75 /* Make sure buffer is large enough */
76 if (length
+ 1 >= line_max
)
79 line
= heap_realloc(line
, line_max
);
86 if (length
- 1 >= 0 && line
[length
- 1] == '\r') /* Strip \r of windows line endings */
89 line_converted_length
= MultiByteToWideChar(CP_ACP
, 0, line
, -1, 0, 0);
90 line_converted
= heap_alloc(line_converted_length
* sizeof(WCHAR
));
91 MultiByteToWideChar(CP_ACP
, 0, line
, -1, line_converted
, line_converted_length
);
95 return line_converted
;
98 static void write_to_stdout(const WCHAR
*str
)
101 UINT str_converted_length
;
103 UINT str_length
= lstrlenW(str
);
104 int codepage
= CP_ACP
;
106 str_converted_length
= WideCharToMultiByte(codepage
, 0, str
, str_length
, NULL
, 0, NULL
, NULL
);
107 str_converted
= heap_alloc(str_converted_length
);
108 WideCharToMultiByte(codepage
, 0, str
, str_length
, str_converted
, str_converted_length
, NULL
, NULL
);
110 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE
), str_converted
, str_converted_length
, &bytes_written
, NULL
);
111 if (bytes_written
< str_converted_length
)
112 ERR("Failed to write output\n");
114 heap_free(str_converted
);
117 static BOOL
run_find_for_line(const WCHAR
*line
, const WCHAR
*tofind
)
121 if (lstrlenW(line
) == 0 || lstrlenW(tofind
) == 0)
124 found
= wcsstr(line
, tofind
);
128 write_to_stdout(line
);
129 write_to_stdout(L
"\r\n");
136 static void output_resource_message(int id
)
139 LoadStringW(GetModuleHandleW(NULL
), id
, buffer
, ARRAY_SIZE(buffer
));
140 write_to_stdout(buffer
);
143 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
146 WCHAR
*tofind
= NULL
;
149 int file_paths_len
= 0;
150 int file_paths_max
= 0;
151 WCHAR
** file_paths
= NULL
;
153 TRACE("running find:");
154 for (i
= 0; i
< argc
; i
++)
156 TRACE(" %s", wine_dbgstr_w(argv
[i
]));
160 for (i
= 1; i
< argc
; i
++)
162 if (argv
[i
][0] == '/')
164 output_resource_message(IDS_INVALID_SWITCH
);
167 else if (tofind
== NULL
)
173 if (file_paths_len
>= file_paths_max
)
175 file_paths_max
= file_paths_max
? file_paths_max
* 2 : 2;
176 file_paths
= heap_realloc(file_paths
, sizeof(WCHAR
*) * file_paths_max
);
178 file_paths
[file_paths_len
++] = argv
[i
];
184 output_resource_message(IDS_INVALID_PARAMETER
);
190 if (file_paths_len
> 0)
192 for (i
= 0; i
< file_paths_len
; i
++)
195 WCHAR file_path_upper
[MAX_PATH
];
197 wcscpy(file_path_upper
, file_paths
[i
]);
198 wcsupr(file_path_upper
);
200 input
= CreateFileW(file_paths
[i
], GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
202 if (input
== INVALID_HANDLE_VALUE
)
204 WCHAR buffer_message
[64];
207 LoadStringW(GetModuleHandleW(NULL
), IDS_FILE_NOT_FOUND
, buffer_message
, ARRAY_SIZE(buffer_message
));
209 wsprintfW(message
, buffer_message
, file_path_upper
);
210 write_to_stdout(message
);
214 write_to_stdout(L
"\r\n---------- ");
215 write_to_stdout(file_path_upper
);
216 write_to_stdout(L
"\r\n");
217 while ((line
= read_line_from_handle(input
)) != NULL
)
219 if (run_find_for_line(line
, tofind
))
229 HANDLE input
= GetStdHandle(STD_INPUT_HANDLE
);
230 while ((line
= read_line_from_handle(input
)) != NULL
)
232 if (run_find_for_line(line
, tofind
))
239 heap_free(file_paths
);