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/debug.h"
24 #include "resources.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(find
);
28 static BOOL
read_char_from_handle(HANDLE handle
, char *char_out
)
30 static char buffer
[4096];
31 static DWORD buffer_max
= 0;
32 static DWORD buffer_pos
= 0;
34 /* Read next content into buffer */
35 if (buffer_pos
>= buffer_max
)
37 BOOL success
= ReadFile(handle
, buffer
, 4096, &buffer_max
, NULL
);
38 if (!success
|| !buffer_max
)
43 *char_out
= buffer
[buffer_pos
++];
47 /* Read a line from a handle, returns NULL if the end is reached */
48 static WCHAR
* read_line_from_handle(HANDLE handle
)
52 WCHAR
*line_converted
;
53 int line_converted_length
;
55 char *line
= malloc(line_max
);
60 success
= read_char_from_handle(handle
, &c
);
74 /* Make sure buffer is large enough */
75 if (length
+ 1 >= line_max
)
78 line
= realloc(line
, line_max
);
85 if (length
- 1 >= 0 && line
[length
- 1] == '\r') /* Strip \r of windows line endings */
88 line_converted_length
= MultiByteToWideChar(CP_ACP
, 0, line
, -1, 0, 0);
89 line_converted
= malloc(line_converted_length
* sizeof(WCHAR
));
90 MultiByteToWideChar(CP_ACP
, 0, line
, -1, line_converted
, line_converted_length
);
94 return line_converted
;
97 static void write_to_stdout(const WCHAR
*str
)
100 UINT str_converted_length
;
102 UINT str_length
= lstrlenW(str
);
103 int codepage
= CP_ACP
;
105 str_converted_length
= WideCharToMultiByte(codepage
, 0, str
, str_length
, NULL
, 0, NULL
, NULL
);
106 str_converted
= malloc(str_converted_length
);
107 WideCharToMultiByte(codepage
, 0, str
, str_length
, str_converted
, str_converted_length
, NULL
, NULL
);
109 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE
), str_converted
, str_converted_length
, &bytes_written
, NULL
);
110 if (bytes_written
< str_converted_length
)
111 ERR("Failed to write output\n");
116 static BOOL
run_find_for_line(const WCHAR
*line
, const WCHAR
*tofind
)
120 if (lstrlenW(line
) == 0 || lstrlenW(tofind
) == 0)
123 found
= wcsstr(line
, tofind
);
127 write_to_stdout(line
);
128 write_to_stdout(L
"\r\n");
135 static void output_resource_message(int id
)
138 LoadStringW(GetModuleHandleW(NULL
), id
, buffer
, ARRAY_SIZE(buffer
));
139 write_to_stdout(buffer
);
142 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
145 WCHAR
*tofind
= NULL
;
148 int file_paths_len
= 0;
149 int file_paths_max
= 0;
150 WCHAR
** file_paths
= NULL
;
152 TRACE("running find:");
153 for (i
= 0; i
< argc
; i
++)
155 TRACE(" %s", wine_dbgstr_w(argv
[i
]));
159 for (i
= 1; i
< argc
; i
++)
161 if (argv
[i
][0] == '/')
163 output_resource_message(IDS_INVALID_SWITCH
);
166 else if (tofind
== NULL
)
172 if (file_paths_len
>= file_paths_max
)
174 file_paths_max
= file_paths_max
? file_paths_max
* 2 : 2;
175 file_paths
= realloc(file_paths
, sizeof(WCHAR
*) * file_paths_max
);
177 file_paths
[file_paths_len
++] = argv
[i
];
183 output_resource_message(IDS_INVALID_PARAMETER
);
189 if (file_paths_len
> 0)
191 for (i
= 0; i
< file_paths_len
; i
++)
194 WCHAR file_path_upper
[MAX_PATH
];
196 wcscpy(file_path_upper
, file_paths
[i
]);
197 wcsupr(file_path_upper
);
199 input
= CreateFileW(file_paths
[i
], GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
201 if (input
== INVALID_HANDLE_VALUE
)
203 WCHAR buffer_message
[64];
206 LoadStringW(GetModuleHandleW(NULL
), IDS_FILE_NOT_FOUND
, buffer_message
, ARRAY_SIZE(buffer_message
));
208 wsprintfW(message
, buffer_message
, file_path_upper
);
209 write_to_stdout(message
);
213 write_to_stdout(L
"\r\n---------- ");
214 write_to_stdout(file_path_upper
);
215 write_to_stdout(L
"\r\n");
216 while ((line
= read_line_from_handle(input
)) != NULL
)
218 if (run_find_for_line(line
, tofind
))
228 HANDLE input
= GetStdHandle(STD_INPUT_HANDLE
);
229 while ((line
= read_line_from_handle(input
)) != NULL
)
231 if (run_find_for_line(line
, tofind
))