1 /* 2 * Copyright (c) 2004, Richard Levitte <richard (at) 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 /* We're most likely overcautious here, but let's reserve for 33 broken WinCE headers and explicitly opt for UNICODE call. 34 Keep in mind that our WinCE builds are compiled with -DUNICODE 35 [as well as -D_UNICODE]. */ 36 #if defined(LP_SYS_WINCE) && !defined(FindFirstFile) 37 # define FindFirstFile FindFirstFileW 38 #endif 39 #if defined(LP_SYS_WINCE) && !defined(FindFirstFile) 40 # define FindNextFile FindNextFileW 41 #endif 42 43 #ifndef NAME_MAX 44 #define NAME_MAX 255 45 #endif 46 47 struct LP_dir_context_st 48 { 49 WIN32_FIND_DATA ctx; 50 HANDLE handle; 51 char entry_name[NAME_MAX+1]; 52 }; 53 54 const char *LP_find_file(LP_DIR_CTX **ctx, const char *directory) 55 { 56 if (ctx == NULL || directory == NULL) 57 { 58 errno = EINVAL; 59 return 0; 60 } 61 62 errno = 0; 63 if (*ctx == NULL) 64 { 65 const char *extdir = directory; 66 char *extdirbuf = NULL; 67 size_t dirlen = strlen (directory); 68 69 if (dirlen == 0) 70 { 71 errno = ENOENT; 72 return 0; 73 } 74 75 *ctx = (LP_DIR_CTX *)malloc(sizeof(LP_DIR_CTX)); 76 if (*ctx == NULL) 77 { 78 errno = ENOMEM; 79 return 0; 80 } 81 memset(*ctx, '\0', sizeof(LP_DIR_CTX)); 82 83 if (directory[dirlen-1] != '*') 84 { 85 extdirbuf = (char *)malloc(dirlen + 3); 86 if (extdirbuf == NULL) 87 { 88 free(*ctx); 89 *ctx = NULL; 90 errno = ENOMEM; 91 return 0; 92 } 93 if (directory[dirlen-1] != '/' && directory[dirlen-1] != '\\') 94 extdir = strcat(strcpy (extdirbuf,directory),"/*"); 95 else 96 extdir = strcat(strcpy (extdirbuf,directory),"*"); 97 } 98 99 if (sizeof(TCHAR) != sizeof(char)) 100 { 101 TCHAR *wdir = NULL; 102 /* len_0 denotes string length *with* trailing 0 */ 103 size_t index = 0,len_0 = strlen(extdir) + 1; 104 105 wdir = (TCHAR *)calloc(len_0, sizeof(TCHAR)); 106 if (wdir == NULL) 107 { 108 if (extdirbuf != NULL) 109 { 110 free (extdirbuf); 111 } 112 free(*ctx); 113 *ctx = NULL; 114 errno = ENOMEM; 115 return 0; 116 } 117 118 #ifdef LP_MULTIBYTE_AVAILABLE 119 if (!MultiByteToWideChar(CP_ACP, 0, extdir, len_0, (WCHAR *)wdir, len_0)) 120 #endif 121 for (index = 0; index < len_0; index++) 122 wdir[index] = (TCHAR)extdir[index]; 123 124 (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx); 125 126 free(wdir); 127 } 128 else 129 { 130 (*ctx)->handle = FindFirstFile((TCHAR *)extdir, &(*ctx)->ctx); 131 } 132 if (extdirbuf != NULL) 133 { 134 free (extdirbuf); 135 } 136 137 if ((*ctx)->handle == INVALID_HANDLE_VALUE) 138 { 139 free(*ctx); 140 *ctx = NULL; 141 errno = EINVAL; 142 return 0; 143 } 144 } 145 else 146 { 147 if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) 148 { 149 return 0; 150 } 151 } 152 if (sizeof(TCHAR) != sizeof(char)) 153 { 154 TCHAR *wdir = (*ctx)->ctx.cFileName; 155 size_t index, len_0 = 0; 156 157 while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) len_0++; 158 len_0++; 159 160 #ifdef LP_MULTIBYTE_AVAILABLE 161 if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0, (*ctx)->entry_name, 162 sizeof((*ctx)->entry_name), NULL, 0)) 163 #endif 164 for (index = 0; index < len_0; index++) 165 (*ctx)->entry_name[index] = (char)wdir[index]; 166 } 167 else 168 strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName, 169 sizeof((*ctx)->entry_name)-1); 170 171 (*ctx)->entry_name[sizeof((*ctx)->entry_name)-1] = '\0'; 172 173 return (*ctx)->entry_name; 174 } 175 176 int LP_find_file_end(LP_DIR_CTX **ctx) 177 { 178 if (ctx != NULL && *ctx != NULL) 179 { 180 FindClose((*ctx)->handle); 181 free(*ctx); 182 *ctx = NULL; 183 return 1; 184 } 185 errno = EINVAL; 186 return 0; 187 } 188