195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */
295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley/*
395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * All rights reserved.
595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * Redistribution and use in source and binary forms, with or without
795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * modification, are permitted provided that the following conditions
895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * are met:
995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 1. Redistributions of source code must retain the above copyright
1095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer.
1195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * 2. Redistributions in binary form must reproduce the above copyright
1295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    notice, this list of conditions and the following disclaimer in the
1395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *    documentation and/or other materials provided with the distribution.
1495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley *
1595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley */
2795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
2895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include "directory.h"
2995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#if defined(OPENSSL_WINDOWS)
3295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <windows.h>
3495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <tchar.h>
3595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#include <errno.h>
3695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
3795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#ifndef NAME_MAX
3895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#define NAME_MAX 255
3995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif
4095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
4195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleystruct OPENSSL_dir_context_st {
4295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  WIN32_FIND_DATA ctx;
4395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  HANDLE handle;
4495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  char entry_name[NAME_MAX + 1];
4595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley};
4695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
4795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyconst char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
4895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx == NULL || directory == NULL) {
4995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    errno = EINVAL;
5095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 0;
5195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
5295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
5395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  errno = 0;
5495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (*ctx == NULL) {
5595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
5695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (*ctx == NULL) {
5795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      errno = ENOMEM;
5895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
5995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
6095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
6195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (sizeof(TCHAR) != sizeof(char)) {
6395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      TCHAR *wdir = NULL;
6495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      /* len_0 denotes string length *with* trailing 0 */
6595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      size_t index = 0, len_0 = strlen(directory) + 1;
6695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
6795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR));
6895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (wdir == NULL) {
6995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        free(*ctx);
7095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        *ctx = NULL;
7195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        errno = ENOMEM;
7295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        return 0;
7395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
7495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
7595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir,
7695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                               len_0)) {
7795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        for (index = 0; index < len_0; index++) {
7895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley          wdir[index] = (TCHAR)directory[index];
7995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        }
8095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
8195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
8395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      free(wdir);
8595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    } else {
8695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
8795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
8895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
8995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
9095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      free(*ctx);
9195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      *ctx = NULL;
9295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      errno = EINVAL;
9395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
9495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
9595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
9695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
9795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      return 0;
9895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
9995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
10095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (sizeof(TCHAR) != sizeof(char)) {
10295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    TCHAR *wdir = (*ctx)->ctx.cFileName;
10395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    size_t index, len_0 = 0;
10495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
10595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) {
10695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      len_0++;
10795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
10895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    len_0++;
10995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
11095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0,
11195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                             (*ctx)->entry_name, sizeof((*ctx)->entry_name),
11295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley                             NULL, 0)) {
11395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      for (index = 0; index < len_0; index++) {
11495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley        (*ctx)->entry_name[index] = (char)wdir[index];
11595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley      }
11695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    }
11795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  } else {
11895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
11995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley            sizeof((*ctx)->entry_name) - 1);
12095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
12195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
12395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return (*ctx)->entry_name;
12595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
12695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
12795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langleyint OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
12895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  if (ctx != NULL && *ctx != NULL) {
12995c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    FindClose((*ctx)->handle);
13095c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    free(*ctx);
13195c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    *ctx = NULL;
13295c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley    return 1;
13395c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  }
13495c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  errno = EINVAL;
13595c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley  return 0;
13695c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley}
13795c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley
13895c29f3cd1f6c08c6c0927868683392eea727ccAdam Langley#endif  /* OPENSSL_WINDOWS */
139