1/* 2 * Copyright (c) 2004, Richard Levitte <richard@levitte.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26#include <windows.h> 27#include <tchar.h> 28#ifndef LPDIR_H 29# include "LPdir.h" 30#endif 31 32/* 33 * We're most likely overcautious here, but let's reserve for broken WinCE 34 * headers and explicitly opt for UNICODE call. Keep in mind that our WinCE 35 * builds are compiled with -DUNICODE [as well as -D_UNICODE]. 36 */ 37#if defined(LP_SYS_WINCE) && !defined(FindFirstFile) 38# define FindFirstFile FindFirstFileW 39#endif 40#if defined(LP_SYS_WINCE) && !defined(FindNextFile) 41# define FindNextFile FindNextFileW 42#endif 43 44#ifndef NAME_MAX 45# define NAME_MAX 255 46#endif 47 48struct LP_dir_context_st { 49 WIN32_FIND_DATA ctx; 50 HANDLE handle; 51 char entry_name[NAME_MAX + 1]; 52}; 53 54const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) 55{ 56 if (ctx == NULL || directory == NULL) { 57 errno = EINVAL; 58 return 0; 59 } 60 61 errno = 0; 62 if (*ctx == NULL) { 63 const char *extdir = directory; 64 char *extdirbuf = NULL; 65 size_t dirlen = strlen(directory); 66 67 if (dirlen == 0) { 68 errno = ENOENT; 69 return 0; 70 } 71 72 *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); 73 if (*ctx == NULL) { 74 errno = ENOMEM; 75 return 0; 76 } 77 memset(*ctx, '\0', sizeof(LP_DIR_CTX)); 78 79 if (directory[dirlen - 1] != '*') { 80 extdirbuf = (char *)malloc(dirlen + 3); 81 if (extdirbuf == NULL) { 82 free(*ctx); 83 *ctx = NULL; 84 errno = ENOMEM; 85 return 0; 86 } 87 if (directory[dirlen - 1] != '/' && directory[dirlen - 1] != '\\') 88 extdir = strcat(strcpy(extdirbuf, directory), "/*"); 89 else 90 extdir = strcat(strcpy(extdirbuf, directory), "*"); 91 } 92 93 if (sizeof(TCHAR) != sizeof(char)) { 94 TCHAR *wdir = NULL; 95 /* len_0 denotes string length *with* trailing 0 */ 96 size_t index = 0, len_0 = strlen(extdir) + 1; 97 98 wdir = (TCHAR *)calloc(len_0, sizeof(TCHAR)); 99 if (wdir == NULL) { 100 if (extdirbuf != NULL) { 101 free(extdirbuf); 102 } 103 free(*ctx); 104 *ctx = NULL; 105 errno = ENOMEM; 106 return 0; 107 } 108#ifdef LP_MULTIBYTE_AVAILABLE 109 if (!MultiByteToWideChar 110 (CP_ACP, 0, extdir, len_0, (WCHAR *)wdir, len_0)) 111#endif 112 for (index = 0; index < len_0; index++) 113 wdir[index] = (TCHAR)extdir[index]; 114 115 (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); 116 117 free(wdir); 118 } else { 119 (*ctx)->handle = FindFirstFile((TCHAR *)extdir, &(*ctx)->ctx); 120 } 121 if (extdirbuf != NULL) { 122 free(extdirbuf); 123 } 124 125 if ((*ctx)->handle == INVALID_HANDLE_VALUE) { 126 free(*ctx); 127 *ctx = NULL; 128 errno = EINVAL; 129 return 0; 130 } 131 } else { 132 if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) { 133 return 0; 134 } 135 } 136 if (sizeof(TCHAR) != sizeof(char)) { 137 TCHAR *wdir = (*ctx)->ctx.cFileName; 138 size_t index, len_0 = 0; 139 140 while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) 141 len_0++; 142 len_0++; 143 144#ifdef LP_MULTIBYTE_AVAILABLE 145 if (!WideCharToMultiByte 146 (CP_ACP, 0, (WCHAR *)wdir, len_0, (*ctx)->entry_name, 147 sizeof((*ctx)->entry_name), NULL, 0)) 148#endif 149 for (index = 0; index < len_0; index++) 150 (*ctx)->entry_name[index] = (char)wdir[index]; 151 } else 152 strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName, 153 sizeof((*ctx)->entry_name) - 1); 154 155 (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0'; 156 157 return (*ctx)->entry_name; 158} 159 160int LP_find_file_end(LP_DIR_CTX **ctx) 161{ 162 if (ctx != NULL && *ctx != NULL) { 163 FindClose((*ctx)->handle); 164 free(*ctx); 165 *ctx = NULL; 166 return 1; 167 } 168 errno = EINVAL; 169 return 0; 170} 171