Merge 13831:14550 from trunk

svn path=/branches/xmlbuildsystem/; revision=14575
This commit is contained in:
Casper Hornstrup
2005-04-10 14:32:30 +00:00
1089 changed files with 131731 additions and 74063 deletions
+2
View File
@@ -79,6 +79,7 @@ ifeq ($(HALFVERBOSEECHO),yes)
ECHO_AR =@echo [AR] $@
ECHO_WINEBLD =@echo [WINEBLD] $@
ECHO_WRC =@echo [WRC] $@
ECHO_WIDL =@echo [WIDL] $@
ECHO_BIN2RES =@echo [BIN2RES] $<
ECHO_DLLTOOL =@echo [DLLTOOL] $@
ECHO_LD =@echo [LD] $@
@@ -105,6 +106,7 @@ else
ECHO_AR =
ECHO_WINEBLD =
ECHO_WRC =
ECHO_WIDL =
ECHO_BIN2RES =
ECHO_DLLTOOL =
ECHO_LD =
+3
View File
@@ -38,6 +38,9 @@
<directory name="hal">
<xi:include href="hal/directory.xml" />
</directory>
<directory name="include">
<xi:include href="include/directory.xml" />
</directory>
<directory name="lib">
<xi:include href="lib/directory.xml" />
</directory>
+1 -1
View File
@@ -11,7 +11,7 @@ TARGET_APPTYPE = console
TARGET_NAME = loadlib
TARGET_CFLAGS = -Wall -Werror -D_USE_W32API -DUNICODE -D_UNICODE
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API -DUNICODE -D_UNICODE
TARGET_SDKLIBS = kernel32.a ntdll.a
+1 -1
View File
@@ -9,7 +9,7 @@ include $(PATH_TO_TOP)/rules.mak
# Console system utilities
# cabman cat net objdir partinfo pice ps sc stats
UTIL_APPS = cat objdir partinfo pnpdump sc shutdown stats tickcount consw ps
UTIL_APPS = cat objdir pnpdump sc shutdown stats tickcount ps
UTIL_NET_APPS = arp finger ftp ipconfig netstat ping route telnet whois
@@ -1,23 +1,21 @@
# $Id$
PATH_TO_TOP = ../../..
TARGET_NORC = yes
TARGET_TYPE = program
TARGET_APPTYPE = console
TARGET_NAME = consw
TARGET_SDKLIBS = ntdll.a kernel32.a
TARGET_OBJECTS = $(TARGET_NAME).o
TARGET_CFLAGS = -Wall -Werror
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# EOF
PATH_TO_TOP = ../../..
TARGET_NORC = yes
TARGET_TYPE = program
TARGET_APPTYPE = console
TARGET_NAME = binpatch
TARGET_SDKLIBS =
TARGET_OBJECTS = patch.o
TARGET_CFLAGS += -Wall -Werror
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# EOF
+615
View File
@@ -0,0 +1,615 @@
#include <conio.h>
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
/** DEFINES *******************************************************************/
#define PATCH_BUFFER_SIZE 4096 /* Maximum size of a patch */
#define PATCH_BUFFER_MAGIC "\xde\xad\xbe\xef MaGiC MaRk "
#define SIZEOF_PATCH_BUFFER_MAGIC (sizeof (PATCH_BUFFER_MAGIC) - 1)
/** TYPES *********************************************************************/
typedef struct _PatchedByte
{
int offset; /*!< File offset of the patched byte. */
unsigned char expected; /*!< Expected (original) value of the byte. */
unsigned char patched; /*!< Patched (new) value for the byte. */
} PatchedByte;
typedef struct _PatchedFile
{
const char *name; /*!< Name of the file to be patched. */
int fileSize; /*!< Size of the file in bytes. */
int patchCount; /*!< Number of patches for the file. */
PatchedByte *patches; /*!< Patches for the file. */
} PatchedFile;
typedef struct _Patch
{
const char *name; /*!< Name of the patch. */
int fileCount; /*!< Number of files in the patch. */
PatchedFile *files; /*!< Files for the patch. */
} Patch;
/** FUNCTION PROTOTYPES *******************************************************/
static void printUsage();
/** GLOBALS *******************************************************************/
static Patch m_patch = { NULL, 0, NULL };
static int m_argc = 0;
static char **m_argv = NULL;
/* patch buffer where we put the patch info into */
static unsigned char m_patchBuffer[SIZEOF_PATCH_BUFFER_MAGIC + PATCH_BUFFER_SIZE] =
PATCH_BUFFER_MAGIC;
/** HELPER FUNCTIONS **********************************************************/
static void *
loadFile(const char *fileName, int *fileSize_)
{
FILE *f;
struct stat sb;
int fileSize;
void *p;
/* Open the file */
f = fopen(fileName, "rb");
if (f == NULL)
{
printf("Couldn't open file %s for reading!\n", fileName);
return NULL;
}
/* Get file size */
if (fstat(fileno(f), &sb) < 0)
{
fclose(f);
printf("Couldn't get size of file %s!\n", fileName);
return NULL;
}
fileSize = sb.st_size;
/* Load file */
p = malloc(fileSize);
if (p == NULL)
{
fclose(f);
printf("Couldn't allocate %d bytes for file %s!\n", fileSize, fileName);
return NULL;
}
if (fread(p, fileSize, 1, f) != 1)
{
fclose(f);
free(p);
printf("Couldn't read file %s into memory!\n", fileName);
return NULL;
}
/* Close file */
fclose(f);
*fileSize_ = fileSize;
return p;
}
static int
saveFile(const char *fileName, void *file, int fileSize)
{
FILE *f;
/* Open the file */
f = fopen(fileName, "wb");
if (f == NULL)
{
printf("Couldn't open file %s for writing!\n", fileName);
return -1;
}
/* Write file */
if (fwrite(file, fileSize, 1, f) != 1)
{
fclose(f);
printf("Couldn't write file %s!\n", fileName);
return -1;
}
/* Close file */
fclose(f);
return 0;
}
static int
compareFiles(
PatchedFile *patchedFile,
const char *originalFileName)
{
const char *patchedFileName = patchedFile->name;
unsigned char *origChunk, *patchedChunk;
int origSize, patchedSize, i, patchCount;
PatchedByte *patches = NULL;
int patchesArrayCount = 0;
/* Load both files */
origChunk = loadFile(originalFileName, &origSize);
if (origChunk == NULL)
return -1;
patchedChunk = loadFile(patchedFileName, &patchedSize);
if (patchedChunk == NULL)
{
free(origChunk);
return -1;
}
if (origSize != patchedSize)
{
free(origChunk);
free(patchedChunk);
printf("File size of %s and %s differs (%d != %d)\n",
originalFileName, patchedFileName,
origSize, patchedSize);
return -1;
}
/* Compare the files and record any differences */
printf("Comparing %s to %s", originalFileName, patchedFileName);
for (i = 0, patchCount = 0; i < origSize; i++)
{
if (origChunk[i] != patchedChunk[i])
{
patchCount++;
/* Resize patches array if needed */
if (patchesArrayCount < patchCount)
{
PatchedByte *newPatches;
newPatches = realloc(patches, patchCount * sizeof (PatchedByte));
if (newPatches == NULL)
{
if (patches != NULL)
free(patches);
free(origChunk);
free(patchedChunk);
printf("\nOut of memory (tried to allocated %d bytes)\n",
patchCount * sizeof (PatchedByte));
return -1;
}
patches = newPatches;
}
/* Fill in patch info */
patches[patchCount - 1].offset = i;
patches[patchCount - 1].expected = origChunk[i];
patches[patchCount - 1].patched = patchedChunk[i];
}
if ((i % (origSize / 40)) == 0)
printf(".");
}
printf(" %d changed bytes found.\n", patchCount);
/* Unload the files */
free(origChunk);
free(patchedChunk);
/* Save patch info */
patchedFile->fileSize = patchedSize;
patchedFile->patchCount = patchCount;
patchedFile->patches = patches;
return 0;
}
static int
outputPatch(const char *outputFileName)
{
unsigned char *patchExe, *patchBuffer;
int i, size, patchExeSize, patchSize, stringSize, stringOffset, patchOffset;
Patch *patch;
PatchedFile *files;
printf("Putting patch into %s...\n", outputFileName);
/* Calculate size of the patch */
patchSize = sizeof (Patch) + sizeof (PatchedFile) * m_patch.fileCount;
stringSize = strlen(m_patch.name) + 1;
for (i = 0; i < m_patch.fileCount; i++)
{
stringSize += strlen(m_patch.files[i].name) + 1;
patchSize += sizeof (PatchedByte) * m_patch.files[i].patchCount;
}
if ((stringSize + patchSize) > PATCH_BUFFER_SIZE)
{
printf("Patch is too big - %d bytes maximum, %d bytes needed\n",
PATCH_BUFFER_SIZE, stringSize + patchSize);
return -1;
}
/* Load patch.exe file into memory... */
patchExe = loadFile(m_argv[0], &patchExeSize);
if (patchExe == NULL)
{
return -1;
}
/* Try to find the magic mark for the patch buffer */
for (i = 0; i < (patchExeSize - SIZEOF_PATCH_BUFFER_MAGIC); i++)
{
if (memcmp(patchExe + i, m_patchBuffer, SIZEOF_PATCH_BUFFER_MAGIC) == 0)
{
patchBuffer = patchExe + i + SIZEOF_PATCH_BUFFER_MAGIC;
break;
}
}
if (!(i < (patchExeSize - SIZEOF_PATCH_BUFFER_MAGIC)))
{
free(patchExe);
printf("Couldn't find patch buffer magic in file %s - this shouldn't happen!!!\n", m_argv[0]);
return -1;
}
/* Pack patch together and replace string pointers by offsets */
patch = (Patch *)patchBuffer;
files = (PatchedFile *)(patchBuffer + sizeof (Patch));
patchOffset = sizeof (Patch) + sizeof (PatchedFile) * m_patch.fileCount;
stringOffset = patchSize;
patch->fileCount = m_patch.fileCount;
patch->files = (PatchedFile *)sizeof (Patch);
patch->name = (const char *)stringOffset;
strcpy(patchBuffer + stringOffset, m_patch.name);
stringOffset += strlen(m_patch.name) + 1;
for (i = 0; i < m_patch.fileCount; i++)
{
files[i].fileSize = m_patch.files[i].fileSize;
files[i].patchCount = m_patch.files[i].patchCount;
files[i].name = (const char *)stringOffset;
strcpy(patchBuffer + stringOffset, m_patch.files[i].name);
stringOffset += strlen(m_patch.files[i].name) + 1;
size = files[i].patchCount * sizeof (PatchedByte);
files[i].patches = (PatchedByte *)patchOffset;
memcpy(patchBuffer + patchOffset, m_patch.files[i].patches, size);
patchOffset += size;
}
size = patchSize + stringSize;
memset(patchBuffer + size, 0, PATCH_BUFFER_SIZE - size);
/* Save file */
if (saveFile(outputFileName, patchExe, patchExeSize) < 0)
{
free(patchExe);
return -1;
}
free(patchExe);
printf("Patch saved!\n");
return 0;
}
static int
loadPatch()
{
char *p;
Patch *patch;
int i;
p = m_patchBuffer + SIZEOF_PATCH_BUFFER_MAGIC;
patch = (Patch *)p;
if (patch->name == NULL)
{
return -1;
}
m_patch.name = p + (int)patch->name;
m_patch.fileCount = patch->fileCount;
m_patch.files = (PatchedFile *)(p + (int)patch->files);
for (i = 0; i < m_patch.fileCount; i++)
{
m_patch.files[i].name = p + (int)m_patch.files[i].name;
m_patch.files[i].patches = (PatchedByte *)(p + (int)m_patch.files[i].patches);
}
printf("Patch %s loaded...\n", m_patch.name);
return 0;
}
/** MAIN FUNCTIONS ************************************************************/
static int
createPatch()
{
int i, status;
const char *outputFileName;
/* Check argument count */
if (m_argc < 6 || (m_argc % 2) != 0)
{
printUsage();
return -1;
}
outputFileName = m_argv[3];
m_patch.name = m_argv[2];
/* Allocate PatchedFiles array */
m_patch.fileCount = (m_argc - 4) / 2;
m_patch.files = malloc(m_patch.fileCount * sizeof (PatchedFile));
if (m_patch.files == NULL)
{
printf("Out of memory!\n");
return -1;
}
memset(m_patch.files, 0, m_patch.fileCount * sizeof (PatchedFile));
/* Compare original to patched files and fill m_patch.files array */
for (i = 0; i < m_patch.fileCount; i++)
{
m_patch.files[i].name = m_argv[4 + (i * 2) + 1];
status = compareFiles(m_patch.files + i, m_argv[4 + (i * 2) + 0]);
if (status < 0)
{
for (i = 0; i < m_patch.fileCount; i++)
{
if (m_patch.files[i].patches != NULL)
free(m_patch.files[i].patches);
}
free(m_patch.files);
m_patch.files = NULL;
m_patch.fileCount = 0;
return status;
}
}
/* Output patch */
return outputPatch(outputFileName);
}
static int
applyPatch()
{
int c, i, j, fileSize, makeBackup;
unsigned char *file;
char *p;
const char *fileName;
char buffer[MAX_PATH];
if (m_argc > 1 && strcmp(m_argv[1], "-d") != 0)
{
printUsage();
return -1;
}
/* Load patch */
if (loadPatch() < 0)
{
printf("This executable doesn't contain a patch, use -c to create one.\n");
return -1;
}
if (m_argc > 1)
{
/* Dump patch */
printf("Patch name: %s\n", m_patch.name);
printf("File count: %d\n", m_patch.fileCount);
for (i = 0; i < m_patch.fileCount; i++)
{
printf("----------------------\n"
"File name: %s\n"
"File size: %d bytes\n",
m_patch.files[i].name, m_patch.files[i].fileSize);
printf("Patch count: %d\n", m_patch.files[i].patchCount);
for (j = 0; j < m_patch.files[i].patchCount; j++)
{
printf(" Offset 0x%x 0x%02x -> 0x%02x\n",
m_patch.files[i].patches[j].offset,
m_patch.files[i].patches[j].expected,
m_patch.files[i].patches[j].patched);
}
}
}
else
{
/* Apply patch */
printf("Applying patch...\n");
for (i = 0; i < m_patch.fileCount; i++)
{
/* Load original file */
fileName = m_patch.files[i].name;
applyPatch_retry_file:
file = loadFile(fileName, &fileSize);
if (file == NULL)
{
printf("File %s not found! ", fileName);
applyPatch_file_open_error:
printf("(S)kip, (R)etry, (A)bort, (M)anually enter filename");
do
{
c = getch();
}
while (c != 's' && c != 'r' && c != 'a' && c != 'm');
printf("\n");
if (c == 's')
{
continue;
}
else if (c == 'r')
{
goto applyPatch_retry_file;
}
else if (c == 'a')
{
return 0;
}
else if (c == 'm')
{
if (fgets(buffer, sizeof (buffer), stdin) == NULL)
{
printf("fgets() failed!\n");
return -1;
}
p = strchr(buffer, '\r');
if (p != NULL)
*p = '\0';
p = strchr(buffer, '\n');
if (p != NULL)
*p = '\0';
fileName = buffer;
goto applyPatch_retry_file;
}
}
/* Check file size */
if (fileSize != m_patch.files[i].fileSize)
{
free(file);
printf("File %s has unexpected filesize of %d bytes (%d bytes expected)\n",
fileName, fileSize, m_patch.files[i].fileSize);
if (fileName != m_patch.files[i].name) /* manually entered filename */
{
goto applyPatch_file_open_error;
}
return -1;
}
/* Ask for backup */
printf("Do you want to make a backup of %s? (Y)es, (N)o, (A)bort", fileName);
do
{
c = getch();
}
while (c != 'y' && c != 'n' && c != 'a');
printf("\n");
if (c == 'y')
{
char buffer[MAX_PATH];
snprintf(buffer, MAX_PATH, "%s.bak", fileName);
buffer[MAX_PATH-1] = '\0';
makeBackup = 1;
if (access(buffer, 0) >= 0) /* file exists */
{
printf("File %s already exists, overwrite? (Y)es, (N)o, (A)bort", buffer);
do
{
c = getch();
}
while (c != 'y' && c != 'n' && c != 'a');
printf("\n");
if (c == 'n')
makeBackup = 0;
else if (c == 'a')
{
free(file);
return 0;
}
}
if (makeBackup && saveFile(buffer, file, fileSize) < 0)
{
free(file);
return -1;
}
}
else if (c == 'a')
{
free(file);
return 0;
}
/* Patch file */
for (j = 0; j < m_patch.files[i].patchCount; j++)
{
int offset = m_patch.files[i].patches[j].offset;
if (file[offset] != m_patch.files[i].patches[j].expected)
{
printf("Unexpected value in file %s at offset 0x%x: expected = 0x%02x, found = 0x%02x\n",
fileName, offset, m_patch.files[i].patches[j].expected, file[offset]);
free(file);
return -1;
}
file[offset] = m_patch.files[i].patches[j].patched;
}
/* Save file */
if (saveFile(fileName, file, fileSize) < 0)
{
free(file);
return -1;
}
free(file);
}
printf("Patch applied sucessfully!\n");
}
return 0;
}
static void
printUsage()
{
printf("Usage:\n"
"%s -c - Create patch\n"
"%s -d - Dump patch\n"
"%s - Apply patch\n"
"\n"
"A patch can be created like this:\n"
"%s -c \"patch name\" output.exe file1.orig file1.patched[ file2.orig file2.patched[ ...]]\n",
m_argv[0], m_argv[0], m_argv[0], m_argv[0]);
}
int
main(
int argc,
char *argv[])
{
m_argc = argc;
m_argv = argv;
if (argc >= 2 && (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0))
{
printUsage();
return 0;
}
else if (argc >= 2 && argv[1][0] == '-')
{
if (strcmp(argv[1], "-c") == 0)
{
return createPatch();
}
else if (strcmp(argv[1], "-d") == 0)
{
return applyPatch();
}
else
{
printf("Unknown option: %s\n"
"Use -h for help.\n",
argv[1]);
return -1;
}
}
return applyPatch();
}
-30
View File
@@ -1,30 +0,0 @@
/* $Id$
*
* DESCRIPTION: Console mode switcher
* PROGRAMMER: Art Yerkes
* REVISIONS
* 2003-07-26 (arty)
*/
#include <windows.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void STDCALL SetConsoleHardwareState( HANDLE conhandle,
DWORD flags,
DWORD state );
int main(int argc, char* argv[])
{
if( argc > 1 ) {
SetConsoleHardwareState( GetStdHandle( STD_INPUT_HANDLE ),
0,
!strcmp( argv[1], "hw" ) );
}
return 0;
}
/* EOF */
-5
View File
@@ -1,5 +0,0 @@
@echo off
rem Turn off cosole, run a program, turn console on
\reactos\bin\consw sw
"%1" "%2" "%3" "%4" "%5" "%6" "%7" "%8" "%9"
\reactos\bin\consw hw
+2
View File
@@ -8,6 +8,8 @@ TARGET_NAME = ftp
TARGET_INSTALLDIR = system32
TARGET_CFLAGS = -D__USE_W32API
TARGET_SDKLIBS = ws2_32.a iphlpapi.a
# ntdll.a
+1 -1
View File
@@ -8,7 +8,7 @@ TARGET_NAME = ping
TARGET_INSTALLDIR = system32
TARGET_CFLAGS = -D__USE_W32_SOCKETS
TARGET_CFLAGS = -D__USE_W32API -D__USE_W32_SOCKETS
TARGET_SDKLIBS = ws2_32.a
+1
View File
@@ -1,5 +1,6 @@
<module name="ping" type="win32cui" installbase="system32" installname="ping.exe">
<include base="ping">.</include>
<define name="__USE_W32API" />
<define name="__USE_W32_SOCKETS" />
<define name="_WIN32_IE">0x600</define>
<define name="_WIN32_WINNT">0x501</define>
+1 -1
View File
@@ -12,7 +12,7 @@ TARGET_SDKLIBS = ws2_32.a iphlpapi.a ntdll.a
TARGET_OBJECTS = $(TARGET_NAME).o
TARGET_GCCLIBS =
TARGET_CFLAGS = -D__USE_W32API
include $(PATH_TO_TOP)/rules.mak
+1
View File
@@ -1,5 +1,6 @@
<module name="route" type="win32cui">
<include base="route">.</include>
<define name="__USE_W32API" />
<library>kernel32</library>
<library>ws2_32</library>
<library>iphlpapi</library>
+1 -1
View File
@@ -10,7 +10,7 @@ TARGET_APPTYPE = console
TARGET_NAME = partinfo
TARGET_CFLAGS = -Wall -Werror -Wno-format
TARGET_CFLAGS = -D__USE_W32API -Wall -Werror -Wno-format
TARGET_SDKLIBS = ntdll.a kernel32.a
+3 -1
View File
@@ -8,9 +8,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <ddk/ntddk.h>
//#define DUMP_DATA
#define DUMP_SIZE_INFO
#define UNICODE
#ifdef DUMP_DATA
void HexDump(char *buffer, ULONG size)
+1 -1
View File
@@ -10,7 +10,7 @@ TARGET_APPTYPE = console
TARGET_NAME = pnpdump
TARGET_CFLAGS = -Wall -Werror
TARGET_CFLAGS = -D__USE_W32API -Wall -Werror
TARGET_SDKLIBS = ntdll.a kernel32.a
+2
View File
@@ -8,6 +8,8 @@
#include <stdlib.h>
#include <conio.h>
#include <ddk/ntddk.h>
#include <pshpack1.h>
typedef struct _CM_PNP_BIOS_DEVICE_NODE
+1 -1
View File
@@ -10,7 +10,7 @@ TARGET_APPTYPE = console
TARGET_NAME = ps
TARGET_CFLAGS = -DANONYMOUSUNIONS -Werror -Wall
TARGET_CFLAGS = -D__USE_W32API -DANONYMOUSUNIONS -Werror -Wall
TARGET_SDKLIBS = ntdll.a kernel32.a user32.a
+1 -1
View File
@@ -13,7 +13,7 @@ TARGET_INSTALLDIR = system32
TARGET_NAME = sc
TARGET_CFLAGS = -DDBG -Werror -Wall
TARGET_CFLAGS = -D__USE_W32API -DDBG -Werror -Wall
TARGET_SDKLIBS = kernel32.a ntdll.a advapi32.a
+949
View File
@@ -0,0 +1,949 @@
/* include/config.h. Generated by configure. */
/* include/config.h.in. Generated from configure.ac by autoheader. */
#define __WINE_CONFIG_H
/* Specifies the compiler flag that forces a short wchar_t */
#define CC_FLAG_SHORT_WCHAR "-fshort-wchar"
/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
systems. This function is required for `alloca.c' support on those systems.
*/
/* #undef CRAY_STACKSEG_END */
/* Define to 1 if using `alloca.c'. */
/* #undef C_ALLOCA */
/* Define to 1 if you have `alloca', as a function or macro. */
#define HAVE_ALLOCA 1
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
/* #undef HAVE_ALLOCA_H */
/* Define if you have ALSA 1.x including devel headers */
/* #undef HAVE_ALSA */
/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
/* #undef HAVE_ALSA_ASOUNDLIB_H */
/* Define to 1 if you have the <arpa/inet.h> header file. */
/* #undef HAVE_ARPA_INET_H */
/* Define to 1 if you have the <arpa/nameser.h> header file. */
/* #undef HAVE_ARPA_NAMESER_H */
/* Define if you have ARTS sound server */
/* #undef HAVE_ARTS */
/* Define if the assembler keyword .size is accepted */
/* #undef HAVE_ASM_DOT_SIZE */
/* Define to 1 if you have the <audio/audiolib.h> header file. */
/* #undef HAVE_AUDIO_AUDIOLIB_H */
/* Define to 1 if you have the <audio/soundlib.h> header file. */
/* #undef HAVE_AUDIO_SOUNDLIB_H */
/* Define to 1 if you have the <capi20.h> header file. */
/* #undef HAVE_CAPI20_H */
/* Define if you have capi4linux libs and headers */
/* #undef HAVE_CAPI4LINUX */
/* Define to 1 if you have the `chsize' function. */
#define HAVE_CHSIZE 1
/* Define to 1 if you have the `clone' function. */
/* #undef HAVE_CLONE */
/* Define to 1 if you have the `connect' function. */
/* #undef HAVE_CONNECT */
/* Define if we have linux/input.h AND it contains the INPUT event API */
/* #undef HAVE_CORRECT_LINUXINPUT_H */
/* Define to 1 if you have the <cups/cups.h> header file. */
/* #undef HAVE_CUPS_CUPS_H */
/* Define to 1 if you have the <curses.h> header file. */
/* #undef HAVE_CURSES_H */
/* Define to 1 if you have the <direct.h> header file. */
#define HAVE_DIRECT_H 1
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define if you have dlopen */
/* #undef HAVE_DLOPEN */
/* Define to 1 if you have the <elf.h> header file. */
/* #undef HAVE_ELF_H */
/* Define to 1 if you have the `epoll_create' function. */
/* #undef HAVE_EPOLL_CREATE */
/* Define to 1 if you have the `ffs' function. */
/* #undef HAVE_FFS */
/* Define to 1 if you have the `finite' function. */
#define HAVE_FINITE 1
/* Define to 1 if you have the <float.h> header file. */
#define HAVE_FLOAT_H 1
/* Define to 1 if you have the <fontconfig/fontconfig.h> header file. */
/* #undef HAVE_FONTCONFIG_FONTCONFIG_H */
/* Define to 1 if you have the `fork' function. */
/* #undef HAVE_FORK */
/* Define to 1 if you have the `fpclass' function. */
#define HAVE_FPCLASS 1
/* Define if FreeType 2 is installed */
/* #undef HAVE_FREETYPE */
/* Define to 1 if you have the <freetype/freetype.h> header file. */
/* #undef HAVE_FREETYPE_FREETYPE_H */
/* Define to 1 if you have the <freetype/ftglyph.h> header file. */
/* #undef HAVE_FREETYPE_FTGLYPH_H */
/* Define to 1 if you have the <freetype/ftnames.h> header file. */
/* #undef HAVE_FREETYPE_FTNAMES_H */
/* Define to 1 if you have the <freetype/ftoutln.h> header file. */
/* #undef HAVE_FREETYPE_FTOUTLN_H */
/* Define to 1 if you have the <freetype/ftsnames.h> header file. */
/* #undef HAVE_FREETYPE_FTSNAMES_H */
/* Define if you have the <freetype/fttrigon.h> header file. */
/* #undef HAVE_FREETYPE_FTTRIGON_H */
/* Define to 1 if you have the <freetype/ftwinfnt.h> header file. */
/* #undef HAVE_FREETYPE_FTWINFNT_H */
/* Define to 1 if you have the <freetype/internal/sfnt.h> header file. */
/* #undef HAVE_FREETYPE_INTERNAL_SFNT_H */
/* Define to 1 if you have the <freetype/ttnameid.h> header file. */
/* #undef HAVE_FREETYPE_TTNAMEID_H */
/* Define to 1 if you have the <freetype/tttables.h> header file. */
/* #undef HAVE_FREETYPE_TTTABLES_H */
/* Define to 1 if the system has the type `fsblkcnt_t'. */
/* #undef HAVE_FSBLKCNT_T */
/* Define to 1 if the system has the type `fsfilcnt_t'. */
/* #undef HAVE_FSFILCNT_T */
/* Define to 1 if you have the `fstatfs' function. */
/* #undef HAVE_FSTATFS */
/* Define to 1 if you have the `fstatvfs' function. */
/* #undef HAVE_FSTATVFS */
/* Define to 1 if you have the <ft2build.h> header file. */
/* #undef HAVE_FT2BUILD_H */
/* Define to 1 if you have the `ftruncate' function. */
#define HAVE_FTRUNCATE 1
/* Define to 1 if you have the `futimes' function. */
/* #undef HAVE_FUTIMES */
/* Define to 1 if you have the `gethostbyname' function. */
/* #undef HAVE_GETHOSTBYNAME */
/* Define to 1 if you have the `getnetbyname' function. */
/* #undef HAVE_GETNETBYNAME */
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getopt_long' function. */
#define HAVE_GETOPT_LONG 1
/* Define to 1 if you have the `getpagesize' function. */
#define HAVE_GETPAGESIZE 1
/* Define to 1 if you have the `getprotobyname' function. */
/* #undef HAVE_GETPROTOBYNAME */
/* Define to 1 if you have the `getprotobynumber' function. */
/* #undef HAVE_GETPROTOBYNUMBER */
/* Define to 1 if you have the `getpwuid' function. */
/* #undef HAVE_GETPWUID */
/* Define to 1 if you have the `getservbyport' function. */
/* #undef HAVE_GETSERVBYPORT */
/* Define to 1 if you have the `gettid' function. */
/* #undef HAVE_GETTID */
/* Define to 1 if you have the `gettimeofday' function. */
/* #undef HAVE_GETTIMEOFDAY */
/* Define to 1 if you have the `getuid' function. */
/* #undef HAVE_GETUID */
/* Define to 1 if you have the <gif_lib.h> header file. */
/* #undef HAVE_GIF_LIB_H */
/* Define to 1 if you have the <GL/glext.h> header file. */
/* #undef HAVE_GL_GLEXT_H */
/* Define to 1 if you have the <GL/glx.h> header file. */
/* #undef HAVE_GL_GLX_H */
/* Define to 1 if you have the <GL/gl.h> header file. */
/* #undef HAVE_GL_GL_H */
/* Define to 1 if the ICU libraries are installed */
/* #undef HAVE_ICU */
/* Define to 1 if you have the <ieeefp.h> header file. */
/* #undef HAVE_IEEEFP_H */
/* Define to 1 if you have the `inet_aton' function. */
/* #undef HAVE_INET_ATON */
/* Define to 1 if you have the `inet_network' function. */
/* #undef HAVE_INET_NETWORK */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <io.h> header file. */
#define HAVE_IO_H 1
/* Define if IPX should use netipx/ipx.h from libc */
/* #undef HAVE_IPX_GNU */
/* Define if IPX includes are taken from Linux kernel */
/* #undef HAVE_IPX_LINUX */
/* Define to 1 if you have the `iswalnum' function. */
#define HAVE_ISWALNUM 1
/* Define to 1 if you have the <jack/jack.h> header file. */
/* #undef HAVE_JACK_JACK_H */
/* Define to 1 if you have the <jpeglib.h> header file. */
/* #undef HAVE_JPEGLIB_H */
/* Define to 1 if you have the <lcms.h> header file. */
/* #undef HAVE_LCMS_H */
/* Define to 1 if you have the <lcms/lcms.h> header file. */
/* #undef HAVE_LCMS_LCMS_H */
/* Define if you have libaudioIO */
/* #undef HAVE_LIBAUDIOIO */
/* Define to 1 if you have the <libaudioio.h> header file. */
/* #undef HAVE_LIBAUDIOIO_H */
/* Define if you have the curses library (-lcurses) */
/* #undef HAVE_LIBCURSES */
/* Define to 1 if you have the `i386' library (-li386). */
/* #undef HAVE_LIBI386 */
/* Define if you have the ncurses library (-lncurses) */
/* #undef HAVE_LIBNCURSES */
/* Define to 1 if you have the `nsl' library (-lnsl). */
/* #undef HAVE_LIBNSL */
/* Define to 1 if you have the `ossaudio' library (-lossaudio). */
/* #undef HAVE_LIBOSSAUDIO */
/* Define to 1 if you have the `poll' library (-lpoll). */
/* #undef HAVE_LIBPOLL */
/* Define to 1 if you have the `resolv' library (-lresolv). */
/* #undef HAVE_LIBRESOLV */
/* Define to 1 if you have the `socket' library (-lsocket). */
/* #undef HAVE_LIBSOCKET */
/* Define to 1 if you have the `w' library (-lw). */
/* #undef HAVE_LIBW */
/* Define to 1 if you have the `xpg4' library (-lxpg4). */
/* #undef HAVE_LIBXPG4 */
/* Define if you have the Xrandr library */
/* #undef HAVE_LIBXRANDR */
/* Define if you have the X Shape extension */
/* #undef HAVE_LIBXSHAPE */
/* Define if you have the Xxf86dga library version 2 */
/* #undef HAVE_LIBXXF86DGA2 */
/* Define if you have the Xxf86vm library */
/* #undef HAVE_LIBXXF86VM */
/* Define if you have the X Shm extension */
/* #undef HAVE_LIBXXSHM */
/* Define to 1 if you have the <link.h> header file. */
/* #undef HAVE_LINK_H */
/* Define if <linux/joystick.h> defines the Linux 2.2 joystick API */
/* #undef HAVE_LINUX_22_JOYSTICK_API */
/* Define to 1 if you have the <linux/capi.h> header file. */
/* #undef HAVE_LINUX_CAPI_H */
/* Define to 1 if you have the <linux/cdrom.h> header file. */
/* #undef HAVE_LINUX_CDROM_H */
/* Define to 1 if you have the <linux/compiler.h> header file. */
/* #undef HAVE_LINUX_COMPILER_H */
/* Define if Linux-style gethostbyname_r and gethostbyaddr_r are available */
/* #undef HAVE_LINUX_GETHOSTBYNAME_R_6 */
/* Define to 1 if you have the <linux/hdreg.h> header file. */
/* #undef HAVE_LINUX_HDREG_H */
/* Define to 1 if you have the <linux/input.h> header file. */
/* #undef HAVE_LINUX_INPUT_H */
/* Define to 1 if you have the <linux/ioctl.h> header file. */
/* #undef HAVE_LINUX_IOCTL_H */
/* Define to 1 if you have the <linux/joystick.h> header file. */
/* #undef HAVE_LINUX_JOYSTICK_H */
/* Define to 1 if you have the <linux/major.h> header file. */
/* #undef HAVE_LINUX_MAJOR_H */
/* Define to 1 if you have the <linux/param.h> header file. */
/* #undef HAVE_LINUX_PARAM_H */
/* Define to 1 if you have the <linux/serial.h> header file. */
/* #undef HAVE_LINUX_SERIAL_H */
/* Define to 1 if you have the <linux/ucdrom.h> header file. */
/* #undef HAVE_LINUX_UCDROM_H */
/* Define to 1 if the system has the type `long long'. */
#define HAVE_LONG_LONG 1
/* Define to 1 if you have the `lstat' function. */
/* #undef HAVE_LSTAT */
/* Define to 1 if you have the <machine/cpu.h> header file. */
/* #undef HAVE_MACHINE_CPU_H */
/* Define to 1 if you have the <machine/soundcard.h> header file. */
/* #undef HAVE_MACHINE_SOUNDCARD_H */
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mmap' function. */
/* #undef HAVE_MMAP */
/* Define to 1 if you have the <mntent.h> header file. */
/* #undef HAVE_MNTENT_H */
/* Define to 1 if the system has the type `mode_t'. */
#define HAVE_MODE_T 1
/* Define if you have NAS including devel headers */
/* #undef HAVE_NAS */
/* Define to 1 if you have the <ncurses.h> header file. */
/* #undef HAVE_NCURSES_H */
/* Define to 1 if you have the <netdb.h> header file. */
/* #undef HAVE_NETDB_H */
/* Define to 1 if you have the <netinet/in.h> header file. */
/* #undef HAVE_NETINET_IN_H */
/* Define to 1 if you have the <netinet/in_systm.h> header file. */
/* #undef HAVE_NETINET_IN_SYSTM_H */
/* Define to 1 if you have the <netinet/tcp_fsm.h> header file. */
/* #undef HAVE_NETINET_TCP_FSM_H */
/* Define to 1 if you have the <netinet/tcp.h> header file. */
/* #undef HAVE_NETINET_TCP_H */
/* Define to 1 if you have the <net/if_arp.h> header file. */
/* #undef HAVE_NET_IF_ARP_H */
/* Define to 1 if you have the <net/if_dl.h> header file. */
/* #undef HAVE_NET_IF_DL_H */
/* Define to 1 if you have the <net/if.h> header file. */
/* #undef HAVE_NET_IF_H */
/* Define to 1 if you have the <net/if_types.h> header file. */
/* #undef HAVE_NET_IF_TYPES_H */
/* Define to 1 if you have the <net/route.h> header file. */
/* #undef HAVE_NET_ROUTE_H */
/* Define to 1 if the system has the type `off_t'. */
#define HAVE_OFF_T 1
/* Define if OpenGL is present on the system */
/* #undef HAVE_OPENGL */
/* Define to 1 if you have the <openssl/ssl.h> header file. */
/* #undef HAVE_OPENSSL_SSL_H */
/* Define if you have the Open Sound system */
/* #undef HAVE_OSS */
/* Define if you have the Open Sound system (MIDI interface) */
/* #undef HAVE_OSS_MIDI */
/* Define to 1 if you have the `pclose' function. */
#define HAVE_PCLOSE 1
/* Define to 1 if the system has the type `pid_t'. */
#define HAVE_PID_T 1
/* Define to 1 if you have the `popen' function. */
#define HAVE_POPEN 1
/* Define if we can use ppdev.h for parallel port access */
/* #undef HAVE_PPDEV */
/* Define to 1 if you have the `pread' function. */
/* #undef HAVE_PREAD */
/* Define to 1 if you have the <process.h> header file. */
#define HAVE_PROCESS_H 1
/* Define to 1 if you have the `pthread_getattr_np' function. */
/* #undef HAVE_PTHREAD_GETATTR_NP */
/* Define to 1 if you have the `pthread_get_stackaddr_np' function. */
/* #undef HAVE_PTHREAD_GET_STACKADDR_NP */
/* Define to 1 if you have the `pthread_get_stacksize_np' function. */
/* #undef HAVE_PTHREAD_GET_STACKSIZE_NP */
/* Define to 1 if you have the <pthread.h> header file. */
/* #undef HAVE_PTHREAD_H */
/* Define to 1 if the system has the type `pthread_rwlockattr_t'. */
/* #undef HAVE_PTHREAD_RWLOCKATTR_T */
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
/* #undef HAVE_PTHREAD_RWLOCK_T */
/* Define to 1 if you have the <pwd.h> header file. */
/* #undef HAVE_PWD_H */
/* Define to 1 if you have the `pwrite' function. */
/* #undef HAVE_PWRITE */
/* Define to 1 if you have the `readlink' function. */
/* #undef HAVE_READLINK */
/* Define to 1 if you have the <regex.h> header file. */
/* #undef HAVE_REGEX_H */
/* Define to 1 if you have the <resolv.h> header file. */
/* #undef HAVE_RESOLV_H */
/* Define to 1 if you have the `rfork' function. */
/* #undef HAVE_RFORK */
/* Define if we have SANE development environment */
/* #undef HAVE_SANE */
/* Define to 1 if you have the <sched.h> header file. */
/* #undef HAVE_SCHED_H */
/* Define to 1 if you have the `sched_yield' function. */
/* #undef HAVE_SCHED_YIELD */
/* Define to 1 if you have the <scsi/scsi.h> header file. */
/* #undef HAVE_SCSI_SCSI_H */
/* Define to 1 if you have the <scsi/scsi_ioctl.h> header file. */
/* #undef HAVE_SCSI_SCSI_IOCTL_H */
/* Define to 1 if you have the <scsi/sg.h> header file. */
/* #undef HAVE_SCSI_SG_H */
/* Define to 1 if you have the `select' function. */
/* #undef HAVE_SELECT */
/* Define to 1 if you have the `sendmsg' function. */
/* #undef HAVE_SENDMSG */
/* Define to 1 if you have the `settimeofday' function. */
/* #undef HAVE_SETTIMEOFDAY */
/* Define if sigaddset is supported */
/* #undef HAVE_SIGADDSET */
/* Define to 1 if you have the `sigaltstack' function. */
/* #undef HAVE_SIGALTSTACK */
/* Define to 1 if `si_fd' is member of `siginfo_t'. */
/* #undef HAVE_SIGINFO_T_SI_FD */
/* Define to 1 if you have the `sigprocmask' function. */
/* #undef HAVE_SIGPROCMASK */
/* Define to 1 if you have the sigsetjmp (and siglongjmp) function */
/* #undef HAVE_SIGSETJMP */
/* Define to 1 if the system has the type `sigset_t'. */
/* #undef HAVE_SIGSET_T */
/* Define to 1 if the system has the type `size_t'. */
#define HAVE_SIZE_T 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the <soundcard.h> header file. */
/* #undef HAVE_SOUNDCARD_H */
/* Define to 1 if you have the `spawnvp' function. */
#define HAVE_SPAWNVP 1
/* Define to 1 if the system has the type `ssize_t'. */
#define HAVE_SSIZE_T 1
/* Define to 1 if you have the `statfs' function. */
/* #undef HAVE_STATFS */
/* Define to 1 if you have the `statvfs' function. */
/* #undef HAVE_STATVFS */
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the `strcasecmp' function. */
#define HAVE_STRCASECMP 1
/* Define to 1 if you have the `strerror' function. */
#define HAVE_STRERROR 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the `strncasecmp' function. */
#define HAVE_STRNCASECMP 1
/* Define to 1 if `msg_accrights' is member of `struct msghdr'. */
/* #undef HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS */
/* Define to 1 if `name' is member of `struct option'. */
#define HAVE_STRUCT_OPTION_NAME 1
/* Define to 1 if `sa_len' is member of `struct sockaddr'. */
/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */
/* Define to 1 if `sun_len' is member of `struct sockaddr_un'. */
/* #undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
/* Define to 1 if `f_bavail' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_BAVAIL */
/* Define to 1 if `f_bfree' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_BFREE */
/* Define to 1 if `f_favail' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_FAVAIL */
/* Define to 1 if `f_ffree' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_FFREE */
/* Define to 1 if `f_frsize' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_FRSIZE */
/* Define to 1 if `f_namelen' is member of `struct statfs'. */
/* #undef HAVE_STRUCT_STATFS_F_NAMELEN */
/* Define to 1 if `f_blocks' is member of `struct statvfs'. */
/* #undef HAVE_STRUCT_STATVFS_F_BLOCKS */
/* Define to 1 if `st_blocks' is member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_BLOCKS */
/* Define to 1 if you have the <syscall.h> header file. */
/* #undef HAVE_SYSCALL_H */
/* Define to 1 if you have the <sys/asoundlib.h> header file. */
/* #undef HAVE_SYS_ASOUNDLIB_H */
/* Define to 1 if you have the <sys/cdio.h> header file. */
/* #undef HAVE_SYS_CDIO_H */
/* Define to 1 if you have the <sys/elf32.h> header file. */
/* #undef HAVE_SYS_ELF32_H */
/* Define to 1 if you have the <sys/epoll.h> header file. */
/* #undef HAVE_SYS_EPOLL_H */
/* Define to 1 if you have the <sys/errno.h> header file. */
/* #undef HAVE_SYS_ERRNO_H */
/* Define to 1 if you have the <sys/exec_elf.h> header file. */
/* #undef HAVE_SYS_EXEC_ELF_H */
/* Define to 1 if you have the <sys/filio.h> header file. */
/* #undef HAVE_SYS_FILIO_H */
/* Define to 1 if you have the <sys/ioctl.h> header file. */
/* #undef HAVE_SYS_IOCTL_H */
/* Define to 1 if you have the <sys/ipc.h> header file. */
/* #undef HAVE_SYS_IPC_H */
/* Define to 1 if you have the <sys/link.h> header file. */
/* #undef HAVE_SYS_LINK_H */
/* Define to 1 if you have the <sys/lwp.h> header file. */
/* #undef HAVE_SYS_LWP_H */
/* Define to 1 if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H */
/* Define to 1 if you have the <sys/modem.h> header file. */
/* #undef HAVE_SYS_MODEM_H */
/* Define to 1 if you have the <sys/mount.h> header file. */
/* #undef HAVE_SYS_MOUNT_H */
/* Define to 1 if you have the <sys/msg.h> header file. */
/* #undef HAVE_SYS_MSG_H */
/* Define to 1 if you have the <sys/param.h> header file. */
#define HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/poll.h> header file. */
/* #undef HAVE_SYS_POLL_H */
/* Define to 1 if you have the <sys/ptrace.h> header file. */
/* #undef HAVE_SYS_PTRACE_H */
/* Define to 1 if you have the <sys/reg.h> header file. */
/* #undef HAVE_SYS_REG_H */
/* Define to 1 if you have the <sys/scsiio.h> header file. */
/* #undef HAVE_SYS_SCSIIO_H */
/* Define to 1 if you have the <sys/shm.h> header file. */
/* #undef HAVE_SYS_SHM_H */
/* Define to 1 if you have the <sys/signal.h> header file. */
/* #undef HAVE_SYS_SIGNAL_H */
/* Define to 1 if you have the <sys/socket.h> header file. */
/* #undef HAVE_SYS_SOCKET_H */
/* Define to 1 if you have the <sys/sockio.h> header file. */
/* #undef HAVE_SYS_SOCKIO_H */
/* Define to 1 if you have the <sys/soundcard.h> header file. */
/* #undef HAVE_SYS_SOUNDCARD_H */
/* Define to 1 if you have the <sys/statfs.h> header file. */
/* #undef HAVE_SYS_STATFS_H */
/* Define to 1 if you have the <sys/statvfs.h> header file. */
/* #undef HAVE_SYS_STATVFS_H */
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/strtio.h> header file. */
/* #undef HAVE_SYS_STRTIO_H */
/* Define to 1 if you have the <sys/syscall.h> header file. */
/* #undef HAVE_SYS_SYSCALL_H */
/* Define to 1 if you have the <sys/sysctl.h> header file. */
/* #undef HAVE_SYS_SYSCTL_H */
/* Define to 1 if you have the <sys/times.h> header file. */
/* #undef HAVE_SYS_TIMES_H */
/* Define to 1 if you have the <sys/time.h> header file. */
#define HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/uio.h> header file. */
/* #undef HAVE_SYS_UIO_H */
/* Define to 1 if you have the <sys/un.h> header file. */
/* #undef HAVE_SYS_UN_H */
/* Define to 1 if you have the <sys/user.h> header file. */
/* #undef HAVE_SYS_USER_H */
/* Define to 1 if you have the <sys/vfs.h> header file. */
/* #undef HAVE_SYS_VFS_H */
/* Define to 1 if you have the <sys/vm86.h> header file. */
/* #undef HAVE_SYS_VM86_H */
/* Define to 1 if you have the <sys/wait.h> header file. */
/* #undef HAVE_SYS_WAIT_H */
/* Define to 1 if you have the `tcgetattr' function. */
/* #undef HAVE_TCGETATTR */
/* Define to 1 if you have the <termios.h> header file. */
/* #undef HAVE_TERMIOS_H */
/* Define to 1 if you have the `timegm' function. */
/* #undef HAVE_TIMEGM */
/* Define to 1 if you have the <ucontext.h> header file. */
/* #undef HAVE_UCONTEXT_H */
/* Define to 1 if you have the <unicode/ubidi.h> header file. */
/* #undef HAVE_UNICODE_UBIDI_H */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have the `usleep' function. */
/* #undef HAVE_USLEEP */
/* Define to 1 if you have the <utime.h> header file. */
#define HAVE_UTIME_H 1
/* Define to 1 if you have the <valgrind/memcheck.h> header file. */
/* #undef HAVE_VALGRIND_MEMCHECK_H */
/* Define if we have va_copy */
#define HAVE_VA_COPY 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define to 1 if you have the `wait4' function. */
/* #undef HAVE_WAIT4 */
/* Define to 1 if you have the `waitpid' function. */
/* #undef HAVE_WAITPID */
/* Define to 1 if you have the <X11/extensions/shape.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_SHAPE_H */
/* Define to 1 if you have the <X11/extensions/xf86dga.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XF86DGA_H */
/* Define to 1 if you have the <X11/extensions/xf86vmode.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XF86VMODE_H */
/* Define to 1 if you have the <X11/extensions/XInput.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XINPUT_H */
/* Define to 1 if you have the <X11/extensions/Xrandr.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XRANDR_H */
/* Define to 1 if you have the <X11/extensions/Xrender.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XRENDER_H */
/* Define to 1 if you have the <X11/extensions/XShm.h> header file. */
/* #undef HAVE_X11_EXTENSIONS_XSHM_H */
/* Define to 1 if you have the <X11/XKBlib.h> header file. */
/* #undef HAVE_X11_XKBLIB_H */
/* Define to 1 if you have the <X11/Xlib.h> header file. */
/* #undef HAVE_X11_XLIB_H */
/* Define to 1 if you have the <X11/Xutil.h> header file. */
/* #undef HAVE_X11_XUTIL_H */
/* Define if you have the XKB extension */
/* #undef HAVE_XKB */
/* Define if Xrender has the XRenderSetPictureTransform function */
/* #undef HAVE_XRENDERSETPICTURETRANSFORM */
/* Define to 1 if you have the `_lwp_create' function. */
/* #undef HAVE__LWP_CREATE */
/* Define to 1 if you have the `_lwp_self' function. */
/* #undef HAVE__LWP_SELF */
/* Define to 1 if you have the `_pclose' function. */
#define HAVE__PCLOSE 1
/* Define to 1 if you have the `_popen' function. */
#define HAVE__POPEN 1
/* Define to 1 if you have the `_snprintf' function. */
#define HAVE__SNPRINTF 1
/* Define to 1 if you have the `_spawnvp' function. */
#define HAVE__SPAWNVP 1
/* Define to 1 if you have the `_stricmp' function. */
#define HAVE__STRICMP 1
/* Define to 1 if you have the `_strnicmp' function. */
#define HAVE__STRNICMP 1
/* Define to 1 if you have the `_vsnprintf' function. */
#define HAVE__VSNPRINTF 1
/* Define if we have __va_copy */
#define HAVE___VA_COPY 1
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "[email protected]"
/* Define to the full name of this package. */
#define PACKAGE_NAME "Wine"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "Wine 20050211"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "wine"
/* Define to the version of this package. */
#define PACKAGE_VERSION "20050211"
/* Define to the soname of the libcapi20 library. */
/* #undef SONAME_LIBCAPI20 */
/* Define to the soname of the libcrypto library. */
/* #undef SONAME_LIBCRYPTO */
/* Define to the soname of the libcups library. */
/* #undef SONAME_LIBCUPS */
/* Define to the soname of the libcurses library. */
/* #undef SONAME_LIBCURSES */
/* Define to the soname of the libfontconfig library. */
/* #undef SONAME_LIBFONTCONFIG */
/* Define to the soname of the libfreetype library. */
/* #undef SONAME_LIBFREETYPE */
/* Define to the soname of the libgif library. */
/* #undef SONAME_LIBGIF */
/* Define to the soname of the libGL library. */
/* #undef SONAME_LIBGL */
/* Define to the soname of the libjack library. */
/* #undef SONAME_LIBJACK */
/* Define to the soname of the libjpeg library. */
/* #undef SONAME_LIBJPEG */
/* Define to the soname of the liblcms library. */
/* #undef SONAME_LIBLCMS */
/* Define to the soname of the libncurses library. */
/* #undef SONAME_LIBNCURSES */
/* Define to the soname of the libssl library. */
/* #undef SONAME_LIBSSL */
/* Define to the soname of the libtxc_dxtn library. */
/* #undef SONAME_LIBTXC_DXTN */
/* Define to the soname of the libungif library. */
/* #undef SONAME_LIBUNGIF */
/* Define to the soname of the libX11 library. */
/* #undef SONAME_LIBX11 */
/* Define to the soname of the libXext library. */
/* #undef SONAME_LIBXEXT */
/* Define to the soname of the libXi library. */
/* #undef SONAME_LIBXI */
/* Define to the soname of the libXrandr library. */
/* #undef SONAME_LIBXRANDR */
/* Define to the soname of the libXrender library. */
/* #undef SONAME_LIBXRENDER */
/* If using the C implementation of alloca, define if you know the
direction of stack growth for your system; otherwise it will be
automatically deduced at run-time.
STACK_DIRECTION > 0 => grows toward higher addresses
STACK_DIRECTION < 0 => grows toward lower addresses
STACK_DIRECTION = 0 => direction of growth unknown */
/* #undef STACK_DIRECTION */
/* Define if the struct statfs is defined by <sys/mount.h> */
/* #undef STATFS_DEFINED_BY_SYS_MOUNT */
/* Define if the struct statfs is defined by <sys/statfs.h> */
/* #undef STATFS_DEFINED_BY_SYS_STATFS */
/* Define if the struct statfs is defined by <sys/vfs.h> */
/* #undef STATFS_DEFINED_BY_SYS_VFS */
/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */
/* #undef STAT_MACROS_BROKEN */
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if the X Window System is missing or not being used. */
#define X_DISPLAY_MISSING 1
/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
`char[]'. */
#define YYTEXT_POINTER 1
/* Set this to 64 to enable 64-bit file support on Linux */
/* #undef _FILE_OFFSET_BITS */
/* Define to a macro to generate an assembly function directive */
#define __ASM_FUNC(name) ".def " __ASM_NAME(name) "; .scl 2; .type 32; .endef"
/* Define to a macro to generate an assembly name from a C symbol */
#define __ASM_NAME(name) "_" name
/* Define to the assembler keyword used to specify a word value */
#define __ASM_SHORT ".short"
/* Define to the assembler keyword used to specify an ASCII string */
#define __ASM_STRING ".string"
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
@@ -1,27 +1,25 @@
/* Definitions for the VERsion infolibrary (VER.DLL)
*
* Copyright 1996 Marcus Meissner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Marked as obsolete: Albert den Haan (Corel Corp) 1999-04-28
* VER.H obsolete, include winver.h instead
*/
#ifndef __WINE_VER_H
#define __WINE_VER_H
#include <winver.h>
#endif /* __WINE_VER_H */
/*
* Resources for the binary we distribute to testers
*
* Copyright 2004 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "winetest.rc"
WINE_BUILD STRINGRES "build.id"
BUILD_INFO STRINGRES "build.nfo"
TESTS_URL STRINGRES "tests.url"
+473
View File
@@ -0,0 +1,473 @@
/*
* GUI support
*
* Copyright 2004 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <windows.h>
#include <commctrl.h>
#include "resource.h"
#include "winetest.h"
/* Event object to signal successful window creation to main thread.
*/
HANDLE initEvent;
/* Dialog handle
*/
HWND dialog;
/* Progress data for the text* functions and for scaling.
*/
unsigned int progressMax, progressCurr;
double progressScale;
/* Progress group counter for the gui* functions.
*/
int progressGroup;
char *
renderString (va_list ap)
{
const char *fmt = va_arg (ap, char*);
static char buffer[128];
vsnprintf (buffer, sizeof buffer, fmt, ap);
return buffer;
}
int
MBdefault (int uType)
{
static const int matrix[][4] = {{IDOK, 0, 0, 0},
{IDOK, IDCANCEL, 0, 0},
{IDABORT, IDRETRY, IDIGNORE, 0},
{IDYES, IDNO, IDCANCEL, 0},
{IDYES, IDNO, 0, 0},
{IDRETRY, IDCANCEL, 0, 0}};
int type = uType & MB_TYPEMASK;
int def = (uType & MB_DEFMASK) / MB_DEFBUTTON2;
return matrix[type][def];
}
/* report (R_STATUS, fmt, ...) */
int
textStatus (va_list ap)
{
char *str = vstrmake (NULL, ap);
fputs (str, stderr);
fputc ('\n', stderr);
free (str);
return 0;
}
int
guiStatus (va_list ap)
{
size_t len;
char *str = vstrmake (&len, ap);
if (len > 128) str[129] = 0;
SetDlgItemText (dialog, IDC_SB, str);
free (str);
return 0;
}
/* report (R_PROGRESS, barnum, steps) */
int
textProgress (va_list ap)
{
progressGroup = va_arg (ap, int);
progressMax = va_arg (ap, int);
progressCurr = 0;
return 0;
}
int
guiProgress (va_list ap)
{
unsigned int max;
HWND pb;
progressGroup = va_arg (ap, int);
progressMax = max = va_arg (ap, int);
progressCurr = 0;
if (max > 0xffff) {
progressScale = (double)0xffff / max;
max = 0xffff;
}
else progressScale = 1;
pb = GetDlgItem (dialog, IDC_PB0 + progressGroup * 2);
SendMessage (pb, PBM_SETRANGE, 0, MAKELPARAM (0, max));
SendMessage (pb, PBM_SETSTEP, (WPARAM)1, 0);
return 0;
}
/* report (R_STEP, fmt, ...) */
int
textStep (va_list ap)
{
char *str = vstrmake (NULL, ap);
progressCurr++;
fputs (str, stderr);
fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
free (str);
return 0;
}
int
guiStep (va_list ap)
{
const int pgID = IDC_ST0 + progressGroup * 2;
char *str = vstrmake (NULL, ap);
progressCurr++;
SetDlgItemText (dialog, pgID, str);
SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
(WPARAM)(progressScale * progressCurr), 0);
free (str);
return 0;
}
/* report (R_DELTA, inc, fmt, ...) */
int
textDelta (va_list ap)
{
const int inc = va_arg (ap, int);
char *str = vstrmake (NULL, ap);
progressCurr += inc;
fputs (str, stderr);
fprintf (stderr, " (%d of %d)\n", progressCurr, progressMax);
free (str);
return 0;
}
int
guiDelta (va_list ap)
{
const int inc = va_arg (ap, int);
const int pgID = IDC_ST0 + progressGroup * 2;
char *str = vstrmake (NULL, ap);
progressCurr += inc;
SetDlgItemText (dialog, pgID, str);
SendDlgItemMessage (dialog, pgID+1, PBM_SETPOS,
(WPARAM)(progressScale * progressCurr), 0);
free (str);
return 0;
}
/* report (R_DIR, fmt, ...) */
int
textDir (va_list ap)
{
char *str = vstrmake (NULL, ap);
fputs ("Temporary directory: ", stderr);
fputs (str, stderr);
fputc ('\n', stderr);
free (str);
return 0;
}
int
guiDir (va_list ap)
{
char *str = vstrmake (NULL, ap);
SetDlgItemText (dialog, IDC_DIR, str);
free (str);
return 0;
}
/* report (R_OUT, fmt, ...) */
int
textOut (va_list ap)
{
char *str = vstrmake (NULL, ap);
fputs ("Log file: ", stderr);
fputs (str, stderr);
fputc ('\n', stderr);
free (str);
return 0;
}
int
guiOut (va_list ap)
{
char *str = vstrmake (NULL, ap);
SetDlgItemText (dialog, IDC_OUT, str);
free (str);
return 0;
}
/* report (R_WARNING, fmt, ...) */
int
textWarning (va_list ap)
{
fputs ("Warning: ", stderr);
textStatus (ap);
return 0;
}
int
guiWarning (va_list ap)
{
char *str = vstrmake (NULL, ap);
MessageBox (dialog, str, "Warning", MB_ICONWARNING | MB_OK);
free (str);
return 0;
}
/* report (R_ERROR, fmt, ...) */
int
textError (va_list ap)
{
fputs ("Error: ", stderr);
textStatus (ap);
return 0;
}
int
guiError (va_list ap)
{
char *str = vstrmake (NULL, ap);
MessageBox (dialog, str, "Error", MB_ICONERROR | MB_OK);
free (str);
return 0;
}
/* report (R_FATAL, fmt, ...) */
int
textFatal (va_list ap)
{
textError (ap);
exit (1);
}
int
guiFatal (va_list ap)
{
guiError (ap);
exit (1);
}
/* report (R_ASK, type, fmt, ...) */
int
textAsk (va_list ap)
{
int uType = va_arg (ap, int);
int ret = MBdefault (uType);
char *str = vstrmake (NULL, ap);
fprintf (stderr, "Question of type %d: %s\n"
"Returning default: %d\n", uType, str, ret);
free (str);
return ret;
}
int
guiAsk (va_list ap)
{
int uType = va_arg (ap, int);
char *str = vstrmake (NULL, ap);
int ret = MessageBox (dialog, str, "Question",
MB_ICONQUESTION | uType);
free (str);
return ret;
}
/* Quiet functions */
int
qNoOp (va_list ap)
{
return 0;
}
int
qFatal (va_list ap)
{
exit (1);
}
int
qAsk (va_list ap)
{
return MBdefault (va_arg (ap, int));
}
BOOL CALLBACK
AboutProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDCANCEL:
EndDialog (hwnd, IDCANCEL);
return TRUE;
}
}
return FALSE;
}
BOOL CALLBACK
DlgProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG:
SendMessage (hwnd, WM_SETICON, ICON_SMALL,
(LPARAM)LoadIcon (GetModuleHandle (NULL),
MAKEINTRESOURCE (IDI_WINE)));
SendMessage (hwnd, WM_SETICON, ICON_BIG,
(LPARAM)LoadIcon (GetModuleHandle (NULL),
MAKEINTRESOURCE (IDI_WINE)));
dialog = hwnd;
if (!SetEvent (initEvent)) {
report (R_STATUS, "Can't signal main thread: %d",
GetLastError ());
EndDialog (hwnd, 2);
}
return TRUE;
case WM_CLOSE:
EndDialog (hwnd, 3);
return TRUE;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDHELP:
DialogBox (GetModuleHandle (NULL),
MAKEINTRESOURCE (IDD_ABOUT), hwnd, AboutProc);
return TRUE;
case IDABORT:
report (R_WARNING, "Not implemented");
return TRUE;
}
}
return FALSE;
}
DWORD WINAPI
DlgThreadProc ()
{
int ret;
InitCommonControls ();
ret = DialogBox (GetModuleHandle (NULL),
MAKEINTRESOURCE (IDD_STATUS),
NULL, DlgProc);
switch (ret) {
case 0:
report (R_WARNING, "Invalid parent handle");
break;
case 1:
report (R_WARNING, "DialogBox failed: %d",
GetLastError ());
break;
case 3:
exit (0);
default:
report (R_STATUS, "Dialog exited: %d", ret);
}
return 0;
}
int
report (enum report_type t, ...)
{
typedef int r_fun_t (va_list);
va_list ap;
int ret = 0;
static r_fun_t * const text_funcs[] =
{textStatus, textProgress, textStep, textDelta,
textDir, textOut,
textWarning, textError, textFatal, textAsk};
static r_fun_t * const GUI_funcs[] =
{guiStatus, guiProgress, guiStep, guiDelta,
guiDir, guiOut,
guiWarning, guiError, guiFatal, guiAsk};
static r_fun_t * const quiet_funcs[] =
{qNoOp, qNoOp, qNoOp, qNoOp,
qNoOp, qNoOp,
qNoOp, qNoOp, qFatal, qAsk};
static r_fun_t * const * funcs = NULL;
switch (t) {
case R_TEXTMODE:
funcs = text_funcs;
return 0;
case R_QUIET:
funcs = quiet_funcs;
return 0;
default:
break;
}
if (!funcs) {
HANDLE DlgThread;
DWORD DlgThreadID;
funcs = text_funcs;
initEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (!initEvent)
report (R_STATUS, "Can't create event object: %d",
GetLastError ());
else {
DlgThread = CreateThread (NULL, 0, DlgThreadProc,
NULL, 0, &DlgThreadID);
if (!DlgThread)
report (R_STATUS, "Can't create GUI thread: %d",
GetLastError ());
else {
DWORD ret = WaitForSingleObject (initEvent, INFINITE);
switch (ret) {
case WAIT_OBJECT_0:
funcs = GUI_funcs;
break;
case WAIT_TIMEOUT:
report (R_STATUS, "GUI creation timed out");
break;
case WAIT_FAILED:
report (R_STATUS, "Wait for GUI failed: %d",
GetLastError ());
break;
default:
report (R_STATUS, "Wait returned %d",
ret);
break;
}
}
}
}
va_start (ap, t);
if (t < sizeof text_funcs / sizeof text_funcs[0] &&
t < sizeof GUI_funcs / sizeof GUI_funcs[0] &&
t >= 0) ret = funcs[t](ap);
else report (R_WARNING, "unimplemented report type: %d", t);
va_end (ap);
return ret;
}
+621
View File
@@ -0,0 +1,621 @@
/*
* Wine Conformance Test EXE
*
* Copyright 2003, 2004 Jakob Eriksson (for Solid Form Sweden AB)
* Copyright 2003 Dimitrie O. Paun
* Copyright 2003 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* This program is dedicated to Anna Lindh,
* Swedish Minister of Foreign Affairs.
* Anna was murdered September 11, 2003.
*
*/
#include "config.h"
#include "wine/port.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <windows.h>
#include "winetest.h"
#include "resource.h"
struct wine_test
{
char *name;
int resource;
int subtest_count;
char **subtests;
char *exename;
};
struct rev_info
{
const char* file;
const char* rev;
};
static struct wine_test *wine_tests;
static struct rev_info *rev_infos = NULL;
static const char whitespace[] = " \t\r\n";
static int running_under_wine ()
{
HMODULE module = GetModuleHandleA("ntdll.dll");
if (!module) return 0;
return (GetProcAddress(module, "wine_server_call") != NULL);
}
static int running_on_visible_desktop ()
{
FARPROC pGetProcessWindowStation = GetProcAddress(GetModuleHandle("user32.dll"), "GetProcessWindowStation");
if (pGetProcessWindowStation)
{
DWORD len;
HWINSTA wstation;
USEROBJECTFLAGS uoflags;
FARPROC pGetUserObjectInformationA = GetProcAddress(GetModuleHandle("user32.dll"), "GetUserObjectInformationA");
wstation = (HWINSTA)pGetProcessWindowStation();
assert(pGetUserObjectInformationA(wstation, UOI_FLAGS, &uoflags, sizeof(uoflags), &len));
return (uoflags.dwFlags & WSF_VISIBLE) != 0;
}
else
return IsWindowVisible(GetDesktopWindow());
}
void print_version ()
{
OSVERSIONINFOEX ver;
BOOL ext;
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (!(ext = GetVersionEx ((OSVERSIONINFO *) &ver)))
{
ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx ((OSVERSIONINFO *) &ver))
report (R_FATAL, "Can't get OS version.");
}
xprintf (" bRunningUnderWine=%d\n", running_under_wine ());
xprintf (" bRunningOnVisibleDesktop=%d\n", running_on_visible_desktop ());
xprintf (" dwMajorVersion=%ld\n dwMinorVersion=%ld\n"
" dwBuildNumber=%ld\n PlatformId=%ld\n szCSDVersion=%s\n",
ver.dwMajorVersion, ver.dwMinorVersion, ver.dwBuildNumber,
ver.dwPlatformId, ver.szCSDVersion);
if (!ext) return;
xprintf (" wServicePackMajor=%d\n wServicePackMinor=%d\n"
" wSuiteMask=%d\n wProductType=%d\n wReserved=%d\n",
ver.wServicePackMajor, ver.wServicePackMinor, ver.wSuiteMask,
ver.wProductType, ver.wReserved);
}
static inline int is_dot_dir(const char* x)
{
return ((x[0] == '.') && ((x[1] == 0) || ((x[1] == '.') && (x[2] == 0))));
}
void remove_dir (const char *dir)
{
HANDLE hFind;
WIN32_FIND_DATA wfd;
char path[MAX_PATH];
size_t dirlen = strlen (dir);
/* Make sure the directory exists before going further */
memcpy (path, dir, dirlen);
strcpy (path + dirlen++, "\\*");
hFind = FindFirstFile (path, &wfd);
if (hFind == INVALID_HANDLE_VALUE) return;
do {
char *lp = wfd.cFileName;
if (!lp[0]) lp = wfd.cAlternateFileName; /* ? FIXME not (!lp) ? */
if (is_dot_dir (lp)) continue;
strcpy (path + dirlen, lp);
if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes)
remove_dir(path);
else if (!DeleteFile (path))
report (R_WARNING, "Can't delete file %s: error %d",
path, GetLastError ());
} while (FindNextFile (hFind, &wfd));
FindClose (hFind);
if (!RemoveDirectory (dir))
report (R_WARNING, "Can't remove directory %s: error %d",
dir, GetLastError ());
}
const char* get_test_source_file(const char* test, const char* subtest)
{
static const char* special_dirs[][2] = {
{ "gdi32", "gdi"}, { "kernel32", "kernel" },
{ "msacm32", "msacm" },
{ "user32", "user" }, { "winspool.drv", "winspool" },
{ "ws2_32", "winsock" }, { 0, 0 }
};
static char buffer[MAX_PATH];
int i;
for (i = 0; special_dirs[i][0]; i++) {
if (strcmp(test, special_dirs[i][0]) == 0) {
test = special_dirs[i][1];
break;
}
}
snprintf(buffer, sizeof(buffer), "dlls/%s/tests/%s.c", test, subtest);
return buffer;
}
const char* get_file_rev(const char* file)
{
const struct rev_info* rev;
for(rev = rev_infos; rev->file; rev++) {
if (strcmp(rev->file, file) == 0) return rev->rev;
}
return "-";
}
void extract_rev_infos ()
{
char revinfo[256], *p;
int size = 0, i, len;
HMODULE module = GetModuleHandle (NULL);
for (i = 0; TRUE; i++) {
if (i >= size) {
size += 100;
rev_infos = xrealloc (rev_infos, size * sizeof (*rev_infos));
}
memset(rev_infos + i, 0, sizeof(rev_infos[i]));
len = LoadStringA (module, REV_INFO+i, revinfo, sizeof(revinfo));
if (len == 0) break; /* end of revision info */
if (len >= sizeof(revinfo) - 1)
report (R_FATAL, "Revision info too long.");
if(!(p = strrchr(revinfo, ':')))
report (R_FATAL, "Revision info malformed (i=%d)", i);
*p = 0;
rev_infos[i].file = strdup(revinfo);
rev_infos[i].rev = strdup(p + 1);
}
}
void* extract_rcdata (int id, int type, DWORD* size)
{
HRSRC rsrc;
HGLOBAL hdl;
LPVOID addr;
if (!(rsrc = FindResource (NULL, (LPTSTR)id, MAKEINTRESOURCE(type))) ||
!(*size = SizeofResource (0, rsrc)) ||
!(hdl = LoadResource (0, rsrc)) ||
!(addr = LockResource (hdl)))
return NULL;
return addr;
}
/* Fills in the name and exename fields */
void
extract_test (struct wine_test *test, const char *dir, int id)
{
BYTE* code;
DWORD size;
FILE* fout;
int strlen, bufflen = 128;
char *exepos;
code = extract_rcdata (id, TESTRES, &size);
if (!code) report (R_FATAL, "Can't find test resource %d: %d",
id, GetLastError ());
test->name = xmalloc (bufflen);
while ((strlen = LoadStringA (NULL, id, test->name, bufflen))
== bufflen - 1) {
bufflen *= 2;
test->name = xrealloc (test->name, bufflen);
}
if (!strlen) report (R_FATAL, "Can't read name of test %d.", id);
test->exename = strmake (NULL, "%s/%s", dir, test->name);
exepos = strstr (test->name, "_test.exe");
if (!exepos) report (R_FATAL, "Not an .exe file: %s", test->name);
*exepos = 0;
test->name = xrealloc (test->name, exepos - test->name + 1);
report (R_STEP, "Extracting: %s", test->name);
if (!(fout = fopen (test->exename, "wb")) ||
(fwrite (code, size, 1, fout) != 1) ||
fclose (fout)) report (R_FATAL, "Failed to write file %s.",
test->exename);
}
/* Run a command for MS milliseconds. If OUT != NULL, also redirect
stdout to there.
Return the exit status, -2 if can't create process or the return
value of WaitForSingleObject.
*/
int
run_ex (char *cmd, const char *out, DWORD ms)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
int fd, oldstdout = -1;
DWORD wait, status;
GetStartupInfo (&si);
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW;
if (out) {
fd = open (out, O_WRONLY | O_CREAT, 0666);
if (-1 == fd)
report (R_FATAL, "Can't open '%s': %d", out, errno);
oldstdout = dup (1);
if (-1 == oldstdout)
report (R_FATAL, "Can't save stdout: %d", errno);
if (-1 == dup2 (fd, 1))
report (R_FATAL, "Can't redirect stdout: %d", errno);
close (fd);
}
if (!CreateProcessA (NULL, cmd, NULL, NULL, TRUE, 0,
NULL, NULL, &si, &pi)) {
status = -2;
} else {
CloseHandle (pi.hThread);
wait = WaitForSingleObject (pi.hProcess, ms);
if (wait == WAIT_OBJECT_0) {
GetExitCodeProcess (pi.hProcess, &status);
} else {
switch (wait) {
case WAIT_FAILED:
report (R_ERROR, "Wait for '%s' failed: %d", cmd,
GetLastError ());
break;
case WAIT_TIMEOUT:
report (R_ERROR, "Process '%s' timed out.", cmd);
break;
default:
report (R_ERROR, "Wait returned %d", wait);
}
status = wait;
if (!TerminateProcess (pi.hProcess, 257))
report (R_ERROR, "TerminateProcess failed: %d",
GetLastError ());
wait = WaitForSingleObject (pi.hProcess, 5000);
switch (wait) {
case WAIT_FAILED:
report (R_ERROR,
"Wait for termination of '%s' failed: %d",
cmd, GetLastError ());
break;
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
report (R_ERROR, "Can't kill process '%s'", cmd);
break;
default:
report (R_ERROR, "Waiting for termination: %d",
wait);
}
}
CloseHandle (pi.hProcess);
}
if (out) {
close (1);
if (-1 == dup2 (oldstdout, 1))
report (R_FATAL, "Can't recover stdout: %d", errno);
close (oldstdout);
}
return status;
}
void
get_subtests (const char *tempdir, struct wine_test *test, int id)
{
char *subname;
FILE *subfile;
size_t total;
char buffer[8192], *index;
static const char header[] = "Valid test names:";
int allocated;
test->subtest_count = 0;
subname = tempnam (0, "sub");
if (!subname) report (R_FATAL, "Can't name subtests file.");
extract_test (test, tempdir, id);
run_ex (test->exename, subname, 5000);
subfile = fopen (subname, "r");
if (!subfile) {
report (R_ERROR, "Can't open subtests output of %s: %d",
test->name, errno);
goto quit;
}
total = fread (buffer, 1, sizeof buffer, subfile);
fclose (subfile);
if (sizeof buffer == total) {
report (R_ERROR, "Subtest list of %s too big.",
test->name, sizeof buffer);
goto quit;
}
buffer[total] = 0;
index = strstr (buffer, header);
if (!index) {
report (R_ERROR, "Can't parse subtests output of %s",
test->name);
goto quit;
}
index += sizeof header;
allocated = 10;
test->subtests = xmalloc (allocated * sizeof(char*));
index = strtok (index, whitespace);
while (index) {
if (test->subtest_count == allocated) {
allocated *= 2;
test->subtests = xrealloc (test->subtests,
allocated * sizeof(char*));
}
test->subtests[test->subtest_count++] = strdup (index);
index = strtok (NULL, whitespace);
}
test->subtests = xrealloc (test->subtests,
test->subtest_count * sizeof(char*));
quit:
if (remove (subname))
report (R_WARNING, "Can't delete file '%s': %d",
subname, errno);
free (subname);
}
void
run_test (struct wine_test* test, const char* subtest)
{
int status;
const char* file = get_test_source_file(test->name, subtest);
const char* rev = get_file_rev(file);
char *cmd = strmake (NULL, "%s %s", test->exename, subtest);
xprintf ("%s:%s start %s %s\n", test->name, subtest, file, rev);
status = run_ex (cmd, NULL, 120000);
free (cmd);
xprintf ("%s:%s done (%d)\n", test->name, subtest, status);
}
BOOL CALLBACK
EnumTestFileProc (HMODULE hModule, LPCTSTR lpszType,
LPTSTR lpszName, LONG_PTR lParam)
{
(*(int*)lParam)++;
return TRUE;
}
char *
run_tests (char *logname, const char *tag)
{
int nr_of_files = 0, nr_of_tests = 0, i;
char *tempdir;
int logfile;
char *strres, *eol, *nextline;
DWORD strsize;
SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
if (!logname) {
logname = tempnam (0, "res");
if (!logname) report (R_FATAL, "Can't name logfile.");
}
report (R_OUT, logname);
logfile = open (logname, O_WRONLY | O_CREAT | O_EXCL | O_APPEND,
0666);
if (-1 == logfile) {
if (EEXIST == errno)
report (R_FATAL, "File %s already exists.", logname);
else report (R_FATAL, "Could not open logfile: %d", errno);
}
if (-1 == dup2 (logfile, 1))
report (R_FATAL, "Can't redirect stdout: %d", errno);
close (logfile);
tempdir = tempnam (0, "wct");
if (!tempdir)
report (R_FATAL, "Can't name temporary dir (check %%TEMP%%).");
report (R_DIR, tempdir);
if (!CreateDirectory (tempdir, NULL))
report (R_FATAL, "Could not create directory: %s", tempdir);
xprintf ("Version 3\n");
strres = extract_rcdata (WINE_BUILD, STRINGRES, &strsize);
xprintf ("Tests from build ");
if (strres) xprintf ("%.*s", strsize, strres);
else xprintf ("-\n");
strres = extract_rcdata (TESTS_URL, STRINGRES, &strsize);
xprintf ("Archive: ");
if (strres) xprintf ("%.*s", strsize, strres);
else xprintf ("-\n");
xprintf ("Tag: %s\n", tag?tag:"");
xprintf ("Build info:\n");
strres = extract_rcdata (BUILD_INFO, STRINGRES, &strsize);
while (strres) {
eol = memchr (strres, '\n', strsize);
if (!eol) {
nextline = NULL;
eol = strres + strsize;
} else {
strsize -= eol - strres + 1;
nextline = strsize?eol+1:NULL;
if (eol > strres && *(eol-1) == '\r') eol--;
}
xprintf (" %.*s\n", eol-strres, strres);
strres = nextline;
}
xprintf ("Operating system version:\n");
print_version ();
xprintf ("Test output:\n" );
report (R_STATUS, "Counting tests");
if (!EnumResourceNames (NULL, MAKEINTRESOURCE(TESTRES),
EnumTestFileProc, (LPARAM)&nr_of_files))
report (R_FATAL, "Can't enumerate test files: %d",
GetLastError ());
wine_tests = xmalloc (nr_of_files * sizeof wine_tests[0]);
report (R_STATUS, "Extracting tests");
report (R_PROGRESS, 0, nr_of_files);
for (i = 0; i < nr_of_files; i++) {
get_subtests (tempdir, wine_tests+i, i);
nr_of_tests += wine_tests[i].subtest_count;
}
report (R_DELTA, 0, "Extracting: Done");
report (R_STATUS, "Running tests");
report (R_PROGRESS, 1, nr_of_tests);
for (i = 0; i < nr_of_files; i++) {
struct wine_test *test = wine_tests + i;
int j;
for (j = 0; j < test->subtest_count; j++) {
report (R_STEP, "Running: %s:%s", test->name,
test->subtests[j]);
run_test (test, test->subtests[j]);
}
}
report (R_DELTA, 0, "Running: Done");
report (R_STATUS, "Cleaning up");
close (1);
remove_dir (tempdir);
free (tempdir);
free (wine_tests);
return logname;
}
void
usage ()
{
fprintf (stderr, "\
Usage: winetest [OPTION]...\n\n\
-c console mode, no GUI\n\
-e preserve the environment\n\
-h print this message and exit\n\
-q quiet mode, no output at all\n\
-o FILE put report into FILE, do not submit\n\
-s FILE submit FILE, do not run tests\n\
-t TAG include TAG of characters [-.0-9a-zA-Z] in the report\n");
}
int WINAPI WinMain (HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR cmdLine, int cmdShow)
{
char *logname = NULL;
const char *cp, *submit = NULL, *tag = NULL;
int reset_env = 1;
if (!running_on_visible_desktop ()) {
report (R_ERROR, "Tests must be run on a visible desktop");
exit (2);
}
/* initialize the revision information first */
extract_rev_infos();
cmdLine = strtok (cmdLine, whitespace);
while (cmdLine) {
if (cmdLine[0] != '-' || cmdLine[2]) {
report (R_ERROR, "Not a single letter option: %s", cmdLine);
usage ();
exit (2);
}
switch (cmdLine[1]) {
case 'c':
report (R_TEXTMODE);
break;
case 'e':
reset_env = 0;
break;
case 'h':
usage ();
exit (0);
case 'q':
report (R_QUIET);
break;
case 's':
submit = strtok (NULL, whitespace);
if (tag)
report (R_WARNING, "ignoring tag for submission");
send_file (submit);
break;
case 'o':
logname = strtok (NULL, whitespace);
break;
case 't':
tag = strtok (NULL, whitespace);
cp = badtagchar (tag);
if (cp) {
report (R_ERROR, "invalid char in tag: %c", *cp);
usage ();
exit (2);
}
break;
default:
report (R_ERROR, "invalid option: -%c", cmdLine[1]);
usage ();
exit (2);
}
cmdLine = strtok (NULL, whitespace);
}
if (!submit) {
if (reset_env && (putenv ("WINETEST_PLATFORM=windows") ||
putenv ("WINETEST_DEBUG=1") ||
putenv ("WINETEST_INTERACTIVE=0") ||
putenv ("WINETEST_REPORT_SUCCESS=0")))
report (R_FATAL, "Could not reset environment: %d", errno);
report (R_STATUS, "Starting up");
if (!logname) {
logname = run_tests (NULL, tag);
if (report (R_ASK, MB_YESNO, "Do you want to submit the "
"test results?") == IDYES)
if (!send_file (logname) && remove (logname))
report (R_WARNING, "Can't remove logfile: %d.", errno);
free (logname);
} else run_tests (logname, tag);
report (R_STATUS, "Finished");
}
exit (0);
}
+23
View File
@@ -0,0 +1,23 @@
PATH_TO_TOP = ../../..
TARGET_TYPE = program
TARGET_APPTYPE = console
TARGET_NAME = winetest
TARGET_SDKLIBS = comctl32.a comdlg32.a ws2_32.a
TARGET_OBJECTS = \
main.o \
send.o \
util.o \
gui.o
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
# EOF
+469
View File
@@ -0,0 +1,469 @@
/*
* Wine porting definitions
*
* Copyright 1996 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_WINE_PORT_H
#define __WINE_WINE_PORT_H
#ifndef __WINE_CONFIG_H
# error You must include config.h to use this header
#endif
#define _GNU_SOURCE /* for pread/pwrite */
#include <fcntl.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_DIRECT_H
# include <direct.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_PROCESS_H
# include <process.h>
#endif
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
/****************************************************************
* Type definitions
*/
#ifndef HAVE_MODE_T
typedef int mode_t;
#endif
#ifndef HAVE_OFF_T
typedef long off_t;
#endif
#ifndef HAVE_PID_T
typedef int pid_t;
#endif
#ifndef HAVE_SIZE_T
typedef unsigned int size_t;
#endif
#ifndef HAVE_SSIZE_T
typedef int ssize_t;
#endif
#ifndef HAVE_FSBLKCNT_T
typedef unsigned long fsblkcnt_t;
#endif
#ifndef HAVE_FSFILCNT_T
typedef unsigned long fsfilcnt_t;
#endif
#ifndef HAVE_STRUCT_STATVFS_F_BLOCKS
struct statvfs
{
unsigned long f_bsize;
unsigned long f_frsize;
fsblkcnt_t f_blocks;
fsblkcnt_t f_bfree;
fsblkcnt_t f_bavail;
fsfilcnt_t f_files;
fsfilcnt_t f_ffree;
fsfilcnt_t f_favail;
unsigned long f_fsid;
unsigned long f_flag;
unsigned long f_namemax;
};
#endif /* HAVE_STRUCT_STATVFS_F_BLOCKS */
/****************************************************************
* Macro definitions
*/
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#else
#define RTLD_LAZY 0x001
#define RTLD_NOW 0x002
#define RTLD_GLOBAL 0x100
#endif
#if !defined(HAVE_FTRUNCATE) && defined(HAVE_CHSIZE)
#define ftruncate chsize
#endif
#if !defined(HAVE_POPEN) && defined(HAVE__POPEN)
#define popen _popen
#endif
#if !defined(HAVE_PCLOSE) && defined(HAVE__PCLOSE)
#define pclose _pclose
#endif
#if !defined(HAVE_SNPRINTF) && defined(HAVE__SNPRINTF)
#define snprintf _snprintf
#endif
#if !defined(HAVE_VSNPRINTF) && defined(HAVE__VSNPRINTF)
#define vsnprintf _vsnprintf
#endif
#ifndef S_ISLNK
# define S_ISLNK(mod) (0)
#endif
#ifndef S_ISSOCK
# define S_ISSOCK(mod) (0)
#endif
#ifndef S_ISDIR
# define S_ISDIR(mod) (((mod) & _S_IFMT) == _S_IFDIR)
#endif
#ifndef S_ISCHR
# define S_ISCHR(mod) (((mod) & _S_IFMT) == _S_IFCHR)
#endif
#ifndef S_ISFIFO
# define S_ISFIFO(mod) (((mod) & _S_IFMT) == _S_IFIFO)
#endif
#ifndef S_ISREG
# define S_ISREG(mod) (((mod) & _S_IFMT) == _S_IFREG)
#endif
#ifndef S_IWUSR
# define S_IWUSR 0
#endif
/* So we open files in 64 bit access mode on Linux */
#ifndef O_LARGEFILE
# define O_LARGEFILE 0
#endif
#ifndef O_NONBLOCK
# define O_NONBLOCK 0
#endif
#ifndef O_BINARY
# define O_BINARY 0
#endif
#if !defined(S_IXUSR) && defined(S_IEXEC)
# define S_IXUSR S_IEXEC
#endif
#if !defined(S_IXGRP) && defined(S_IEXEC)
# define S_IXGRP S_IEXEC
#endif
#if !defined(S_IXOTH) && defined(S_IEXEC)
# define S_IXOTH S_IEXEC
#endif
/****************************************************************
* Constants
*/
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 1.570796326794896619
#endif
/* Macros to define assembler functions somewhat portably */
#if defined(__GNUC__) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(__APPLE__)
# define __ASM_GLOBAL_FUNC(name,code) \
__asm__( ".text\n\t" \
".align 4\n\t" \
".globl " __ASM_NAME(#name) "\n\t" \
__ASM_FUNC(#name) "\n" \
__ASM_NAME(#name) ":\n\t" \
code \
"\n\t.previous" );
#else /* defined(__GNUC__) && !defined(__MINGW32__) && !defined(__APPLE__) */
# define __ASM_GLOBAL_FUNC(name,code) \
void __asm_dummy_##name(void) { \
asm( ".align 4\n\t" \
".globl " __ASM_NAME(#name) "\n\t" \
__ASM_FUNC(#name) "\n" \
__ASM_NAME(#name) ":\n\t" \
code ); \
}
#endif /* __GNUC__ */
/* Constructor functions */
#ifdef __GNUC__
# define DECL_GLOBAL_CONSTRUCTOR(func) \
static void func(void) __attribute__((constructor)); \
static void func(void)
#elif defined(__i386__)
# define DECL_GLOBAL_CONSTRUCTOR(func) \
static void __dummy_init_##func(void) { \
asm(".section .init,\"ax\"\n\t" \
"call " #func "\n\t" \
".previous"); } \
static void func(void)
#elif defined(__sparc__)
# define DECL_GLOBAL_CONSTRUCTOR(func) \
static void __dummy_init_##func(void) { \
asm("\t.section \".init\",#alloc,#execinstr\n" \
"\tcall " #func "\n" \
"\tnop\n" \
"\t.section \".text\",#alloc,#execinstr\n" ); } \
static void func(void)
#else
# error You must define the DECL_GLOBAL_CONSTRUCTOR macro for your platform
#endif
/* Register functions */
#ifdef __i386__
#define DEFINE_REGS_ENTRYPOINT( name, fn, args, pop_args ) \
__ASM_GLOBAL_FUNC( name, \
"call " __ASM_NAME("__wine_call_from_32_regs") "\n\t" \
".long " __ASM_NAME(#fn) "\n\t" \
".byte " #args "," #pop_args )
/* FIXME: add support for other CPUs */
#endif /* __i386__ */
/****************************************************************
* Function definitions (only when using libwine_port)
*/
#ifndef NO_LIBWINE_PORT
#ifndef HAVE_FSTATVFS
int fstatvfs( int fd, struct statvfs *buf );
#endif
#ifndef HAVE_GETOPT_LONG
extern char *optarg;
extern int optind;
extern int opterr;
extern int optopt;
struct option;
#ifndef HAVE_STRUCT_OPTION_NAME
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
#endif
extern int getopt_long (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
extern int getopt_long_only (int ___argc, char *const *___argv,
const char *__shortopts,
const struct option *__longopts, int *__longind);
#endif /* HAVE_GETOPT_LONG */
#ifndef HAVE_FFS
int ffs( int x );
#endif
#ifndef HAVE_FUTIMES
struct timeval;
int futimes(int fd, const struct timeval tv[2]);
#endif
#ifndef HAVE_GETPAGESIZE
size_t getpagesize(void);
#endif /* HAVE_GETPAGESIZE */
#ifndef HAVE_GETTID
pid_t gettid(void);
#endif /* HAVE_GETTID */
#ifndef HAVE_LSTAT
int lstat(const char *file_name, struct stat *buf);
#endif /* HAVE_LSTAT */
#ifndef HAVE_MEMMOVE
void *memmove(void *dest, const void *src, size_t len);
#endif /* !defined(HAVE_MEMMOVE) */
#ifndef HAVE_PREAD
ssize_t pread( int fd, void *buf, size_t count, off_t offset );
#endif /* HAVE_PREAD */
#ifndef HAVE_PWRITE
ssize_t pwrite( int fd, const void *buf, size_t count, off_t offset );
#endif /* HAVE_PWRITE */
#ifndef HAVE_READLINK
int readlink( const char *path, char *buf, size_t size );
#endif /* HAVE_READLINK */
#ifndef HAVE_SIGSETJMP
# include <setjmp.h>
typedef jmp_buf sigjmp_buf;
int sigsetjmp( sigjmp_buf buf, int savesigs );
void siglongjmp( sigjmp_buf buf, int val );
#endif /* HAVE_SIGSETJMP */
#ifndef HAVE_STATVFS
int statvfs( const char *path, struct statvfs *buf );
#endif
#ifndef HAVE_STRNCASECMP
# ifndef HAVE__STRNICMP
int strncasecmp(const char *str1, const char *str2, size_t n);
# else
# define strncasecmp _strnicmp
# endif
#endif /* !defined(HAVE_STRNCASECMP) */
#ifndef HAVE_STRERROR
const char *strerror(int err);
#endif /* !defined(HAVE_STRERROR) */
#ifndef HAVE_STRCASECMP
# ifndef HAVE__STRICMP
int strcasecmp(const char *str1, const char *str2);
# else
# define strcasecmp _stricmp
# endif
#endif /* !defined(HAVE_STRCASECMP) */
#ifndef HAVE_USLEEP
int usleep (unsigned int useconds);
#endif /* !defined(HAVE_USLEEP) */
#ifdef __i386__
static inline void *memcpy_unaligned( void *dst, const void *src, size_t size )
{
return memcpy( dst, src, size );
}
#else
extern void *memcpy_unaligned( void *dst, const void *src, size_t size );
#endif /* __i386__ */
extern int mkstemps(char *template, int suffix_len);
/* Process creation flags */
#ifndef _P_WAIT
# define _P_WAIT 0
# define _P_NOWAIT 1
# define _P_OVERLAY 2
# define _P_NOWAITO 3
# define _P_DETACH 4
#endif
#ifndef HAVE_SPAWNVP
extern int spawnvp(int mode, const char *cmdname, const char * const argv[]);
#endif
/* Interlocked functions */
#if defined(__i386__) && defined(__GNUC__)
extern inline long interlocked_cmpxchg( long *dest, long xchg, long compare );
extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare );
extern inline long interlocked_xchg( long *dest, long val );
extern inline void *interlocked_xchg_ptr( void **dest, void *val );
extern inline long interlocked_xchg_add( long *dest, long incr );
extern inline long interlocked_cmpxchg( long *dest, long xchg, long compare )
{
long ret;
__asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
: "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
return ret;
}
extern inline void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare )
{
void *ret;
__asm__ __volatile__( "lock; cmpxchgl %2,(%1)"
: "=a" (ret) : "r" (dest), "r" (xchg), "0" (compare) : "memory" );
return ret;
}
extern inline long interlocked_xchg( long *dest, long val )
{
long ret;
__asm__ __volatile__( "lock; xchgl %0,(%1)"
: "=r" (ret) : "r" (dest), "0" (val) : "memory" );
return ret;
}
extern inline void *interlocked_xchg_ptr( void **dest, void *val )
{
void *ret;
__asm__ __volatile__( "lock; xchgl %0,(%1)"
: "=r" (ret) : "r" (dest), "0" (val) : "memory" );
return ret;
}
extern inline long interlocked_xchg_add( long *dest, long incr )
{
long ret;
__asm__ __volatile__( "lock; xaddl %0,(%1)"
: "=r" (ret) : "r" (dest), "0" (incr) : "memory" );
return ret;
}
#else /* __i386___ && __GNUC__ */
extern long interlocked_cmpxchg( long *dest, long xchg, long compare );
extern void *interlocked_cmpxchg_ptr( void **dest, void *xchg, void *compare );
extern long interlocked_xchg( long *dest, long val );
extern void *interlocked_xchg_ptr( void **dest, void *val );
extern long interlocked_xchg_add( long *dest, long incr );
#endif /* __i386___ && __GNUC__ */
#else /* NO_LIBWINE_PORT */
#define __WINE_NOT_PORTABLE(func) func##_is_not_portable func##_is_not_portable
#define ffs __WINE_NOT_PORTABLE(ffs)
#define fstatvfs __WINE_NOT_PORTABLE(fstatvfs)
#define futimes __WINE_NOT_PORTABLE(futimes)
#define getopt_long __WINE_NOT_PORTABLE(getopt_long)
#define getopt_long_only __WINE_NOT_PORTABLE(getopt_long_only)
#define getpagesize __WINE_NOT_PORTABLE(getpagesize)
#define interlocked_cmpxchg __WINE_NOT_PORTABLE(interlocked_cmpxchg)
#define interlocked_cmpxchg_ptr __WINE_NOT_PORTABLE(interlocked_cmpxchg_ptr)
#define interlocked_xchg __WINE_NOT_PORTABLE(interlocked_xchg)
#define interlocked_xchg_ptr __WINE_NOT_PORTABLE(interlocked_xchg_ptr)
#define interlocked_xchg_add __WINE_NOT_PORTABLE(interlocked_xchg_add)
#define lstat __WINE_NOT_PORTABLE(lstat)
#define memcpy_unaligned __WINE_NOT_PORTABLE(memcpy_unaligned)
#define memmove __WINE_NOT_PORTABLE(memmove)
#define pread __WINE_NOT_PORTABLE(pread)
#define pwrite __WINE_NOT_PORTABLE(pwrite)
#define spawnvp __WINE_NOT_PORTABLE(spawnvp)
#define statvfs __WINE_NOT_PORTABLE(statvfs)
#define strcasecmp __WINE_NOT_PORTABLE(strcasecmp)
#define strerror __WINE_NOT_PORTABLE(strerror)
#define strncasecmp __WINE_NOT_PORTABLE(strncasecmp)
#define usleep __WINE_NOT_PORTABLE(usleep)
#endif /* NO_LIBWINE_PORT */
#endif /* !defined(__WINE_WINE_PORT_H) */
+53
View File
@@ -0,0 +1,53 @@
/*
* Resource definitions
*
* Copyright 2004 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define IDI_WINE 1
#define IDD_STATUS 100
#define IDD_ABOUT 101
#define IDC_ST0 1000
#define IDC_PB0 1001
#define IDC_ST1 1002
#define IDC_PB1 1003
#define IDC_ST2 1004
#define IDC_PB2 1005
#define IDC_DIR 2000
#define IDC_OUT 2001
#define IDC_SB 3000
#define IDC_EDIT 4000
#define IDC_ABOUT 4001
/* Resource types */
#define TESTRES 1000
#define STRINGRES 1001
/* String resources */
#define WINE_BUILD 10000
#define BUILD_INFO 10001
#define TESTS_URL 10002
/* Revision info strings start from this index: */
#define REV_INFO 30000
+223
View File
@@ -0,0 +1,223 @@
/*
* HTTP handling functions.
*
* Copyright 2003 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <winsock.h>
#include <stdio.h>
#include <errno.h>
#include "winetest.h"
SOCKET
open_http (const char *server)
{
WSADATA wsad;
struct sockaddr_in sa;
SOCKET s;
report (R_STATUS, "Opening HTTP connection to %s", server);
if (WSAStartup (MAKEWORD (2,2), &wsad)) return INVALID_SOCKET;
sa.sin_family = AF_INET;
sa.sin_port = htons (80);
sa.sin_addr.s_addr = inet_addr (server);
if (sa.sin_addr.s_addr == INADDR_NONE) {
struct hostent *host = gethostbyname (server);
if (!host) {
report (R_ERROR, "Hostname lookup failed for %s", server);
goto failure;
}
sa.sin_addr.s_addr = ((struct in_addr *)host->h_addr)->s_addr;
}
s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET) {
report (R_ERROR, "Can't open network socket: %d",
WSAGetLastError ());
goto failure;
}
if (!connect (s, (struct sockaddr*)&sa, sizeof (struct sockaddr_in)))
return s;
report (R_ERROR, "Can't connect: %d", WSAGetLastError ());
closesocket (s);
failure:
WSACleanup ();
return INVALID_SOCKET;
}
int
close_http (SOCKET s)
{
int ret;
ret = closesocket (s);
return (WSACleanup () || ret);
}
int
send_buf (SOCKET s, const char *buf, size_t length)
{
int sent;
while (length > 0) {
sent = send (s, buf, length, 0);
if (sent == SOCKET_ERROR) return 1;
buf += sent;
length -= sent;
}
return 0;
}
int
send_str (SOCKET s, ...)
{
va_list ap;
char *p;
int ret;
size_t len;
va_start (ap, s);
p = vstrmake (&len, ap);
va_end (ap);
if (!p) return 1;
ret = send_buf (s, p, len);
free (p);
return ret;
}
int
send_file (const char *name)
{
SOCKET s;
FILE *f;
#define BUFLEN 8192
unsigned char buffer[BUFLEN+1];
size_t bytes_read, total, filesize;
char *str;
int ret;
/* RFC 2616 */
#define SEP "--8<--cut-here--8<--"
static const char head[] = "POST /submit HTTP/1.0\r\n"
"Host: test.winehq.org\r\n"
"User-Agent: Winetest Shell\r\n"
"Content-Type: multipart/form-data; boundary=\"" SEP "\"\r\n"
"Content-Length: %u\r\n\r\n";
static const char body1[] = "--" SEP "\r\n"
"Content-Disposition: form-data; name=\"reportfile\"; filename=\"%s\"\r\n"
"Content-Type: application/octet-stream\r\n\r\n";
static const char body2[] = "\r\n--" SEP "\r\n"
"Content-Disposition: form-data; name=\"submit\"\r\n\r\n"
"Upload File\r\n"
"--" SEP "--\r\n";
s = open_http ("test.winehq.org");
if (s == INVALID_SOCKET) return 1;
f = fopen (name, "rb");
if (!f) {
report (R_WARNING, "Can't open file '%s': %d", name, errno);
goto abort1;
}
fseek (f, 0, SEEK_END);
filesize = ftell (f);
if (filesize > 1024*1024) {
report (R_WARNING,
"File too big (%.1f MB > 1 MB); submitting partial report.",
filesize/1024.0/1024);
filesize = 1024*1024;
}
fseek (f, 0, SEEK_SET);
report (R_STATUS, "Sending header");
str = strmake (&total, body1, name);
ret = send_str (s, head, filesize + total + sizeof body2 - 1) ||
send_buf (s, str, total);
free (str);
if (ret) {
report (R_WARNING, "Error sending header: %d, %d",
errno, WSAGetLastError ());
goto abort2;
}
report (R_STATUS, "Sending %u bytes of data", filesize);
report (R_PROGRESS, 2, filesize);
total = 0;
while (total < filesize && (bytes_read = fread (buffer, 1, BUFLEN/2, f))) {
if ((signed)bytes_read == -1) {
report (R_WARNING, "Error reading log file: %d", errno);
goto abort2;
}
total += bytes_read;
if (total > filesize) bytes_read -= total - filesize;
if (send_buf (s, buffer, bytes_read)) {
report (R_WARNING, "Error sending body: %d, %d",
errno, WSAGetLastError ());
goto abort2;
}
report (R_DELTA, bytes_read, "Network transfer: In progress");
}
fclose (f);
if (send_buf (s, body2, sizeof body2 - 1)) {
report (R_WARNING, "Error sending trailer: %d, %d",
errno, WSAGetLastError ());
goto abort2;
}
report (R_DELTA, 0, "Network transfer: Done");
total = 0;
while ((bytes_read = recv (s, buffer+total, BUFLEN-total, 0))) {
if ((signed)bytes_read == SOCKET_ERROR) {
report (R_WARNING, "Error receiving reply: %d, %d",
errno, WSAGetLastError ());
goto abort1;
}
total += bytes_read;
if (total == BUFLEN) {
report (R_WARNING, "Buffer overflow");
goto abort1;
}
}
if (close_http (s)) {
report (R_WARNING, "Error closing connection: %d, %d",
errno, WSAGetLastError ());
return 1;
}
str = strmake (&bytes_read, "Received %s (%d bytes).\n",
name, filesize);
ret = memcmp (str, buffer + total - bytes_read, bytes_read);
free (str);
if (ret) {
buffer[total] = 0;
str = strstr (buffer, "\r\n\r\n");
if (!str) str = buffer;
else str = str + 4;
report (R_ERROR, "Can't submit logfile '%s'. "
"Server response: %s", name, str);
}
return ret;
abort2:
fclose (f);
abort1:
close_http (s);
return 1;
}
+20
View File
@@ -0,0 +1,20 @@
/* Automatically generated -- do not edit! */
#include "resource.h"
STRINGTABLE {
0 "advapi32_test.exe"
1 "comctl32_test.exe"
REV_INFO+0 "lib/advapi32/winetests/crypt_lmhash.c:1.1"
REV_INFO+1 "lib/advapi32/winetests/crypt_md4.c:1.1"
REV_INFO+2 "lib/advapi32/winetests/crypt_md5.c:1.1"
REV_INFO+3 "lib/advapi32/winetests/crypt_sha.c:1.1"
REV_INFO+4 "lib/advapi32/winetests/registry.c:1.1"
REV_INFO+5 "lib/advapi32/winetests/security.c:1."
REV_INFO+6 "lib/advapi32/winetests/crypt.c:1.1"
REV_INFO+7 "dlls/comctl32/tests/imagelist.c:1.1"
REV_INFO+8 "dlls/comctl32/tests/mru.c:1.1"
REV_INFO+9 "dlls/comctl32/tests/subclass.c:1.1"
REV_INFO+10 "dlls/comctl32/tests/tab.c:1.1"
}
0 TESTRES "../../../lib/advapi32/winetests/advapi32_test.exe"
1 TESTRES "../../../lib/comctl32/winetests/comctl32_test.exe"
+118
View File
@@ -0,0 +1,118 @@
/*
* Utility functions.
*
* Copyright 2003 Dimitrie O. Paun
* Copyright 2003 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <unistd.h>
#include <errno.h>
#include "winetest.h"
void *xmalloc (size_t len)
{
void *p = malloc (len);
if (!p) report (R_FATAL, "Out of memory.");
return p;
}
void *xrealloc (void *op, size_t len)
{
void *p = realloc (op, len);
if (!p) report (R_FATAL, "Out of memory.");
return p;
}
char *vstrfmtmake (size_t *lenp, const char *fmt, va_list ap)
{
size_t size = 1000;
char *p, *q;
int n;
p = malloc (size);
if (!p) return NULL;
while (1) {
n = vsnprintf (p, size, fmt, ap);
if (n < 0) size *= 2; /* Windows */
else if ((unsigned)n >= size) size = n+1; /* glibc */
else break;
q = realloc (p, size);
if (!q) {
free (p);
return NULL;
}
p = q;
}
if (lenp) *lenp = n;
return p;
}
char *vstrmake (size_t *lenp, va_list ap)
{
const char *fmt;
fmt = va_arg (ap, const char*);
return vstrfmtmake (lenp, fmt, ap);
}
char *strmake (size_t *lenp, ...)
{
va_list ap;
char *p;
va_start (ap, lenp);
p = vstrmake (lenp, ap);
if (!p) report (R_FATAL, "Out of memory.");
va_end (ap);
return p;
}
void xprintf (const char *fmt, ...)
{
va_list ap;
size_t size;
ssize_t written;
char *buffer, *head;
va_start (ap, fmt);
buffer = vstrfmtmake (&size, fmt, ap);
head = buffer;
va_end (ap);
while ((written = write (1, head, size)) != size) {
if (written == -1)
report (R_FATAL, "Can't write logs: %d", errno);
head += written;
size -= written;
}
free (buffer);
}
const char *
badtagchar (const char *tag)
{
while (*tag)
if (('a'<=*tag && *tag<='z') ||
('A'<=*tag && *tag<='Z') ||
('0'<=*tag && *tag<='9') ||
*tag=='-' || *tag=='.')
tag++;
else return tag;
return NULL;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

+61
View File
@@ -0,0 +1,61 @@
/*
* winetest definitions
*
* Copyright 2003 Dimitrie O. Paun
* Copyright 2003 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINETESTS_H
#define __WINETESTS_H
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
void fatal (const char* msg);
void warning (const char* msg);
void *xmalloc (size_t len);
void *xrealloc (void *op, size_t len);
void xprintf (const char *fmt, ...);
char *vstrmake (size_t *lenp, va_list ap);
char *strmake (size_t *lenp, ...);
const char *badtagchar (const char *tag);
int send_file (const char *name);
/* GUI definitions */
#include <windows.h>
enum report_type {
R_STATUS = 0,
R_PROGRESS,
R_STEP,
R_DELTA,
R_DIR,
R_OUT,
R_WARNING,
R_ERROR,
R_FATAL,
R_ASK,
R_TEXTMODE,
R_QUIET
};
int report (enum report_type t, ...);
#endif /* __WINETESTS_H */
+132
View File
@@ -0,0 +1,132 @@
/*
* Winetest resources
*
* Copyright 2004 Ferenc Wagner
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <windows.h>
#include <winres.h>
#include "resource.h"
#include "tests.rc"
IDD_STATUS DIALOG 0, 0, 160, 140
STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
CAPTION "Wine Test Shell"
BEGIN
LTEXT "Extracting:", IDC_ST0, 10, 5, 140, 10
CONTROL "PB0", IDC_PB0, PROGRESS_CLASS, 0, 5, 15, 150, 10
LTEXT "Running:", IDC_ST1, 10, 30, 140, 10
CONTROL "PB1", IDC_PB1, PROGRESS_CLASS, 0, 5, 40, 150, 15
LTEXT "Network transfer:", IDC_ST2, 10, 60, 140, 10
CONTROL "PB2", IDC_PB2, PROGRESS_CLASS, 0, 5, 70, 150, 10
LTEXT "Working directory:", IDC_STATIC, 10, 89, 100, 10
EDITTEXT IDC_DIR, 71, 88, 79, 10,
ES_READONLY | ES_AUTOHSCROLL
LTEXT "Output file:", IDC_STATIC, 10, 100, 100, 10
EDITTEXT IDC_OUT, 46, 99, 104, 10,
ES_READONLY | ES_AUTOHSCROLL
DEFPUSHBUTTON "About", IDHELP, 20, 113, 30, 14
PUSHBUTTON "Edit", IDCANCEL, 65, 113, 30, 14,
WS_DISABLED
PUSHBUTTON "Stop", IDABORT, 110, 113, 30, 14
CONTROL "Created", IDC_SB, STATUSCLASSNAME, 0, 0,0,0,0
END
IDD_ABOUT DIALOG 0, 0, 150, 60
STYLE WS_POPUP
CAPTION "About Wine Test Shell"
BEGIN
CTEXT "This program extracts and runs a series of tests which check Wine's conformance to the Windows API.",
IDC_STATIC, 10, 5, 130, 30
DEFPUSHBUTTON "Close", IDCANCEL, 55, 40, 40, 14
END
/* BINRES wine.ico */
IDI_WINE ICON "wine.ico"
/* {
'00 00 01 00 02 00 20 20 10 00 00 00 00 00 E8 02'
'00 00 26 00 00 00 10 10 10 00 00 00 00 00 28 01'
'00 00 0E 03 00 00 28 00 00 00 20 00 00 00 40 00'
'00 00 01 00 04 00 00 00 00 00 00 02 00 00 00 00'
'00 00 00 00 00 00 10 00 00 00 00 00 00 00 39 02'
'B1 00 23 02 6C 00 0F 03 29 00 1B 02 51 00 FF FF'
'FF 00 1B 1A 1B 00 1E 02 63 00 33 02 A1 00 08 08'
'08 00 14 03 3C 00 0C 04 1E 00 2E 02 8E 00 10 0F'
'10 00 2A 02 82 00 29 02 7D 00 03 02 04 00 44 44'
'44 44 44 44 44 44 55 44 44 44 44 44 44 44 44 44'
'44 44 44 44 8F FF 84 44 44 44 44 44 44 44 44 44'
'44 44 44 8F F8 F8 44 44 44 44 44 44 44 44 44 44'
'44 44 8F FF F5 44 44 44 44 44 44 44 44 44 44 44'
'44 5C F8 C8 F5 44 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 85 44 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 4C 44 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 4C 44 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 45 54 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 45 F4 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 45 FF 44 44 44 44 44 44 44 44 44 44'
'44 44 44 44 48 FF F4 44 44 44 44 44 44 44 44 44'
'44 44 44 44 48 23 9A 84 44 44 44 44 44 44 44 44'
'44 44 44 44 42 B7 7E AF 44 44 44 44 44 44 44 44'
'44 44 44 44 49 00 00 EA C4 44 44 44 44 44 44 44'
'44 44 44 44 46 00 00 01 F4 44 44 44 44 44 44 44'
'44 44 44 44 46 00 00 00 9F 44 44 44 44 44 44 44'
'44 44 44 44 46 00 70 00 EF 44 44 44 44 44 44 44'
'44 44 44 44 43 00 00 00 79 F4 44 44 44 44 44 44'
'44 44 44 44 49 00 00 00 0E F4 44 44 44 44 44 44'
'44 44 44 44 42 00 00 00 07 24 44 44 44 44 44 44'
'44 44 44 44 43 B0 00 00 00 34 44 44 44 44 44 44'
'44 44 44 44 4C 30 00 00 00 1F 44 44 44 44 44 44'
'44 44 44 44 48 27 E1 1D B1 2C 44 44 44 44 44 44'
'44 44 44 44 44 A9 CC CF F8 48 C4 44 44 44 44 44'
'44 44 44 44 44 58 44 44 44 45 C4 44 44 44 44 44'
'44 44 44 44 44 4C 44 44 44 44 84 44 44 44 44 44'
'44 44 44 44 44 48 44 44 44 44 C4 44 44 44 44 44'
'44 44 44 44 44 48 C4 44 44 44 C4 44 44 44 44 44'
'44 44 44 44 44 44 F4 44 44 4C C4 44 44 44 44 44'
'44 44 44 44 44 44 84 44 F8 84 44 44 44 44 44 44'
'44 44 44 44 44 44 48 F8 44 44 44 44 44 44 FF FF'
'3F FF FF F0 7F FF FF C0 FF FF FF 03 FF FF FC 03'
'FF FF FF F3 FF FF FF FB FF FF FF FB FF FF FF F9'
'FF FF FF F9 FF FF FF F8 FF FF FF F8 7F FF FF F8'
'1F FF FF F8 0F FF FF F8 07 FF FF F8 07 FF FF F8'
'03 FF FF F8 03 FF FF F8 01 FF FF F8 01 FF FF F8'
'01 FF FF F8 01 FF FF F8 00 FF FF F8 00 FF FF FC'
'02 7F FF FC FE 7F FF FE FF 7F FF FE FF 7F FF FE'
'7F 7F FF FF 7E 7F FF FF 71 FF FF FF 8F FF 28 00'
'00 00 10 00 00 00 20 00 00 00 01 00 04 00 00 00'
'00 00 80 00 00 00 00 00 00 00 00 00 00 00 10 00'
'00 00 00 00 00 00 3A 02 B1 00 0A 06 14 00 12 03'
'33 00 FF FF FF 00 12 12 12 00 0B 0B 0B 00 1B 1B'
'1B 00 25 02 6F 00 2E 02 92 00 1A 02 52 00 36 02'
'A6 00 15 03 3E 00 04 04 05 00 13 11 19 00 1E 02'
'62 00 2A 02 82 00 33 33 33 CC 43 33 33 33 33 33'
'CC 5C 33 33 33 33 33 36 C5 53 33 33 33 33 33 33'
'33 43 33 33 33 33 33 33 33 65 33 33 33 33 33 33'
'33 DC 33 33 33 33 33 33 33 17 EC 33 33 33 33 33'
'33 B0 07 53 33 33 33 33 33 90 00 B3 33 33 33 33'
'33 B0 00 FC 33 33 33 33 33 BA 00 A2 33 33 33 33'
'33 C7 88 82 33 33 33 33 33 3D D5 14 43 33 33 33'
'33 35 33 33 53 33 33 33 33 33 53 33 53 33 33 33'
'33 33 C5 5C 33 33 FC 7F 00 00 F0 FF 00 00 E1 FF'
'00 00 FD FF 00 00 FC FF 00 00 FC FF 00 00 FC 3F'
'00 00 FC 1F 00 00 FC 1F 00 00 FC 0F 00 00 FC 0F'
'00 00 FC 0F 00 00 FE 07 00 00 FE F7 00 00 FF 77'
'00 00 FF 0F 00 00'
} */
+1
View File
@@ -45,6 +45,7 @@
<property name="BASEADDRESS_COMDLG32" value="0x76200000" />
<property name="BASEADDRESS_OLEAUT32" value="0x76260000" />
<property name="BASEADDRESS_RICHED32" value="0x76340000" />
<property name="BASEADDRESS_RICHED20" value="0x76360000" />
<property name="BASEADDRESS_TWAIN_32" value="0x76380000" />
<property name="BASEADDRESS_MIDIMAP" value="0x76600000" />
<property name="BASEADDRESS_MPR" value="0x76620000" />
+4 -1
View File
@@ -29,7 +29,7 @@ all:
$(MAKE) -C fdebug
test:
clean:
$(MAKE) -C bootsect clean
$(MAKE) -C freeldr clean
@@ -38,6 +38,7 @@ clean:
$(MAKE) -C tools clean
bootcd:
ifeq ($(ARCH),i386)
$(CP) bootsect/isoboot.bin ${BOOTCD_DIR}/../isoboot.bin
$(CP) bootsect/dosmbr.bin ${BOOTCD_DIR}/loader/dosmbr.bin
$(CP) bootsect/ext2.bin ${BOOTCD_DIR}/loader/ext2.bin
@@ -46,5 +47,7 @@ bootcd:
$(CP) bootsect/isoboot.bin ${BOOTCD_DIR}/loader/isoboot.bin
$(CP) freeldr/freeldr.sys ${BOOTCD_DIR}/loader/freeldr.sys
$(CP) freeldr/setupldr.sys ${BOOTCD_DIR}/loader/setupldr.sys
endif
.PHONY : clean
+5 -53
View File
@@ -25,56 +25,8 @@ BOOTCD_DIR = $(PATH_TO_TOP)/../bootcd
.PHONY : clean bootcd
all: $(BIN2C) dosmbr.bin fat.bin fat32.bin isoboot.bin ext2.bin
$(BIN2C) :
@$(MAKE) --no-print-directory -C $(FREELDR_TOOLS_PATH)
dosmbr.bin : dosmbr.asm
@echo freeldr: Assembling dosmbr
@$(NASM_CMD) $(NFLAGS) -o dosmbr.bin -f bin dosmbr.asm
fat.bin : fat.asm $(BIN2C)
@echo freeldr: Assembling fat
@$(NASM_CMD) $(NFLAGS) -o fat.bin -f bin fat.asm
@$(BIN2C) fat.bin fat.h fat_data
fat32.bin : fat32.asm $(BIN2C)
@echo freeldr: Assembling fat32
@$(NASM_CMD) $(NFLAGS) -o fat32.bin -f bin fat32.asm
@$(BIN2C) fat32.bin fat32.h fat32_data
isoboot.bin : isoboot.asm
@echo freeldr: Assembling isoboot
@$(NASM_CMD) $(NFLAGS) -o isoboot.bin -f bin isoboot.asm
ext2.bin : ext2.asm
@echo freeldr: Assembling ext2
@$(NASM_CMD) $(NFLAGS) -o ext2.bin -f bin ext2.asm
@$(BIN2C) ext2.bin ext2.h ext2_data
.PHONY : bootcd
bootcd: bootcd_dirs isoboot.bin
$(CP) isoboot.bin $(BOOTCD_DIR)
$(CP) dosmbr.bin $(BOOTCD_DIR)/disk/loader
$(CP) ext2.bin $(BOOTCD_DIR)/disk/loader
$(CP) fat.bin $(BOOTCD_DIR)/disk/loader
$(CP) fat32.bin $(BOOTCD_DIR)/disk/loader
$(CP) isoboot.bin $(BOOTCD_DIR)/disk/loader
.PHONY : bootcd_dirs
bootcd_dirs:
$(MKDIR) $(BOOTCD_DIR)
$(MKDIR) $(BOOTCD_DIR)/disk
$(MKDIR) $(BOOTCD_DIR)/disk/reactos
$(MKDIR) $(BOOTCD_DIR)/disk/install
$(MKDIR) $(BOOTCD_DIR)/disk/bootdisk
$(MKDIR) $(BOOTCD_DIR)/disk/loader
clean:
@-$(RM) *.bin
@-$(RM) *.h
@echo freeldr: Clean ALL done.
ifeq ($(ARCH),powerpc)
include Makefile.powerpc
else
include Makefile.i386
endif
@@ -0,0 +1,52 @@
all: $(BIN2C) dosmbr.bin fat.bin fat32.bin isoboot.bin ext2.bin
$(BIN2C) :
@$(MAKE) --no-print-directory -C $(FREELDR_TOOLS_PATH)
dosmbr.bin : dosmbr.asm
@echo ===================================================== Assembling dosmbr
@$(NASM_CMD) $(NFLAGS) -o dosmbr.bin -f bin dosmbr.asm
fat.bin : fat.asm $(BIN2C)
@echo ===================================================== Assembling fat
@$(NASM_CMD) $(NFLAGS) -o fat.bin -f bin fat.asm
@$(BIN2C) fat.bin fat.h fat_data
fat32.bin : fat32.asm $(BIN2C)
@echo ===================================================== Assembling fat32
@$(NASM_CMD) $(NFLAGS) -o fat32.bin -f bin fat32.asm
@$(BIN2C) fat32.bin fat32.h fat32_data
isoboot.bin : isoboot.asm
@echo ===================================================== Assembling isoboot
@$(NASM_CMD) $(NFLAGS) -o isoboot.bin -f bin isoboot.asm
ext2.bin : ext2.asm
@echo ===================================================== Assembling ext2
@$(NASM_CMD) $(NFLAGS) -o ext2.bin -f bin ext2.asm
@$(BIN2C) ext2.bin ext2.h ext2_data
.PHONY : bootcd
bootcd: bootcd_dirs isoboot.bin
$(CP) isoboot.bin $(BOOTCD_DIR)
$(CP) dosmbr.bin $(BOOTCD_DIR)/disk/loader
$(CP) ext2.bin $(BOOTCD_DIR)/disk/loader
$(CP) fat.bin $(BOOTCD_DIR)/disk/loader
$(CP) fat32.bin $(BOOTCD_DIR)/disk/loader
$(CP) isoboot.bin $(BOOTCD_DIR)/disk/loader
.PHONY : bootcd_dirs
bootcd_dirs:
$(MKDIR) $(BOOTCD_DIR)
$(MKDIR) $(BOOTCD_DIR)/disk
$(MKDIR) $(BOOTCD_DIR)/disk/reactos
$(MKDIR) $(BOOTCD_DIR)/disk/install
$(MKDIR) $(BOOTCD_DIR)/disk/bootdisk
$(MKDIR) $(BOOTCD_DIR)/disk/loader
clean:
@-$(RM) *.bin
@-$(RM) *.h
@echo Clean ALL done.
@@ -0,0 +1,35 @@
TOOLS=$(PATH_TO_TOP)/tools
SECTIONS= \
--only-section=.text \
--only-section=.data \
--only-section=.bss
LDSECT= -Ttext 0xe00000 -Tdata 0xe10000
OBJS=ofwboot.o freeldr.o
CFLAGS=-mbig -meabi -fPIC -fno-builtin -I../freeldr/include
FREELDR=../freeldr/freeldr.sys
.SUFFIXES: .c .o
all: ofwldr
hack-coff$(EXEEXT):
$(HOST_CC) -I../freeldr/include hack-coff.c -o $@
ofwboot.o: ofwboot.s
$(NASM_CMD) $< -c -o $@
$(FREELDR):
$(MAKE) -C ../freeldr
freeldr.o: $(FREELDR)
$(TOOLS)/ppc-le2be $< freeldr.tmp
$(OBJCOPY) -I binary -O elf32-powerpc -B powerpc:common freeldr.tmp $@
rm freeldr.tmp
ofwldr: $(OBJS)
mppcw32-ld --no-omagic $(LDSECT) $(OBJS) -g -o $@.elf
mppcw32-objcopy $(SECTIONS) -O aixcoff-rs6000 $@.elf $@
$(TOOLS)/hack-coff $@
clean:
rm -rf ofwldr *.o *.elf *.tmp
+960
View File
@@ -0,0 +1,960 @@
.section .text
_start:
.long 0xe00000 + 12
.long 0
.long 0
/*
* LIFTED FROM arch/macppc/stand/ofwboot/Locore.c
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
* Copyright (C) 1995, 1996 TooLs GmbH.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by TooLs GmbH.
* 4. The name of TooLs GmbH may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
_begin:
sync
isync
lis %r1,stack@ha
addi %r1,%r1,stack@l
addi %r1,%r1,16384 - 0x10
mfmsr %r8
li %r0,0
mtmsr %r0
isync
mtibatu 0,%r0
mtibatu 1,%r0
mtibatu 2,%r0
mtibatu 3,%r0
mtdbatu 0,%r0
mtdbatu 1,%r0
mtdbatu 2,%r0
mtdbatu 3,%r0
li %r9,0x12 /* BATL(0, BAT_M, BAT_PP_RW) */
mtibatl 0,%r9
mtdbatl 0,%r9
li %r9,0x1ffe /* BATU(0, BAT_BL_256M, BAT_Vs) */
mtibatu 0,%r9
mtdbatu 0,%r9
isync
li %r8,0x3030
mtmsr %r8
/* Store ofw call addr */
mr %r21,%r5
lis %r10,0xe00000@ha
stw %r5,ofw_call_addr - _start@l(%r10)
lis %r4,_binary_freeldr_tmp_end@ha
addi %r4,%r4,_binary_freeldr_tmp_end@l
lis %r3,_binary_freeldr_tmp_start@ha
addi %r3,%r3,_binary_freeldr_tmp_start@l
lis %r5,0x8000@ha
addi %r5,%r5,0x8000@l
bl copy_bits
bl zero_registers
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_banner - _start
bl ofw_print_string
bl ofw_print_eol
/* Zero CTR */
mtcr %r31
lis %r3,0x8000@ha
addi %r3,%r3,0x8000@l
mtlr %r3
lis %r3,call_ofw@ha
addi %r3,%r3,call_ofw - _start
b call_freeldr
.align 4
call_freeldr:
/* Get the address of the functions list --
* Note:
* Because of little endian switch we must use an even number of
* instructions here.. Pad with a nop if needed. */
mfmsr %r10
ori %r10,%r10,1
mtmsr %r10
nop
/* Note that this is little-endian from here on */
blr
nop
.align 4
call_ofw:
/* R3 has the function offset to call (n * 4)
* Other arg registers are unchanged.
* Note that these 4 instructions are in reverse order due to
* little-endian convention */
andi. %r0,%r0,65534
mfmsr %r0
mtmsr %r0
/* Now normal ordering resumes */
subi %r1,%r1,0x100
stw %r8,4(%r1)
stw %r9,8(%r1)
stw %r10,12(%r1)
mflr %r8
stw %r8,16(%r1)
lis %r10,0xe00000@ha
add %r9,%r3,%r10
lwz %r3,ofw_functions - _start@l(%r9)
mtctr %r3
mr %r3,%r4
mr %r4,%r5
mr %r5,%r6
mr %r6,%r7
mr %r7,%r8
/* Goto the swapped function */
bctrl
lwz %r8,16(%r1)
mtlr %r8
lwz %r8,4(%r1)
lwz %r9,8(%r1)
lwz %r10,12(%r1)
addi %r1,%r1,0x100
/* Ok, go back to little endian */
mfmsr %r0
ori %r0,%r0,1
mtmsr %r0
/* Note that this is little-endian from here on */
blr
nop
zero_registers:
xor %r2,%r2,%r2
mr %r0,%r2
mr %r3,%r2
mr %r4,%r2
mr %r5,%r2
mr %r6,%r2
mr %r7,%r2
mr %r8,%r2
mr %r9,%r2
mr %r10,%r2
mr %r11,%r2
mr %r12,%r2
mr %r13,%r2
mr %r14,%r2
mr %r15,%r2
mr %r12,%r2
mr %r13,%r2
mr %r14,%r2
mr %r15,%r2
mr %r16,%r2
mr %r17,%r2
mr %r18,%r2
mr %r19,%r2
mr %r20,%r2
mr %r21,%r2
mr %r22,%r2
mr %r23,%r2
mr %r24,%r2
mr %r25,%r2
mr %r26,%r2
mr %r27,%r2
mr %r28,%r2
mr %r29,%r2
mr %r30,%r2
mr %r31,%r2
blr
prim_strlen:
mr %r5,%r3
prim_strlen_loop:
lbz %r4,0(%r3)
cmpi 0,0,%r4,0
beq prim_strlen_done
addi %r3,%r3,1
b prim_strlen_loop
prim_strlen_done:
sub %r3,%r3,%r5
blr
copy_bits:
cmp 0,0,%r3,%r4
beqlr
lwz %r6,0(%r3)
stw %r6,0(%r5)
addi %r3,%r3,4
addi %r5,%r5,4
b copy_bits
ofw_print_string_hook:
bl ofw_print_number
bl ofw_exit
ofw_print_string:
/* Reserve some stack space */
subi %r1,%r1,32
/* Save args */
stw %r3,0(%r1)
/* Save the lr, a scratch register */
stw %r8,8(%r1)
mflr %r8
stw %r8,12(%r1)
/* Load the package name */
lis %r3,0xe00000@ha
addi %r3,%r3,ofw_chosen_name - _start
/* Fire */
bl ofw_finddevice
/* Load up for getprop */
stw %r3,16(%r1)
lis %r4,0xe00000@ha
addi %r4,%r4,ofw_stdout_name - _start
addi %r5,%r1,20
li %r6,4
bl ofw_getprop
/* Measure the string and remember the length */
lwz %r3,0(%r1)
bl prim_strlen
mr %r5,%r3
lwz %r3,20(%r1)
lwz %r4,0(%r1)
/* Write the string */
bl ofw_write
/* Return */
lwz %r8,12(%r1)
mtlr %r8
lwz %r8,8(%r1)
addi %r1,%r1,32
blr
/* Print 8 hex digits representing a number in r3 */
ofw_print_number:
subi %r1,%r1,32
stw %r8,0(%r1)
mflr %r8
stw %r8,4(%r1)
stw %r9,8(%r1)
xor %r9,%r9,%r9
stw %r9,12(%r1)
/* Set up and, devide, shift */
mr %r8,%r3
lis %r6,0xf0000000@ha
lis %r7,0x10000000@ha
li %r9,8
ofw_number_loop:
nop
cmpi 0,0,%r9,0
beq ofw_number_return
subi %r9,%r9,1
/* Body: isolate digit, divide, print */
and %r5,%r6,%r8
divwu %r4,%r5,%r7
srwi %r6,%r6,4
srwi %r7,%r7,4
nop
cmpi 0,0,%r4,10
bge ofw_number_letter
addi %r4,%r4,'0'
b ofw_number_digit_out
ofw_number_letter:
addi %r4,%r4,'A' - 10
ofw_number_digit_out:
stb %r4,12(%r1)
addi %r3,%r1,12
stw %r6,16(%r1)
stw %r7,20(%r1)
stw %r8,24(%r1)
stw %r9,28(%r1)
bl ofw_print_string
lwz %r6,16(%r1)
lwz %r7,20(%r1)
lwz %r8,24(%r1)
lwz %r9,28(%r1)
b ofw_number_loop
ofw_number_return:
/* Return */
lwz %r9,8(%r1)
lwz %r8,4(%r1)
mtlr %r8
lwz %r8,0(%r1)
addi %r1,%r1,32
blr
ofw_print_eol:
subi %r1,%r1,16
stw %r8,0(%r1)
mflr %r8
stw %r8,4(%r1)
li %r4,0x0d0a
sth %r4,8(%r1)
xor %r4,%r4,%r4
sth %r4,10(%r1)
addi %r3,%r1,8
bl ofw_print_string
lwz %r8,4(%r1)
mtlr %r8
lwz %r8,0(%r1)
addi %r1,%r1,16
blr
ofw_print_nothing:
subi %r1,%r1,16
stw %r8,0(%r1)
mflr %r8
stw %r8,4(%r1)
li %r4,0
sth %r4,8(%r1)
xor %r4,%r4,%r4
sth %r4,10(%r1)
addi %r3,%r1,8
bl ofw_print_string
lwz %r8,4(%r1)
mtlr %r8
lwz %r8,0(%r1)
addi %r1,%r1,16
blr
ofw_print_space:
subi %r1,%r1,16
stw %r8,0(%r1)
mflr %r8
stw %r8,4(%r1)
li %r4,0x2000
sth %r4,8(%r1)
xor %r4,%r4,%r4
sth %r4,10(%r1)
addi %r3,%r1,8
bl ofw_print_string
lwz %r8,4(%r1)
mtlr %r8
lwz %r8,0(%r1)
addi %r1,%r1,16
blr
ofw_print_regs:
/* Construct ofw exit call */
subi %r1,%r1,0xa0
stw %r0,0(%r1)
stw %r1,4(%r1)
stw %r2,8(%r1)
stw %r3,12(%r1)
stw %r4,16(%r1)
stw %r5,20(%r1)
stw %r6,24(%r1)
stw %r7,28(%r1)
stw %r8,32(%r1)
stw %r9,36(%r1)
stw %r10,40(%r1)
stw %r11,44(%r1)
stw %r12,48(%r1)
stw %r13,52(%r1)
stw %r14,56(%r1)
stw %r15,60(%r1)
stw %r16,64(%r1)
stw %r17,68(%r1)
stw %r18,72(%r1)
stw %r19,76(%r1)
stw %r20,80(%r1)
stw %r21,84(%r1)
stw %r22,88(%r1)
stw %r23,92(%r1)
stw %r24,96(%r1)
stw %r25,100(%r1)
stw %r26,104(%r1)
stw %r27,108(%r1)
stw %r28,112(%r1)
stw %r29,116(%r1)
stw %r30,120(%r1)
stw %r31,124(%r1)
mflr %r0
stw %r0,128(%r1)
mfcr %r0
stw %r0,132(%r1)
mfctr %r0
stw %r0,136(%r1)
mfmsr %r0
stw %r0,140(%r1)
/* Count at zero */
xor %r0,%r0,%r0
stw %r0,144(%r1)
mr %r3,%r1
stw %r3,148(%r1)
/* Body, print the regname, then the register */
ofw_register_loop:
lwz %r3,144(%r1)
cmpi 0,0,%r3,32
beq ofw_register_special
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_reg_init - _start
bl ofw_print_string
lwz %r3,144(%r1)
bl ofw_print_number
bl ofw_print_space
lwz %r3,144(%r1)
mulli %r3,%r3,4
add %r3,%r1,%r3
lwz %r3,0(%r3)
stw %r3,152(%r1)
bl ofw_print_number
lwz %r3,144(%r1)
addi %r3,%r3,1
stw %r3,144(%r1)
b done_dump
dump_optional:
bl ofw_print_space
bl ofw_print_space
lwz %r3,152(%r1)
lwz %r3,0(%r3)
bl ofw_print_number
bl ofw_print_space
lwz %r3,152(%r1)
lwz %r3,4(%r3)
bl ofw_print_number
bl ofw_print_space
lwz %r3,152(%r1)
lwz %r3,8(%r3)
bl ofw_print_number
bl ofw_print_space
lwz %r3,152(%r1)
lwz %r3,12(%r3)
bl ofw_print_number
bl ofw_print_space
done_dump:
bl ofw_print_eol
b ofw_register_loop
ofw_register_special:
/* LR */
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_reg_lr - _start
bl ofw_print_string
bl ofw_print_space
lwz %r3,128(%r1)
bl ofw_print_number
bl ofw_print_eol
/* CR */
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_reg_cr - _start
bl ofw_print_string
bl ofw_print_space
lwz %r3,132(%r1)
bl ofw_print_number
bl ofw_print_eol
/* CTR */
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_reg_ctr - _start
bl ofw_print_string
bl ofw_print_space
lwz %r3,136(%r1)
bl ofw_print_number
bl ofw_print_eol
/* MSR */
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_reg_msr - _start
bl ofw_print_string
bl ofw_print_space
lwz %r3,140(%r1)
bl ofw_print_number
bl ofw_print_eol
/* Return */
lwz %r0,128(%r1)
mtlr %r0
lwz %r0,0(%r1)
lwz %r2,8(%r1)
lwz %r3,12(%r1)
lwz %r4,16(%r1)
lwz %r5,20(%r1)
lwz %r6,24(%r1)
lwz %r7,28(%r1)
addi %r1,%r1,0xa0
blr
ofw_finddevice_hook:
subi %r1,%r1,32
stw %r3,0(%r1)
mflr %r3
stw %r3,4(%r1)
lwz %r3,0(%r1)
bl ofw_finddevice
stw %r3,0(%r1)
lwz %r3,4(%r1)
mtlr %r3
lwz %r3,0(%r1)
addi %r1,%r1,32
blr
ofw_finddevice:
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,32
/* Store r8, r9, lr */
stw %r8,20(%r1)
stw %r9,24(%r1)
mflr %r8
stw %r8,28(%r1)
/* Get finddevice name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_finddevice_name - _start
stw %r9,0(%r1)
/* 1 Argument and 1 return */
li %r9,1
stw %r9,4(%r1)
stw %r9,8(%r1)
stw %r3,12(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
lwz %r3,16(%r1)
/* Restore registers */
lwz %r8,28(%r1)
mtlr %r8
lwz %r9,24(%r1)
lwz %r8,20(%r1)
addi %r1,%r1,32
/* Return */
blr
ofw_getprop_hook:
/* Reserve stack space:
* 32 bytes for the ofw call
* 12 bytes for r8, r9, lr
*/
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,48
/* Store r8, r9, lr */
stw %r8,32(%r1)
stw %r9,36(%r1)
mflr %r8
stw %r8,40(%r1)
/* Get getprop name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_getprop_name - _start
stw %r9,0(%r1)
/* 4 Argument and 1 return */
li %r9,4
stw %r9,4(%r1)
li %r9,1
stw %r9,8(%r1)
stw %r3,12(%r1) /* Package */
stw %r4,16(%r1) /* Property */
stw %r5,20(%r1) /* Return buffer */
stw %r6,24(%r1) /* Buffer size */
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
/* Workaround to a wierd crash ... not sure what causes it.
* XXX investigate me */
bl ofw_print_nothing
/* Return */
lwz %r3,28(%r1)
/* Restore registers */
lwz %r8,40(%r1)
mtlr %r8
lwz %r9,36(%r1)
lwz %r8,32(%r1)
addi %r1,%r1,48
/* Return */
blr
ofw_getprop:
/* Reserve stack space:
* 32 bytes for the ofw call
* 12 bytes for r8, r9, lr
*/
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,48
/* Store r8, r9, lr */
stw %r8,32(%r1)
stw %r9,36(%r1)
mflr %r8
stw %r8,40(%r1)
/* Get getprop name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_getprop_name - _start
stw %r9,0(%r1)
/* 4 Argument and 1 return */
li %r9,4
stw %r9,4(%r1)
li %r9,1
stw %r9,8(%r1)
stw %r3,12(%r1) /* Package */
stw %r4,16(%r1) /* Property */
stw %r5,20(%r1) /* Return buffer */
stw %r6,24(%r1) /* Buffer size */
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
/* Return */
lwz %r3,28(%r1)
/* Restore registers */
lwz %r8,40(%r1)
mtlr %r8
lwz %r9,36(%r1)
lwz %r8,32(%r1)
addi %r1,%r1,48
/* Return */
blr
ofw_write:
/* Reserve stack space:
* 28 bytes for the ofw call
* 12 bytes for r8, r9, lr
*/
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,48
nop
/* Store r8, r9, lr */
stw %r8,28(%r1)
stw %r9,32(%r1)
mflr %r8
stw %r8,36(%r1)
/* Get write name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_write_name - _start
stw %r9,0(%r1)
/* 3 Arguments and 1 return */
li %r9,3
stw %r9,4(%r1)
li %r9,1
stw %r9,8(%r1)
stw %r3,12(%r1)
stw %r4,16(%r1)
stw %r5,20(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
/* Return */
lwz %r3,24(%r1)
/* Restore registers */
lwz %r8,36(%r1)
mtlr %r8
lwz %r9,32(%r1)
lwz %r8,28(%r1)
addi %r1,%r1,48
/* Return */
blr
ofw_read:
/* Reserve stack space:
* 28 bytes for the ofw call
* 12 bytes for r8, r9, lr
*/
/* Reserve stack space ...
* 20 bytes for the ofw call,
* r8, r9, and lr */
subi %r1,%r1,48
nop
/* Store r8, r9, lr */
stw %r8,28(%r1)
stw %r9,32(%r1)
mflr %r8
stw %r8,36(%r1)
/* Get read name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_read_name - _start
stw %r9,0(%r1)
/* 3 Arguments and 1 return */
li %r9,3
stw %r9,4(%r1)
li %r9,1
stw %r9,8(%r1)
stw %r3,12(%r1)
stw %r4,16(%r1)
stw %r5,20(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
/* Set argument */
mr %r3,%r1
/* Fire */
blrl
/* Return */
lwz %r3,24(%r1)
/* Restore registers */
lwz %r8,36(%r1)
mtlr %r8
lwz %r9,32(%r1)
lwz %r8,28(%r1)
addi %r1,%r1,48
/* Return */
blr
ofw_exit:
lis %r3,0xe00000@ha
addi %r3,%r3,freeldr_halt - _start
bl ofw_print_string
/*
ofw_exit_loop:
b ofw_exit_loop
*/
/* Load the exit name */
lis %r8,0xe00000@ha
addi %r9,%r8,ofw_exit_name - _start
stw %r9,0(%r1)
/* Zero args, zero returns */
xor %r9,%r9,%r9
stw %r9,4(%r1)
stw %r9,8(%r1)
/* Load up the call address */
lwz %r9,ofw_call_addr - _start(%r8)
mtlr %r9
mr %r3,%r1
/* Fire */
blrl
/* No return from exit */
.org 0x1000
freeldr_banner:
.ascii "ReactOS OpenFirmware Boot Program\r\n\0"
freeldr_halt:
.ascii "ReactOS OpenFirmware Boot Program Halting\r\n\0"
freeldr_reg_init:
.ascii "r\0"
freeldr_reg_lr:
.ascii "lr \0"
freeldr_reg_cr:
.ascii "cr \0"
freeldr_reg_ctr:
.ascii "ctr\0"
freeldr_reg_msr:
.ascii "msr\0"
ofw_call_addr:
.long 0
ofw_memory_size:
.long 0
.long 0
.long 0
.long 0
ofw_finddevice_name:
.ascii "finddevice\0"
ofw_getprop_name:
.ascii "getprop\0"
ofw_write_name:
.ascii "write\0"
ofw_read_name:
.ascii "read\0"
ofw_exit_name:
.ascii "exit\0"
ofw_chosen_name:
.ascii "/chosen\0"
ofw_stdout_name:
.ascii "stdout\0"
ofw_memory_name:
.ascii "/memory@0\0"
ofw_reg_name:
.ascii "reg\0"
ofw_functions:
.long ofw_finddevice_hook
.long ofw_getprop_hook
.long ofw_write
.long ofw_read
.long ofw_exit
.long ofw_print_regs
.long ofw_print_string
.long ofw_print_number
.org 0x2000
stack:
.space 0x4000
@@ -28,6 +28,7 @@
#include "../../reactos/registry.h"
#include "hardware.h"
BOOLEAN AcpiPresent = FALSE;
static BOOL
FindAcpiBios(VOID)
@@ -63,6 +64,7 @@ DetectAcpiBios(FRLDRHKEY SystemKey, ULONG *BusNumber)
if (FindAcpiBios())
{
AcpiPresent = TRUE;
/* Create new bus key */
sprintf(Buffer,
"MultifunctionAdapter\\%u", *BusNumber);
@@ -0,0 +1,3 @@
.extern PpcInit
_start:
b PpcInit
@@ -0,0 +1,305 @@
/*
* FreeLoader PowerPC Part
* Copyright (C) 2005 Art Yerkes
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "freeldr.h"
#include "machine.h"
#include "of.h"
extern void BootMain( char * );
extern char *GetFreeLoaderVersionString();
ULONG BootPartition = 0;
ULONG BootDrive = 0;
of_proxy ofproxy;
void *PageDirectoryStart, *PageDirectoryEnd;
static int chosen_package, stdin_handle;
BOOLEAN AcpiPresent = FALSE;
char BootPath[0x100];
void le_swap( const void *start_addr_v,
const void *end_addr_v,
const void *target_addr_v ) {
long *start_addr = (long *)ROUND_DOWN((long)start_addr_v,8),
*end_addr = (long *)ROUND_UP((long)end_addr_v,8),
*target_addr = (long *)ROUND_DOWN((long)target_addr_v,8);
long tmp;
while( start_addr <= end_addr ) {
tmp = start_addr[0];
target_addr[0] = REV(start_addr[1]);
target_addr[1] = REV(tmp);
start_addr += 2;
target_addr += 2;
}
}
int ofw_finddevice( const char *name ) {
int ret, len;
len = strlen(name);
le_swap( name, name + len, name );
ret = ofproxy( 0, (char *)name, NULL, NULL, NULL );
le_swap( name, name + len, name );
return ret;
}
int ofw_getprop( int package, const char *name, void *buffer, int buflen ) {
int ret, len = strlen(name);
le_swap( name, name + len, name );
le_swap( buffer, buffer + buflen, buffer );
ret = ofproxy
( 4, (void *)package, (char *)name, buffer, (void *)buflen );
le_swap( buffer, buffer + buflen, buffer );
le_swap( name, name + len, name );
return ret;
}
int ofw_write( int handle, const char *data, int len ) {
int ret;
le_swap( data, data + len, data );
ret = ofproxy
( 8, (void *)handle, (char *)data, (void *)len, NULL );
le_swap( data, data + len, data );
return ret;
}
int ofw_read( int handle, const char *data, int len ) {
int ret;
le_swap( data, data + len, data );
ret = ofproxy
( 12, (void *)handle, (char *)data, (void *)len, NULL );
le_swap( data, data + len, data );
return ret;
}
void ofw_exit() {
ofproxy( 16, NULL, NULL, NULL, NULL );
}
void ofw_dumpregs() {
ofproxy( 20, NULL, NULL, NULL, NULL );
}
void ofw_print_string( const char *str ) {
int len = strlen(str);
le_swap( (char *)str, str + len, (char *)str );
ofproxy( 24, (void *)str, NULL, NULL, NULL );
le_swap( (char *)str, str + len, (char *)str );
}
void ofw_print_number( int num ) {
ofproxy( 28, (void *)num, NULL, NULL, NULL );
}
void PpcPutChar( int ch ) {
char buf[3];
if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; }
else { buf[0] = ch; buf[1] = 0; }
buf[2] = 0;
ofw_print_string( buf );
}
BOOL PpcConsKbHit() {
return TRUE;
}
int PpcConsGetCh() {
char buf;
ofw_read( stdin_handle, &buf, 1 );
return buf;
}
void PpcVideoClearScreen( UCHAR Attr ) {
ofw_print_string("ClearScreen\n");
}
VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOL Init ) {
printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
return VideoGraphicsMode;
}
/* FIXME: Query */
VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
ofw_print_string("GetDisplaySize\n");
*Width = 640;
*Height = 480;
*Depth = 8;
}
ULONG PpcVideoGetBufferSize() {
ULONG Width, Height, Depth;
ofw_print_string("PpcVideoGetBufferSize\n");
PpcVideoGetDisplaySize( &Width, &Height, &Depth );
return Width * Height * Depth / 8;
}
VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
printf("SetTextCursorPosition(%d,%d)\n", X,Y);
}
VOID PpcVideoHideShowTextCursor( BOOL Show ) {
printf("HideShowTextCursor(%s)\n", Show ? "true" : "false");
}
VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
printf( "\033[%d;%dH%c", Y, X, Ch );
}
VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer );
}
BOOL PpcVideoIsPaletteFixed() {
return FALSE;
}
VOID PpcVideoSetPaletteColor( UCHAR Color,
UCHAR Red, UCHAR Green, UCHAR Blue ) {
printf( "SetPaletteColor(%x,%x,%x,%x)\n", Color, Red, Green, Blue );
}
VOID PpcVideoGetPaletteColor( UCHAR Color,
UCHAR *Red, UCHAR *Green, UCHAR *Blue ) {
printf( "GetPaletteColor(%x)\n", Color);
}
VOID PpcVideoSync() {
printf( "Sync\n" );
}
VOID PpcVideoPrepareForReactOS() {
printf( "PrepareForReactOS\n");
}
/* XXX FIXME:
* According to the linux people (this is backed up by my own experience),
* the memory object in older ofw does not do getprop right.
*
* The "right" way is to probe the pci bridge. *sigh*
*/
ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
ULONG MaxMemoryMapSize ) {
printf("GetMemoryMap(chosen=%x)\n", chosen_package);
BiosMemoryMap[0].Type = MEMTYPE_USABLE;
BiosMemoryMap[0].BaseAddress = 0;
BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
printf( "Returning memory map (%dk total)\n",
(int)BiosMemoryMap[0].Length / 1024 );
return 1;
}
BOOL PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
ULONG SectorCount, PVOID Buffer ) {
printf("DiskReadLogicalSectors\n");
return FALSE;
}
BOOL PpcDiskGetPartitionEntry( ULONG DriveNumber, ULONG PartitionNumber,
PPARTITION_TABLE_ENTRY PartitionTableEntry ) {
printf("GetPartitionEntry(%d,%d)\n", DriveNumber, PartitionNumber);
return FALSE;
}
BOOL PpcDiskGetDriveGeometry( ULONG DriveNumber, PGEOMETRY DriveGeometry ) {
printf("GetGeometry(%d)\n", DriveNumber);
return FALSE;
}
ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
printf("GetCacheableBlockCount\n");
return 0;
}
VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day,
PULONG Hour, PULONG Minute, PULONG Second ) {
printf("RTCGeturrentDateTime\n");
}
VOID PpcHwDetect() {
}
void PpcInit( of_proxy the_ofproxy ) {
ofproxy = the_ofproxy;
chosen_package = ofw_finddevice( "/chosen" );
ofw_getprop( chosen_package, "stdin",
&stdin_handle, sizeof(stdin_handle) );
stdin_handle = REV(stdin_handle);
MachVtbl.ConsPutChar = PpcPutChar;
MachVtbl.ConsKbHit = PpcConsKbHit;
MachVtbl.ConsGetCh = PpcConsGetCh;
printf("chosen_package = %x\n", chosen_package);
MachVtbl.VideoClearScreen = PpcVideoClearScreen;
MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
MachVtbl.VideoGetDisplaySize = PpcVideoGetDisplaySize;
MachVtbl.VideoGetBufferSize = PpcVideoGetBufferSize;
MachVtbl.VideoSetTextCursorPosition = PpcVideoSetTextCursorPosition;
MachVtbl.VideoHideShowTextCursor = PpcVideoHideShowTextCursor;
MachVtbl.VideoPutChar = PpcVideoPutChar;
MachVtbl.VideoCopyOffScreenBufferToVRAM =
PpcVideoCopyOffScreenBufferToVRAM;
MachVtbl.VideoIsPaletteFixed = PpcVideoIsPaletteFixed;
MachVtbl.VideoSetPaletteColor = PpcVideoSetPaletteColor;
MachVtbl.VideoGetPaletteColor = PpcVideoGetPaletteColor;
MachVtbl.VideoSync = PpcVideoSync;
MachVtbl.VideoPrepareForReactOS = PpcVideoPrepareForReactOS;
MachVtbl.GetMemoryMap = PpcGetMemoryMap;
MachVtbl.DiskReadLogicalSectors = PpcDiskReadLogicalSectors;
MachVtbl.DiskGetPartitionEntry = PpcDiskGetPartitionEntry;
MachVtbl.DiskGetDriveGeometry = PpcDiskGetDriveGeometry;
MachVtbl.DiskGetCacheableBlockCount = PpcDiskGetCacheableBlockCount;
MachVtbl.RTCGetCurrentDateTime = PpcRTCGetCurrentDateTime;
MachVtbl.HwDetect = PpcHwDetect;
printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
BootMain("freeldr-ppc");
}
void MachInit() {
int len;
printf( "Determining boot device:\n" );
len = ofw_getprop(chosen_package, "bootpath",
BootPath, sizeof(BootPath));
printf( "Got %d bytes of path\n", len );
BootPath[len] = 0;
printf( "Boot Path: %s\n", BootPath );
printf( "FreeLDR starting\n" );
}
void FrLdrSetupPageDirectory() {
}
void beep() {
}
UCHAR STDCALL READ_PORT_UCHAR(PUCHAR Address) {
return 0xff;
}
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
}
+1 -1
View File
@@ -21,7 +21,7 @@
* Limitations:
* - No support for compressed files.
* - No attribute list support.
* - May crash on currupted filesystem.
* - May crash on corrupted filesystem.
*/
#include <freeldr.h>
@@ -52,6 +52,7 @@
#define MB_INFO_FLAG_BOOT_LOADER_NAME 0x00000200
#define MB_INFO_FLAG_APM_TABLE 0x00000400
#define MB_INFO_FLAG_GRAPHICS_TABLE 0x00000800
#define MB_INFO_FLAG_ACPI_TABLE 0x00001000
#ifndef ASM
/* Do not include here in boot.S. */
@@ -38,6 +38,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
*/
#ifdef __i386__
#include "i386.h"
#elif defined(_M_PPC)
#include "powerpc.h"
#endif
#define L_clz
#define L_udivdi3
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -22,11 +22,11 @@
#define __MEM_H
#ifdef __i386__
#if defined(__i386__) || defined(_PPC_)
#define MM_PAGE_SIZE 4096
#endif // defined __i386__
#endif // defined __i386__ or _PPC_
typedef struct
{
+69 -7
View File
@@ -164,9 +164,7 @@ FrLdrStartup(ULONG Magic)
/* Re-initalize EFLAGS */
Ke386EraseFlags();
/* Get Kernel Base and Set MmSystemRangeStart */
FrLdrGetKernelBase();
/* Get the PAE Mode */
FrLdrGetPaeMode();
/* Initialize the page directory */
@@ -531,6 +529,14 @@ FrLdrMapKernel(FILE *KernelImage)
ULONG_PTR TargetSection;
ULONG SectionSize;
LONG i;
PIMAGE_DATA_DIRECTORY RelocationDDir;
PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
ULONG Count;
ULONG_PTR Address, MaxAddress;
PUSHORT TypeOffset;
ULONG_PTR Delta;
PUSHORT ShortPtr;
PULONG LongPtr;
/* Allocate 1024 bytes for PE Header */
ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024);
@@ -552,8 +558,9 @@ FrLdrMapKernel(FILE *KernelImage)
/* Now read the MZ header to get the offset to the PE Header */
NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew);
/* Save the Image Base */
KernelBase = NtHeader->OptionalHeader.ImageBase;
/* Get Kernel Base */
KernelBase = NtHeader->OptionalHeader.ImageBase;
FrLdrGetKernelBase();
/* Save Entrypoint */
KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
@@ -603,9 +610,64 @@ FrLdrMapKernel(FILE *KernelImage)
Section->Misc.VirtualSize - Section->SizeOfRawData);
}
}
/* Get the Relocation Data Directory */
RelocationDDir = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
/* Now relocate the file */
/* FIXME: ADD RELOC CODE */
/* Get the Relocation Section Start and End*/
RelocationDir = (PIMAGE_BASE_RELOCATION)(KERNEL_BASE_PHYS + RelocationDDir->VirtualAddress);
RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
/* Calculate Difference between Real Base and Compiled Base*/
Delta = KernelBase - NtHeader->OptionalHeader.ImageBase;;
/* Determine how far we shoudl relocate */
MaxAddress = KERNEL_BASE_PHYS + ImageSize;
/* Relocate until we've processed all the blocks */
while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) {
/* See how many Relocation Blocks we have */
Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
/* Calculate the Address of this Directory */
Address = KERNEL_BASE_PHYS + RelocationDir->VirtualAddress;
/* Calculate the Offset of the Type */
TypeOffset = (PUSHORT)(RelocationDir + 1);
for (i = 0; i < Count; i++) {
ShortPtr = (PUSHORT)(Address + (*TypeOffset & 0xFFF));
/* Don't relocate after the end of the loaded driver */
if ((ULONG_PTR)ShortPtr >= MaxAddress) break;
switch (*TypeOffset >> 12) {
case IMAGE_REL_BASED_ABSOLUTE:
break;
case IMAGE_REL_BASED_HIGH:
*ShortPtr += HIWORD(Delta);
break;
case IMAGE_REL_BASED_LOW:
*ShortPtr += LOWORD(Delta);
break;
case IMAGE_REL_BASED_HIGHLOW:
LongPtr = (PULONG)ShortPtr;
*LongPtr += Delta;
break;
}
TypeOffset++;
}
/* Move to the next Relocation Table */
RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
}
/* Increase the next Load Base */
NextModuleBase = ROUND_UP(KERNEL_BASE_PHYS + ImageSize, PAGE_SIZE);
@@ -578,8 +578,9 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
PARTITION_TABLE_ENTRY PartitionTableEntry;
ULONG rosPartition;
extern ULONG PageDirectoryStart;
extern ULONG PageDirectoryEnd;
extern ULONG PageDirectoryStart;
extern ULONG PageDirectoryEnd;
extern BOOLEAN AcpiPresent;
//
// Open the operating system section
@@ -596,8 +597,8 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
* Setup multiboot information structure
*/
LoaderBlock.Flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
LoaderBlock.BootDevice = 0xffffffff;
LoaderBlock.CommandLine = (unsigned long)multiboot_kernel_cmdline;
LoaderBlock.ModsCount = 0;
@@ -734,6 +735,7 @@ LoadAndBootReactOS(PUCHAR OperatingSystemName)
*/
MachHwDetect();
if (AcpiPresent) LoaderBlock.Flags |= MB_INFO_FLAG_ACPI_TABLE;
UiDrawStatusText("Loading...");
UiDrawProgressBarCenter(0, 100, "Loading ReactOS...");
+16 -13
View File
@@ -20,6 +20,7 @@
#include <freeldr.h>
#include <machine.h>
#include <rtl.h>
#include <stdarg.h>
/*
* print() - prints unformatted text to stdout
@@ -38,12 +39,11 @@ void print(char *str)
*/
void printf(char *format, ... )
{
int *dataptr = (int *)(void *)&format;
va_list ap;
va_start(ap,format);
char c, *ptr, str[16];
int ll;
dataptr++;
while ((c = *(format++)))
{
if (c != '%')
@@ -66,11 +66,11 @@ void printf(char *format, ... )
case 'd': case 'u': case 'x':
if (ll)
{
*convert_i64_to_ascii(str, c, *((unsigned long long *) dataptr++)) = 0;
*convert_i64_to_ascii(str, c, va_arg(ap, unsigned long long)) = 0;
}
else
{
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
*convert_to_ascii(str, c, va_arg(ap, unsigned long)) = 0;
}
ptr = str;
@@ -81,10 +81,10 @@ void printf(char *format, ... )
}
break;
case 'c': MachConsPutChar((*(dataptr++))&0xff); break;
case 'c': MachConsPutChar((va_arg(ap,int))&0xff); break;
case 's':
ptr = (char *)(*(dataptr++));
ptr = va_arg(ap,char *);
while ((c = *(ptr++)))
{
@@ -100,16 +100,18 @@ void printf(char *format, ... )
}
}
}
va_end(ap);
}
void sprintf(char *buffer, char *format, ... )
{
int *dataptr = (int *)(void *)&format;
va_list ap;
char c, *ptr, str[16];
char *p = buffer;
int ll;
dataptr++;
va_start(ap,format);
while ((c = *(format++)))
{
@@ -134,11 +136,11 @@ void sprintf(char *buffer, char *format, ... )
case 'd': case 'u': case 'x':
if (ll)
{
*convert_i64_to_ascii(str, c, *((unsigned long long*) dataptr++)) = 0;
*convert_i64_to_ascii(str, c, va_arg(ap, unsigned long long)) = 0;
}
else
{
*convert_to_ascii(str, c, *((unsigned long *) dataptr++)) = 0;
*convert_to_ascii(str, c, va_arg(ap, unsigned long)) = 0;
}
ptr = str;
@@ -151,12 +153,12 @@ void sprintf(char *buffer, char *format, ... )
break;
case 'c':
*p = (*(dataptr++))&0xff;
*p = va_arg(ap,int)&0xff;
p++;
break;
case 's':
ptr = (char *)(*(dataptr++));
ptr = va_arg(ap,char *);
while ((c = *(ptr++)))
{
@@ -174,5 +176,6 @@ void sprintf(char *buffer, char *format, ... )
}
}
}
va_end(ap);
*p=0;
}
+3 -5
View File
@@ -17,16 +17,15 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* convert_to_ascii() - converts a number to it's ascii equivalent
* from:
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1996 Erich Boleyn <erich@uruk.org>
*/
char *convert_to_ascii(char *buf, int c, ...)
char *convert_to_ascii(char *buf, int c, int num)
{
unsigned long num = *((&c) + 1), mult = 10;
unsigned long mult = 10;
char *ptr = buf;
if (c == 'x')
@@ -63,9 +62,8 @@ char *convert_to_ascii(char *buf, int c, ...)
return ptr;
}
char *convert_i64_to_ascii(char *buf, int c, ...)
char *convert_i64_to_ascii(char *buf, int c, unsigned long long num)
{
unsigned long long num = *(long long*)((&c) + 1);
int mult = 10;
char *ptr = buf;
+129
View File
@@ -344,4 +344,133 @@ HKCR,"NDS\Clsid","",0x00000002,"{323991f0-7bad-11cf-b03d-00aa006e0975}"
HKCR,"WinNT\Clsid","",0x00000002,"{8b20cd60-0f29-11cf-abc4-02608c9e7553}"
; For language support:
HKCR,"MIME",,0x00000012
HKCR,"MIME\Database",,0x00000012
HKCR,"MIME\Database\Rfc1766",,0x00000012
HKCR,"MIME\Database\Rfc1766","0436",0x00000000,"af;Afrikaans"
HKCR,"MIME\Database\Rfc1766","041C",0x00000000,"sq;Albanian"
HKCR,"MIME\Database\Rfc1766","0001",0x00000000,"ar;Arabic"
HKCR,"MIME\Database\Rfc1766","0401",0x00000000,"ar-sa;Arabic (Saudi Arabia)"
HKCR,"MIME\Database\Rfc1766","0801",0x00000000,"ar-iq;Arabic (Iraq)"
HKCR,"MIME\Database\Rfc1766","0C01",0x00000000,"ar-eg;Arabic (Egypt)"
HKCR,"MIME\Database\Rfc1766","1001",0x00000000,"ar-ly;Arabic (Libya)"
HKCR,"MIME\Database\Rfc1766","1401",0x00000000,"ar-dz;Arabic (Algeria)"
HKCR,"MIME\Database\Rfc1766","1801",0x00000000,"ar-ma;Arabic (Morocco)"
HKCR,"MIME\Database\Rfc1766","1C01",0x00000000,"ar-tn;Arabic (Tunisia)"
HKCR,"MIME\Database\Rfc1766","2001",0x00000000,"ar-om;Arabic (Oman)"
HKCR,"MIME\Database\Rfc1766","2401",0x00000000,"ar-ye;Arabic (Yemen)"
HKCR,"MIME\Database\Rfc1766","2801",0x00000000,"ar-sy;Arabic (Syria)"
HKCR,"MIME\Database\Rfc1766","2C01",0x00000000,"ar-jo;Arabic (Jordan)"
HKCR,"MIME\Database\Rfc1766","3001",0x00000000,"ar-lb;Arabic (Lebanon)"
HKCR,"MIME\Database\Rfc1766","3401",0x00000000,"ar-kw;Arabic (Kuwait)"
HKCR,"MIME\Database\Rfc1766","3801",0x00000000,"ar-ae;Arabic (U.A.E.)"
HKCR,"MIME\Database\Rfc1766","3C01",0x00000000,"ar-bh;Arabic (Bahrain)"
HKCR,"MIME\Database\Rfc1766","4001",0x00000000,"ar-qa;Arabic (Qatar)"
HKCR,"MIME\Database\Rfc1766","042D",0x00000000,"eu;Basque"
HKCR,"MIME\Database\Rfc1766","0402",0x00000000,"bg;Bulgarian"
HKCR,"MIME\Database\Rfc1766","0423",0x00000000,"be;Belarusian"
HKCR,"MIME\Database\Rfc1766","0403",0x00000000,"ca;Catalan"
HKCR,"MIME\Database\Rfc1766","0004",0x00000000,"zh;Chinese"
HKCR,"MIME\Database\Rfc1766","0404",0x00000000,"zh-tw;Chinese (Taiwan)"
HKCR,"MIME\Database\Rfc1766","0804",0x00000000,"zh-cn;Chinese (China)"
HKCR,"MIME\Database\Rfc1766","0C04",0x00000000,"zh-hk;Chinese (Hong Kong SAR)"
HKCR,"MIME\Database\Rfc1766","1004",0x00000000,"zh-sg;Chinese (Singapore)"
HKCR,"MIME\Database\Rfc1766","041A",0x00000000,"hr;Croatian"
HKCR,"MIME\Database\Rfc1766","0405",0x00000000,"cs;Czech"
HKCR,"MIME\Database\Rfc1766","0406",0x00000000,"da;Danish"
HKCR,"MIME\Database\Rfc1766","0413",0x00000000,"nl;Dutch (Netherlands)"
HKCR,"MIME\Database\Rfc1766","0813",0x00000000,"nl-be;Dutch (Belgium)"
HKCR,"MIME\Database\Rfc1766","0009",0x00000000,"en;English"
HKCR,"MIME\Database\Rfc1766","0409",0x00000000,"en-us;English (United States)"
HKCR,"MIME\Database\Rfc1766","0809",0x00000000,"en-gb;English (United Kingdom)"
HKCR,"MIME\Database\Rfc1766","0C09",0x00000000,"en-au;English (Australia)"
HKCR,"MIME\Database\Rfc1766","1009",0x00000000,"en-ca;English (Canada)"
HKCR,"MIME\Database\Rfc1766","1409",0x00000000,"en-nz;English (New Zealand)"
HKCR,"MIME\Database\Rfc1766","1809",0x00000000,"en-ie;English (Ireland)"
HKCR,"MIME\Database\Rfc1766","1C09",0x00000000,"en-za;English (South Africa)"
HKCR,"MIME\Database\Rfc1766","2009",0x00000000,"en-jm;English (Jamaica)"
HKCR,"MIME\Database\Rfc1766","2809",0x00000000,"en-bz;English (Belize)"
HKCR,"MIME\Database\Rfc1766","2C09",0x00000000,"en-tt;English (Trinidad)"
HKCR,"MIME\Database\Rfc1766","0425",0x00000000,"et;Estonian"
HKCR,"MIME\Database\Rfc1766","0438",0x00000000,"fo;Faeroese"
HKCR,"MIME\Database\Rfc1766","0429",0x00000000,"fa;Farsi"
HKCR,"MIME\Database\Rfc1766","040B",0x00000000,"fi;Finnish"
HKCR,"MIME\Database\Rfc1766","040C",0x00000000,"fr;French (France)"
HKCR,"MIME\Database\Rfc1766","080C",0x00000000,"fr-be;French (Belgium)"
HKCR,"MIME\Database\Rfc1766","0C0C",0x00000000,"fr-ca;French (Canada)"
HKCR,"MIME\Database\Rfc1766","100C",0x00000000,"fr-ch;French (Switzerland)"
HKCR,"MIME\Database\Rfc1766","140C",0x00000000,"fr-lu;French (Luxembourg)"
HKCR,"MIME\Database\Rfc1766","043C",0x00000000,"gd;Gaelic"
HKCR,"MIME\Database\Rfc1766","0407",0x00000000,"de;German (Germany)"
HKCR,"MIME\Database\Rfc1766","0807",0x00000000,"de-ch;German (Switzerland)"
HKCR,"MIME\Database\Rfc1766","0C07",0x00000000,"de-at;German (Austria)"
HKCR,"MIME\Database\Rfc1766","1007",0x00000000,"de-lu;German (Luxembourg)"
HKCR,"MIME\Database\Rfc1766","1407",0x00000000,"de-li;German (Liechtenstein)"
HKCR,"MIME\Database\Rfc1766","0408",0x00000000,"el;Greek"
HKCR,"MIME\Database\Rfc1766","040D",0x00000000,"he;Hebrew"
HKCR,"MIME\Database\Rfc1766","0439",0x00000000,"hi;Hindi"
HKCR,"MIME\Database\Rfc1766","040E",0x00000000,"hu;Hungarian"
HKCR,"MIME\Database\Rfc1766","040F",0x00000000,"is;Icelandic"
HKCR,"MIME\Database\Rfc1766","0421",0x00000000,"in;Indonesian"
HKCR,"MIME\Database\Rfc1766","0410",0x00000000,"it;Italian (Italy)"
HKCR,"MIME\Database\Rfc1766","0810",0x00000000,"it-ch;Italian (Switzerland)"
HKCR,"MIME\Database\Rfc1766","0411",0x00000000,"ja;Japanese"
HKCR,"MIME\Database\Rfc1766","0412",0x00000000,"ko;Korean"
HKCR,"MIME\Database\Rfc1766","0426",0x00000000,"lv;Latvian"
HKCR,"MIME\Database\Rfc1766","0427",0x00000000,"lt;Lithuanian"
HKCR,"MIME\Database\Rfc1766","042F",0x00000000,"mk;FYRO Macedonian"
HKCR,"MIME\Database\Rfc1766","043E",0x00000000,"ms;Malay (Malaysia)"
HKCR,"MIME\Database\Rfc1766","043A",0x00000000,"mt;Maltese"
HKCR,"MIME\Database\Rfc1766","0414",0x00000000,"no;Norwegian (Bokmal)"
HKCR,"MIME\Database\Rfc1766","0814",0x00000000,"no;Norwegian (Nynorsk)"
HKCR,"MIME\Database\Rfc1766","0415",0x00000000,"pl;Polish"
HKCR,"MIME\Database\Rfc1766","0416",0x00000000,"pt-br;Portuguese (Brazil)"
HKCR,"MIME\Database\Rfc1766","0816",0x00000000,"pt;Portuguese (Portugal)"
HKCR,"MIME\Database\Rfc1766","0417",0x00000000,"rm;Rhaeto-Romanic"
HKCR,"MIME\Database\Rfc1766","0418",0x00000000,"ro;Romanian"
HKCR,"MIME\Database\Rfc1766","0818",0x00000000,"ro-mo;Romanian (Moldova)"
HKCR,"MIME\Database\Rfc1766","0419",0x00000000,"ru;Russian"
HKCR,"MIME\Database\Rfc1766","0819",0x00000000,"ru-mo;Russian (Moldova)"
HKCR,"MIME\Database\Rfc1766","0C1A",0x00000000,"sr;Serbian (Cyrillic)"
HKCR,"MIME\Database\Rfc1766","081A",0x00000000,"sr;Serbian (Latin)"
HKCR,"MIME\Database\Rfc1766","041B",0x00000000,"sk;Slovak"
HKCR,"MIME\Database\Rfc1766","0424",0x00000000,"sl;Slovenian"
HKCR,"MIME\Database\Rfc1766","042E",0x00000000,"sb;Sorbian"
HKCR,"MIME\Database\Rfc1766","040A",0x00000000,"es;Spanish (Traditional Sort)"
HKCR,"MIME\Database\Rfc1766","080A",0x00000000,"es-mx;Spanish (Mexico)"
HKCR,"MIME\Database\Rfc1766","0C0A",0x00000000,"es;Spanish (International Sort)"
HKCR,"MIME\Database\Rfc1766","100A",0x00000000,"es-gt;Spanish (Guatemala)"
HKCR,"MIME\Database\Rfc1766","140A",0x00000000,"es-cr;Spanish (Costa Rica)"
HKCR,"MIME\Database\Rfc1766","180A",0x00000000,"es-pa;Spanish (Panama)"
HKCR,"MIME\Database\Rfc1766","1C0A",0x00000000,"es-do;Spanish (Dominican Republic)"
HKCR,"MIME\Database\Rfc1766","200A",0x00000000,"es-ve;Spanish (Venezuela)"
HKCR,"MIME\Database\Rfc1766","240A",0x00000000,"es-co;Spanish (Colombia)"
HKCR,"MIME\Database\Rfc1766","280A",0x00000000,"es-pe;Spanish (Peru)"
HKCR,"MIME\Database\Rfc1766","2C0A",0x00000000,"es-ar;Spanish (Argentina)"
HKCR,"MIME\Database\Rfc1766","300A",0x00000000,"es-ec;Spanish (Ecuador)"
HKCR,"MIME\Database\Rfc1766","340A",0x00000000,"es-cl;Spanish (Chile)"
HKCR,"MIME\Database\Rfc1766","380A",0x00000000,"es-uy;Spanish (Uruguay)"
HKCR,"MIME\Database\Rfc1766","3C0A",0x00000000,"es-py;Spanish (Paraguay)"
HKCR,"MIME\Database\Rfc1766","400A",0x00000000,"es-bo;Spanish (Bolivia)"
HKCR,"MIME\Database\Rfc1766","440A",0x00000000,"es-sv;Spanish (El Salvador)"
HKCR,"MIME\Database\Rfc1766","480A",0x00000000,"es-hn;Spanish (Honduras)"
HKCR,"MIME\Database\Rfc1766","4C0A",0x00000000,"es-ni;Spanish (Nicaragua)"
HKCR,"MIME\Database\Rfc1766","500A",0x00000000,"es-pr;Spanish (Puerto Rico)"
HKCR,"MIME\Database\Rfc1766","0430",0x00000000,"sx;Sutu"
HKCR,"MIME\Database\Rfc1766","041D",0x00000000,"sv;Swedish"
HKCR,"MIME\Database\Rfc1766","081D",0x00000000,"sv-fi;Swedish (Finland)"
HKCR,"MIME\Database\Rfc1766","041E",0x00000000,"th;Thai"
HKCR,"MIME\Database\Rfc1766","0431",0x00000000,"ts;Tsonga"
HKCR,"MIME\Database\Rfc1766","0432",0x00000000,"tn;Tswana"
HKCR,"MIME\Database\Rfc1766","041F",0x00000000,"tr;Turkish"
HKCR,"MIME\Database\Rfc1766","0422",0x00000000,"uk;Ukrainian"
HKCR,"MIME\Database\Rfc1766","0420",0x00000000,"ur;Urdu"
HKCR,"MIME\Database\Rfc1766","042A",0x00000000,"vi;Vietnamese"
HKCR,"MIME\Database\Rfc1766","0434",0x00000000,"xh;Xhosa"
HKCR,"MIME\Database\Rfc1766","043D",0x00000000,"ji;Yiddish"
HKCR,"MIME\Database\Rfc1766","0435",0x00000000,"zu;Zulu"
; EOF
+21 -2
View File
@@ -257,10 +257,10 @@ HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management","Pagin
; Subsystems
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Debug",0x00020000,""
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Kmode",0x00020000,"%SystemRoot%\system32\win32k.sys"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Optional",0x00070001,50,00,6f,00,73,00,69,00,78,00,00,00,4f,00,73,00,32,00,00,00,00,00
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Optional",0x00010000,"Posix","Os2"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Os2",0x00020000,"%SystemRoot%\system32\os2ss.exe"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Posix",0x00020000,"%SystemRoot%\system32\psxss.exe"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Required",0x00070001,44,00,65,00,62,00,75,00,67,00,00,00,57,00,69,00,6e,00,64,00,6f,00,77,00,73,00,00,00,00,00
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Required",0x00010000,"Debug","Windows"
HKLM,"SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems","Windows",0x00020000,"%SystemRoot%\system32\csrss.exe"
; 3Com 3c905 Driver
@@ -469,6 +469,19 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","ImagePath",0x00020000,"system
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Keyboard","Type",0x00010001,0x00000001
; Serial port enumerator
HKLM,"SYSTEM\CurrentControlSet\Services\serenum","ErrorControl",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Group",0x00000000,"PNP Filter"
HKLM,"SYSTEM\CurrentControlSet\Services\serenum","ImagePath",0x00020000,"system32\drivers\serenum.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Start",0x00010001,0x00000003
HKLM,"SYSTEM\CurrentControlSet\Services\serenum","Type",0x00010001,0x00000001
;hard coded values
HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","0",0x00000000,"ACPI\PNP0501"
HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","Count",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\serenum\Enum","NextInstance",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1","UpperFilters",0x00010000,"serenum"
HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\2","UpperFilters",0x00010000,"serenum"
; SB16 driver
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","Group",0x00000000,"Base"
HKLM,"SYSTEM\CurrentControlSet\Services\sndblst","ServiceType",0x00010001,0x00000001
@@ -676,6 +689,12 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Group",0x00000000,"Base"
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","ImagePath",0x00020000,"system32\drivers\serial.sys"
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Start",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Serial","Type",0x00010001,0x00000001
;hard coded values
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","0",0x00000000,"ACPI\PNP0501"
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","Count",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Services\Serial\Enum","NextInstance",0x00010001,0x00000001
HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\1","Service",0x00000000,"serial"
HKLM,"SYSTEM\CurrentControlSet\Enum\ACPI\PNP0501\2","Service",0x00000000,"serial"
; Packet driver
HKLM,"SYSTEM\CurrentControlSet\Services\Packet","ErrorControl",0x00010001,0x00000001
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 25 KiB

+6 -1
View File
@@ -29,6 +29,7 @@ Signature = "$ReactOS$"
drivers\bus\acpi\acpi.sys 2
drivers\bus\isapnp\isapnp.sys 2
drivers\bus\pci\pci.sys 2
drivers\bus\serenum\serenum.sys 2
drivers\dd\beep\beep.sys 2
drivers\dd\bootvid\bootvid.sys 2
drivers\dd\null\null.sys 2
@@ -99,6 +100,7 @@ lib\mpr\mpr.dll 1
lib\msacm\msacm32.dll 1
lib\msafd\msafd.dll 1
lib\msgina\msgina.dll 1
lib\msi\msi.dll 1
lib\msimg32\msimg32.dll 1
lib\msvcrt\msvcrt.dll 1
lib\msvcrt20\msvcrt20.dll 1
@@ -108,10 +110,12 @@ lib\ole32\ole32.dll 1
lib\oleaut32\oleaut32.dll 1
lib\olepro32\olepro32.dll 1
lib\psapi\psapi.dll 1
lib\riched20\riched20.dll 1
lib\richedit\riched32.dll 1
lib\rpcrt4\rpcrt4.dll 1
lib\samlib\samlib.dll 1
lib\secur32\secur32.dll 1
lib\serialui\serialui.dll 1
lib\setupapi\setupapi.dll 1
lib\shdocvw\shdocvw.dll 1
lib\shell32\shell32.dll 1
@@ -146,8 +150,9 @@ subsys\system\cmd\cmd.exe 1
subsys\system\explorer\explorer.exe 4
subsys\system\explorer\explorer-cfg-template.xml 4
subsys\system\explorer\notifyhook\notifyhook.dll 1
subsys\system\ibrowser\ibrowser.exe 1
subsys\system\format\format.exe 1
subsys\system\ibrowser\ibrowser.exe 1
subsys\system\msiexec\msiexec.exe 1
subsys\system\notepad\notepad.exe 1
subsys\system\regedit\regedit.exe 4
subsys\system\regsvr32\regsvr32.exe 1
+30 -27
View File
@@ -26,52 +26,55 @@ This will allow you to use the WINE tools and librarys with very little
work to import a new dll.
The following build tools are derived from Wine.
reactos/tools/unicode # Synced to Wine-20050310
reactos/tools/wpp # Synced to Wine-20050310
reactos/tools/bin2res # Resource to binary converter
reactos/tools/winebuild # Synced to Wine-20050211
reactos/tools/winebuild # Synced to Wine-20050310
reactos/tools/wmc # Wine Message Compiler
reactos/tools/wrc # Synced to Wine-20050211
reactos/tools/wrc # Synced to Wine-20050310
reactos/tools/widl # Synced to Wine-20050310
The following shared libraries are a 100% port from Winehq sources.
reactos/lib/cabinet # Synced to Wine-20050211
reactos/lib/comctl32 # Synced to Wine-20050211
reactos/lib/comdlg32 # Synced to Wine-20050211
reactos/lib/dinput # Synced to Wine-20050211
reactos/lib/dinput8 # Synced to Wine-20050211
reactos/lib/icmp # Synced to Wine-20050211
reactos/lib/cabinet # Synced to Wine-20050310
reactos/lib/comctl32 # Synced to Wine-20050310
reactos/lib/comdlg32 # Synced to Wine-20050310
reactos/lib/dinput # Synced to Wine-20050310
reactos/lib/dinput8 # Synced to Wine-20050310
reactos/lib/icmp # Synced to Wine-20050310
reactos/lib/iphlpapi # Out of sync
reactos/lib/imagehlp # Patches for BindImage need review and submission to winehq.
reactos/lib/msvcrt20 # Out of sync
reactos/lib/mpr # Synced to Wine-20050211
reactos/lib/mpr # Synced to Wine-20050310
reactos/lib/msacm # Out of sync
reactos/lib/msimg32 # Synced to Wine-20050211
reactos/lib/msi # Synced to Wine-20050211
reactos/lib/msimg32 # Synced to Wine-20050310
reactos/lib/msi # Synced to Wine-20050310
reactos/lib/msvideo # Out of sync
reactos/lib/netapi32 # Out of sync
reactos/lib/odbc32 # In sync. Depends on port of Linux ODBC.
reactos/lib/ole32 # Synced to Wine-20050211
reactos/lib/oleaut32 # Synced to Wine-20050211
reactos/lib/oledlg # Synced to Wine-20050211
reactos/lib/olepro32 # Synced to Wine-20050211
reactos/lib/richedit # Synced to Wine-20050211
reactos/lib/rpcrt4 # Synced to Wine-20050211
reactos/lib/setupapi # Synced to Wine-20050125 # CVS
reactos/lib/shell32 # Synced to Wine-20050211
reactos/lib/shdocvw # Synced to Wine-20050211
reactos/lib/shlwapi # Synced to Wine-20050211
reactos/lib/ole32 # Synced to Wine-20050310
reactos/lib/oleaut32 # Synced to Wine-20050310
reactos/lib/oledlg # Synced to Wine-20050310
reactos/lib/olepro32 # Synced to Wine-20050310
reactos/lib/riched20 # Synced to Wine-20050310
reactos/lib/richedit # Synced to Wine-20050310
reactos/lib/rpcrt4 # Synced to Wine-20050310
reactos/lib/setupapi # Synced to Wine-20050310
reactos/lib/shell32 # Synced to Wine-20050310
reactos/lib/shdocvw # Synced to Wine-20050310
reactos/lib/shlwapi # Synced to Wine-20050310
reactos/lib/twain # Out of sync
reactos/lib/unicode # Dependancy on this lib needs to be removed. Synced to Wine-20050211
reactos/lib/urlmon # Synced to Wine-20050211
reactos/lib/urlmon # Synced to Wine-20050310
reactos/lib/version # Out of sync
reactos/lib/wininet # Out of sync
reactos/lib/winmm # Synced to Wine-20050211
reactos/lib/winmm/midimap # Synced to Wine-20050211
reactos/lib/winmm/wavemap # Synced to Wine-20050211
reactos/lib/winmm # Synced to Wine-20050310
reactos/lib/winmm/midimap # Synced to Wine-20050310
reactos/lib/winmm/wavemap # Synced to Wine-20050310
ReactOS shares the following programs with Winehq.
reactos/subsys/system/regedit # Out of sync
reactos/subsys/system/expand # Out of sync
reactos/subsys/system/msiexec # Synced to Wine-20050211
reactos/subsys/system/msiexec # Synced to Wine-20050311
In addition the following libs, dlls and source files are mostly based on code ported
from Winehq CVS. If you are looking to update something in these files
+103
View File
@@ -0,0 +1,103 @@
/*
Boiler plate for irp cancelation, for irp queues you manage yourself
-Gunnar
*/
CancelRoutine(
DEV_OBJ Dev,
Irp
)
{
//don't need this since we have our own sync. protecting irp cancellation
IoReleaseCancelSpinLock(Irp->CancelIrql);
theLock = Irp->Tail.Overlay.DriverContext[3];
Lock(theLock);
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
Unlock(theLock);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
QUEUE_BOLIERPLATE
{
Lock(theLock);
Irp->Tail.Overlay.DriverContext[3] = &theLock;
IoSetCancelRoutine(Irp, CancelRoutine);
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
{
/*
Irp has already been cancelled (before we got to queue it),
and we got to remove the cancel routine before the canceler could,
so we cancel/complete the irp ourself.
*/
Unlock(theLock);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return FALSE;
}
//else were ok
Irp->IoStatus.Status = STATUS_PENDING;
IoMarkIrpPending(Irp);
InsertTailList(Queue);
Unlock(theLock);
}
DEQUEUE_BOILERPLATE
{
Lock(theLock);
Irp = RemoveHeadList(Queue);
if (!IoSetCancelRoutine(Irp, NULL))
{
/*
Cancel routine WILL be called after we release the spinlock. It will try to remove
the irp from the list and cancel/complete this irp. Since we allready removed it,
make its ListEntry point to itself.
*/
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
Unlock(theLock);
return;
}
/*
Cancel routine will NOT be called, canceled or not.
The Irp might have been canceled (Irp->Cancel flag set) but we don't care,
since we are to complete this Irp now anyways.
*/
Unlock(theLock);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+1 -1
View File
@@ -6,7 +6,7 @@ PATH_TO_TOP = ../..
include $(PATH_TO_TOP)/rules.mak
DRIVERS = acpi isapnp pci
DRIVERS = acpi isapnp pci serenum
all: $(DRIVERS)
+184 -9
View File
@@ -4,6 +4,7 @@
* FILE: acpi/ospm/fdo.c
* PURPOSE: ACPI device object dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* Hervé Poussineau (hpoussin@reactos.com)
* UPDATE HISTORY:
* 08-08-2001 CSH Created
*/
@@ -60,12 +61,7 @@ AcpiCreateDeviceIDString(PUNICODE_STRING DeviceID,
L"ACPI\\%S",
Node->device.id.hid);
if (!AcpiCreateUnicodeString(DeviceID, Buffer, PagedPool))
{
return FALSE;
}
return TRUE;
return AcpiCreateUnicodeString(DeviceID, Buffer, PagedPool);
}
@@ -108,8 +104,158 @@ BOOLEAN
AcpiCreateInstanceIDString(PUNICODE_STRING InstanceID,
BM_NODE *Node)
{
/* FIXME: Create unique instnce id. */
return AcpiCreateUnicodeString(InstanceID, L"0000", PagedPool);
WCHAR Buffer[10];
if (Node->device.id.uid[0])
swprintf(Buffer, L"%S", Node->device.id.uid);
else
/* FIXME: Generate unique id! */
swprintf(Buffer, L"0000");
return AcpiCreateUnicodeString(InstanceID, Buffer, PagedPool);
}
static BOOLEAN
AcpiCreateResourceList(PCM_RESOURCE_LIST* pResourceList,
PULONG ResourceListSize,
RESOURCE* resources)
{
BOOLEAN Done;
ULONG NumberOfResources = 0;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
RESOURCE* resource;
ULONG i;
KIRQL Dirql;
/* Count number of resources */
Done = FALSE;
resource = resources;
while (!Done)
{
switch (resource->id)
{
case irq:
{
IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
NumberOfResources += irq_data->number_of_interrupts;
break;
}
case dma:
{
DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
NumberOfResources += dma_data->number_of_channels;
break;
}
case io:
{
NumberOfResources++;
break;
}
case end_tag:
{
Done = TRUE;
break;
}
}
resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
}
/* Allocate memory */
*ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (NumberOfResources - 1);
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool(PagedPool, *ResourceListSize);
*pResourceList = ResourceList;
if (!ResourceList)
return FALSE;
ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = Internal; /* FIXME */
ResourceList->List[0].BusNumber = 0; /* We're the only ACPI bus device in the system */
ResourceList->List[0].PartialResourceList.Version = 1;
ResourceList->List[0].PartialResourceList.Revision = 1;
ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
/* Fill resources list structure */
Done = FALSE;
resource = resources;
while (!Done)
{
switch (resource->id)
{
case irq:
{
IRQ_RESOURCE *irq_data = (IRQ_RESOURCE*) &resource->data;
for (i = 0; i < irq_data->number_of_interrupts; i++)
{
ResourceDescriptor->Type = CmResourceTypeInterrupt;
ResourceDescriptor->ShareDisposition =
(irq_data->shared_exclusive == SHARED ? CmResourceShareShared : CmResourceShareDeviceExclusive);
ResourceDescriptor->Flags =
(irq_data->edge_level == LEVEL_SENSITIVE ? CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE : CM_RESOURCE_INTERRUPT_LATCHED);
ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
Internal, 0, 0, irq_data->interrupts[i],
&Dirql,
&ResourceDescriptor->u.Interrupt.Affinity);
ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
ResourceDescriptor++;
}
break;
}
case dma:
{
DMA_RESOURCE *dma_data = (DMA_RESOURCE*) &resource->data;
for (i = 0; i < dma_data->number_of_channels; i++)
{
ResourceDescriptor->Type = CmResourceTypeDma;
ResourceDescriptor->Flags = 0;
switch (dma_data->type)
{
case TYPE_A: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_A; break;
case TYPE_B: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_B; break;
case TYPE_F: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_TYPE_F; break;
}
if (dma_data->bus_master == BUS_MASTER)
ResourceDescriptor->Flags |= CM_RESOURCE_DMA_BUS_MASTER;
switch (dma_data->transfer)
{
case TRANSFER_8: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8; break;
case TRANSFER_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16; break;
case TRANSFER_8_16: ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8_AND_16; break;
}
ResourceDescriptor->u.Dma.Channel = dma_data->channels[i];
ResourceDescriptor++;
}
break;
}
case io:
{
IO_RESOURCE *io_data = (IO_RESOURCE*) &resource->data;
ResourceDescriptor->Type = CmResourceTypePort;
ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
if (io_data->io_decode == DECODE_16)
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
else
ResourceDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
ResourceDescriptor->u.Port.Start.u.HighPart = 0;
ResourceDescriptor->u.Port.Start.u.LowPart = io_data->min_base_address;
ResourceDescriptor->u.Port.Length = io_data->range_length;
ResourceDescriptor++;
break;
}
case end_tag:
{
Done = TRUE;
break;
}
}
resource = (RESOURCE *) ((NATIVE_UINT) resource + (NATIVE_UINT) resource->length);
}
acpi_rs_dump_resource_list(resource);
return TRUE;
}
@@ -126,7 +272,7 @@ FdoQueryBusRelations(
ANSI_STRING AnsiString;
ACPI_STATUS AcpiStatus;
PACPI_DEVICE Device;
NTSTATUS Status;
NTSTATUS Status = STATUS_SUCCESS;
BM_NODE *Node;
ULONG Size;
ULONG i;
@@ -147,6 +293,7 @@ FdoQueryBusRelations(
CurrentEntry = DeviceExtension->DeviceListHead.Flink;
while (CurrentEntry != &DeviceExtension->DeviceListHead)
{
ACPI_BUFFER Buffer;
Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry);
/* FIXME: For ACPI namespace devices on the motherboard create filter DOs
@@ -198,6 +345,34 @@ FdoQueryBusRelations(
AcpiStatus = bm_get_node(Device->BmHandle, 0, &Node);
if (ACPI_SUCCESS(AcpiStatus))
{
/* Get current resources */
Buffer.length = 0;
Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
if ((Status & ACPI_OK) == 0)
{
ASSERT(FALSE);
}
if (Buffer.length > 0)
{
Buffer.pointer = ExAllocatePool(PagedPool, Buffer.length);
if (!Buffer.pointer)
{
ASSERT(FALSE);
}
Status = acpi_get_current_resources(Node->device.acpi_handle, &Buffer);
if (ACPI_FAILURE(Status))
{
ASSERT(FALSE);
}
if (!AcpiCreateResourceList(&PdoDeviceExtension->ResourceList,
&PdoDeviceExtension->ResourceListSize,
(RESOURCE*)Buffer.pointer))
{
ASSERT(FALSE);
}
ExFreePool(Buffer.pointer);
}
/* Add Device ID string */
if (!AcpiCreateDeviceIDString(&PdoDeviceExtension->DeviceID,
Node))
@@ -47,6 +47,9 @@ typedef struct _PDO_DEVICE_EXTENSION
UNICODE_STRING InstanceID;
// Hardware IDs
UNICODE_STRING HardwareIDs;
// Resource list
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
+1 -1
View File
@@ -601,5 +601,5 @@ acpi_os_writable(void *ptr, u32 len)
u32
acpi_os_get_thread_id (void)
{
return (ULONG)PsGetCurrentThreadId();
return (ULONG)PsGetCurrentThreadId() + 1;
}
+33
View File
@@ -107,6 +107,35 @@ PdoQueryId(
}
static NTSTATUS
PdoQueryResources(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST ResourceList;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (DeviceExtension->ResourceListSize == 0)
{
return Irp->IoStatus.Status;
}
ResourceList = ExAllocatePool(PagedPool, DeviceExtension->ResourceListSize);
if (!ResourceList)
{
Irp->IoStatus.Information = 0;
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(ResourceList, DeviceExtension->ResourceList, DeviceExtension->ResourceListSize);
Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
return STATUS_SUCCESS;
}
static NTSTATUS
PdoSetPower(
IN PDEVICE_OBJECT DeviceObject,
@@ -201,6 +230,9 @@ PdoPnpControl(
break;
case IRP_MN_QUERY_RESOURCES:
Status = PdoQueryResources(DeviceObject,
Irp,
IrpSp);
break;
case IRP_MN_QUERY_STOP_DEVICE:
@@ -213,6 +245,7 @@ PdoPnpControl(
break;
case IRP_MN_START_DEVICE:
Status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE:
+1 -1
View File
@@ -503,7 +503,7 @@ acpi_tb_get_table_rsdt (
REPORT_ERROR (("Invalid signature where RSDP indicates %s should be located\n",
table_signature));
return (status);
return (AE_NO_ACPI_TABLES);
}
@@ -389,6 +389,7 @@ acpi_cm_init_globals (
acpi_gbl_acpi_mutex_info[i].mutex = NULL;
acpi_gbl_acpi_mutex_info[i].locked = FALSE;
acpi_gbl_acpi_mutex_info[i].use_count = 0;
acpi_gbl_acpi_mutex_info[i].owner_id = 0;
}
/* Global notify handlers */
+541
View File
@@ -0,0 +1,541 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial enumerator driver
* FILE: drivers/bus/serenum/detect.c
* PURPOSE: Detection of serial devices
*
* PROGRAMMERS: Jason Filby (jasonfilby@yahoo.com)
* Filip Navara (xnavara@volny.cz)
* Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "serenum.h"
static NTSTATUS
SerenumDeviceIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferSize,
IN OUT PVOID OutputBuffer OPTIONAL,
IN OUT PULONG OutputBufferSize)
{
KEVENT Event;
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
KeInitializeEvent (&Event, NotificationEvent, FALSE);
Irp = IoBuildDeviceIoControlRequest(CtlCode,
DeviceObject,
InputBuffer,
InputBufferSize,
OutputBuffer,
(OutputBufferSize) ? *OutputBufferSize : 0,
FALSE,
&Event,
&IoStatus);
if (Irp == NULL)
{
DPRINT("Serenum: IoBuildDeviceIoControlRequest() failed\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
DPRINT("Serenum: Operation pending\n");
KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (OutputBufferSize)
{
*OutputBufferSize = IoStatus.Information;
}
return Status;
}
static NTSTATUS
ReadBytes(
IN PDEVICE_OBJECT LowerDevice,
OUT PUCHAR Buffer,
IN ULONG BufferSize,
OUT PULONG FilledBytes)
{
PIRP Irp;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS Status;
KeInitializeEvent(&event, NotificationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_READ,
LowerDevice,
Buffer, BufferSize,
0,
&event,
&ioStatus);
if (!Irp)
return FALSE;
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Suspended, KernelMode, FALSE, NULL);
Status = ioStatus.Status;
}
DPRINT("Serenum: bytes received: %lu/%lu\n",
ioStatus.Information, BufferSize);
*FilledBytes = ioStatus.Information;
return Status;
}
static NTSTATUS
ReportDetectedDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PUNICODE_STRING DeviceDescription,
IN PUNICODE_STRING DeviceId,
IN PUNICODE_STRING HardwareIds,
IN PUNICODE_STRING CompatibleIds)
{
PDEVICE_OBJECT Pdo = NULL;
PPDO_DEVICE_EXTENSION PdoDeviceExtension = NULL;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
NTSTATUS Status;
DPRINT("Serenum: SerenumReportDetectedDevice() called with %wZ (%wZ) detected\n", DeviceId, DeviceDescription);
Status = IoCreateDevice(
DeviceObject->DriverObject,
sizeof(PDO_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status)) goto ByeBye;
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
Pdo->Flags |= DO_POWER_PAGABLE;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PdoDeviceExtension->Common.IsFDO = FALSE;
Status = SerenumDuplicateUnicodeString(&PdoDeviceExtension->DeviceDescription, DeviceDescription, PagedPool);
if (!NT_SUCCESS(Status)) goto ByeBye;
Status = SerenumDuplicateUnicodeString(&PdoDeviceExtension->DeviceId, DeviceId, PagedPool);
if (!NT_SUCCESS(Status)) goto ByeBye;
Status = SerenumDuplicateUnicodeString(&PdoDeviceExtension->HardwareIds, HardwareIds, PagedPool);
if (!NT_SUCCESS(Status)) goto ByeBye;
Status = SerenumDuplicateUnicodeString(&PdoDeviceExtension->CompatibleIds, CompatibleIds, PagedPool);
if (!NT_SUCCESS(Status)) goto ByeBye;
/* Device attached to serial port (Pdo) may delegate work to
* serial port stack (Fdo = DeviceObject variable) */
Pdo->StackSize = DeviceObject->StackSize + 1;
FdoDeviceExtension->AttachedPdo = Pdo;
PdoDeviceExtension->AttachedFdo = DeviceObject;
Pdo->Flags |= DO_BUFFERED_IO;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
ByeBye:
if (Pdo)
{
if (PdoDeviceExtension->DeviceDescription.Buffer)
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceDescription);
if (PdoDeviceExtension->DeviceId.Buffer)
RtlFreeUnicodeString(&PdoDeviceExtension->DeviceId);
if (PdoDeviceExtension->HardwareIds.Buffer)
RtlFreeUnicodeString(&PdoDeviceExtension->HardwareIds);
if (PdoDeviceExtension->CompatibleIds.Buffer)
RtlFreeUnicodeString(&PdoDeviceExtension->CompatibleIds);
IoDeleteDevice(Pdo);
}
return Status;
}
static BOOLEAN
SerenumIsValidPnpIdString(
IN PUCHAR Buffer,
IN ULONG BufferLength)
{
/* FIXME: SerenumIsValidPnpIdString not implemented */
DPRINT1("Serenum: SerenumIsValidPnpIdString() unimplemented\n");
return STATUS_SUCCESS;
}
static NTSTATUS
ReportDetectedPnpDevice(
IN PUCHAR Buffer,
IN ULONG BufferLength)
{
ULONG i;
/* FIXME: ReportDetectedPnpDevice not implemented */
DPRINT1("Serenum: ReportDetectedPnpDevice() unimplemented\n");
DPRINT1("");
for (i = 0; i < BufferLength; i++)
DbgPrint("%c", Buffer[i]);
DbgPrint("\n");
/* Call ReportDetectedDevice */
return STATUS_SUCCESS;
}
#define BEGIN_ID '('
#define END_ID ')'
static NTSTATUS
SerenumWait(ULONG milliseconds)
{
KTIMER Timer;
LARGE_INTEGER DueTime;
DueTime.QuadPart = -milliseconds * 10;
KeInitializeTimer(&Timer);
KeSetTimer(&Timer, DueTime, NULL);
return KeWaitForSingleObject(&Timer, Executive, KernelMode, FALSE, NULL);
}
NTSTATUS
SerenumDetectPnpDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT LowerDevice)
{
UCHAR Buffer[256];
ULONG BaudRate;
ULONG TotalBytesReceived = 0;
ULONG Size;
ULONG Msr, Purge;
ULONG i;
BOOLEAN BufferContainsBeginId, BufferContainsEndId;
SERIAL_LINE_CONTROL Lcr;
SERIAL_TIMEOUTS Timeouts;
SERIALPERF_STATS PerfStats;
NTSTATUS Status;
/* 1. COM port initialization, check for device enumerate */
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
SerenumWait(200);
Size = sizeof(Msr);
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS,
NULL, 0, &Msr, &Size);
if (!NT_SUCCESS(Status)) return Status;
if ((Msr & SR_MSR_DSR) == 0) goto SerenumDisconnectIdle;
/* 2. COM port setup, 1st phase */
CHECKPOINT;
BaudRate = SERIAL_BAUD_1200;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, 0);
if (!NT_SUCCESS(Status)) return Status;
Lcr.WordLength = 7;
Lcr.Parity = NO_PARITY;
Lcr.StopBits = STOP_BIT_1;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&Lcr, sizeof(Lcr), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
SerenumWait(200);
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
SerenumWait(200);
/* 3. Wait for response, 1st phase */
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Timeouts.ReadIntervalTimeout = 0;
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 200;
Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
&Timeouts, sizeof(Timeouts), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer), &Size);
if (!NT_SUCCESS(Status)) return Status;
if (Size != 0) goto SerenumCollectPnpComDeviceId;
/* 4. COM port setup, 2nd phase */
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Purge = SERIAL_PURGE_RXABORT | SERIAL_PURGE_RXCLEAR;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_PURGE,
&Purge, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
SerenumWait(200);
/* 5. Wait for response, 2nd phase */
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = ReadBytes(LowerDevice, Buffer, 1, &TotalBytesReceived);
if (!NT_SUCCESS(Status)) return Status;
if (TotalBytesReceived != 0) goto SerenumCollectPnpComDeviceId;
Size = sizeof(Msr);
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS,
NULL, 0, &Msr, &Size);
if (!NT_SUCCESS(Status)) return Status;
if ((Msr & SR_MSR_DSR) == 0) goto SerenumVerifyDisconnect; else goto SerenumConnectIdle;
/* 6. Collect PnP COM device ID */
SerenumCollectPnpComDeviceId:
CHECKPOINT;
Timeouts.ReadIntervalTimeout = 200;
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 2200;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
&Timeouts, sizeof(Timeouts), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = ReadBytes(LowerDevice, &Buffer[TotalBytesReceived], sizeof(Buffer) - TotalBytesReceived, &Size);
if (!NT_SUCCESS(Status)) return Status;
TotalBytesReceived += Size;
Size = sizeof(PerfStats);
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_STATS,
NULL, 0, &PerfStats, &Size);
if (!NT_SUCCESS(Status)) return Status;
if (PerfStats.FrameErrorCount + PerfStats.ParityErrorCount != 0) goto SerenumConnectIdle;
BufferContainsBeginId = BufferContainsEndId = FALSE;
for (i = 0; i < TotalBytesReceived; i++)
{
if (Buffer[i] == BEGIN_ID) BufferContainsBeginId = TRUE;
if (Buffer[i] == END_ID) BufferContainsEndId = TRUE;
}
if (TotalBytesReceived == 1 || BufferContainsEndId)
{
if (SerenumIsValidPnpIdString(Buffer, TotalBytesReceived))
return ReportDetectedPnpDevice(Buffer, TotalBytesReceived);
goto SerenumConnectIdle;
}
if (!BufferContainsBeginId) goto SerenumConnectIdle;
if (!BufferContainsEndId) goto SerenumConnectIdle;
Size = sizeof(Msr);
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_GET_MODEMSTATUS,
NULL, 0, &Msr, &Size);
if (!NT_SUCCESS(Status)) return Status;
if ((Msr & SR_MSR_DSR) == 0) goto SerenumVerifyDisconnect;
/* 7. Verify disconnect */
SerenumVerifyDisconnect:
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
SerenumWait(5000);
goto SerenumDisconnectIdle;
/* 8. Connect idle */
SerenumConnectIdle:
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
BaudRate = SERIAL_BAUD_300;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Lcr.WordLength = 7;
Lcr.Parity = NO_PARITY;
Lcr.StopBits = STOP_BIT_1;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&Lcr, sizeof(Lcr), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
if (TotalBytesReceived == 0)
return STATUS_DEVICE_NOT_CONNECTED;
else
return STATUS_SUCCESS;
/* 9. Disconnect idle */
SerenumDisconnectIdle:
CHECKPOINT;
/* FIXME: report to OS device removal, if it was present */
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_CLR_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
BaudRate = SERIAL_BAUD_300;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Lcr.WordLength = 7;
Lcr.Parity = NO_PARITY;
Lcr.StopBits = STOP_BIT_1;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&Lcr, sizeof(Lcr), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
return STATUS_DEVICE_NOT_CONNECTED;
}
NTSTATUS
SerenumDetectLegacyDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT LowerDevice)
{
ULONG Fcr, Mcr;
ULONG BaudRate;
ULONG Command;
SERIAL_TIMEOUTS Timeouts;
SERIAL_LINE_CONTROL LCR;
ULONG i, Count;
UCHAR Buffer[16];
UNICODE_STRING DeviceDescription;
UNICODE_STRING DeviceId;
UNICODE_STRING HardwareIds;
UNICODE_STRING CompatibleIds;
NTSTATUS Status;
RtlZeroMemory(Buffer, sizeof(Buffer));
/* Reset UART */
CHECKPOINT;
Mcr = 0; /* MCR: DTR/RTS/OUT2 off */
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
&Mcr, sizeof(Mcr), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Set communications parameters */
CHECKPOINT;
/* DLAB off */
Fcr = 0;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_FIFO_CONTROL,
&Fcr, sizeof(Fcr), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Set serial port speed */
BaudRate = SERIAL_BAUD_1200;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_BAUD_RATE,
&BaudRate, sizeof(BaudRate), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Set LCR */
LCR.WordLength = 7;
LCR.Parity = NO_PARITY;
LCR.StopBits = STOP_BITS_2;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_LINE_CONTROL,
&LCR, sizeof(LCR), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Flush receive buffer */
CHECKPOINT;
Command = SERIAL_PURGE_RXCLEAR;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_MODEM_CONTROL,
&Command, sizeof(Command), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Wait 100 ms */
SerenumWait(100);
/* Enable DTR/RTS */
CHECKPOINT;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_DTR,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_RTS,
NULL, 0, NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Set timeout to 500 microseconds */
CHECKPOINT;
Timeouts.ReadIntervalTimeout = 100;
Timeouts.ReadTotalTimeoutMultiplier = 0;
Timeouts.ReadTotalTimeoutConstant = 500;
Timeouts.WriteTotalTimeoutMultiplier = Timeouts.WriteTotalTimeoutConstant = 0;
Status = SerenumDeviceIoControl(LowerDevice, IOCTL_SERIAL_SET_TIMEOUTS,
&Timeouts, sizeof(Timeouts), NULL, NULL);
if (!NT_SUCCESS(Status)) return Status;
/* Fill the read buffer */
CHECKPOINT;
Status = ReadBytes(LowerDevice, Buffer, sizeof(Buffer)/sizeof(Buffer[0]), &Count);
if (!NT_SUCCESS(Status)) return Status;
for (i = 0; i < Count; i++)
{
if (Buffer[i] == 'B')
{
/* Sign for Microsoft Ballpoint */
/* Hardware id: *PNP0F09
* Compatible id: *PNP0F0F, SERIAL_MOUSE
*/
RtlInitUnicodeString(&DeviceDescription, L"Microsoft Ballpoint device");
RtlInitUnicodeString(&DeviceId, L"*PNP0F09");
SerenumInitMultiSzString(&HardwareIds, "*PNP0F09", NULL);
SerenumInitMultiSzString(&CompatibleIds, "*PNP0F0F", "SERIAL_MOUSE", NULL);
Status = ReportDetectedDevice(DeviceObject,
&DeviceDescription, &DeviceId, &HardwareIds, &CompatibleIds);
RtlFreeUnicodeString(&HardwareIds);
RtlFreeUnicodeString(&CompatibleIds);
return Status;
}
else if (Buffer[i] == 'M')
{
/* Sign for Microsoft Mouse protocol followed by button specifier */
if (i == sizeof(Buffer) - 1)
{
/* Overflow Error */
return STATUS_DEVICE_NOT_CONNECTED;
}
switch (Buffer[i + 1])
{
case '3':
/* Hardware id: *PNP0F08
* Compatible id: SERIAL_MOUSE
*/
RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with 3-buttons");
RtlInitUnicodeString(&DeviceId, L"*PNP0F08");
SerenumInitMultiSzString(&HardwareIds, "*PNP0F08", NULL);
SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL);
default:
/* Hardware id: *PNP0F01
* Compatible id: SERIAL_MOUSE
*/
RtlInitUnicodeString(&DeviceDescription, L"Microsoft Mouse with 2-buttons or Microsoft Wheel Mouse");
RtlInitUnicodeString(&DeviceId, L"*PNP0F01");
SerenumInitMultiSzString(&HardwareIds, "*PNP0F01", NULL);
SerenumInitMultiSzString(&CompatibleIds, "SERIAL_MOUSE", NULL);
}
Status = ReportDetectedDevice(DeviceObject,
&DeviceDescription, &DeviceId, &HardwareIds, &CompatibleIds);
RtlFreeUnicodeString(&HardwareIds);
RtlFreeUnicodeString(&CompatibleIds);
return Status;
}
}
return STATUS_DEVICE_NOT_CONNECTED;
}
+213
View File
@@ -0,0 +1,213 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial enumerator driver
* FILE: drivers/bus/serenum/fdo.c
* PURPOSE: IRP_MJ_PNP operations for FDOs
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "serenum.h"
NTSTATUS STDCALL
SerenumAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
PDEVICE_OBJECT Fdo;
PFDO_DEVICE_EXTENSION DeviceExtension;
//UNICODE_STRING SymbolicLinkName;
NTSTATUS Status;
DPRINT("Serenum: SerenumAddDevice called. Pdo = %p\n", Pdo);
/* Create new device object */
Status = IoCreateDevice(DriverObject,
sizeof(FDO_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("Serenum: IoCreateDevice() failed with status 0x%08lx\n", Status);
return Status;
}
/* Register device interface */
#if 0 /* FIXME: activate */
Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, NULL, &SymbolicLinkName);
if (!NT_SUCCESS(Status))
{
DPRINT("Serenum: IoRegisterDeviceInterface() failed with status 0x%08lx\n", Status);
goto ByeBye;
}
DPRINT1("Serenum: IoRegisterDeviceInterface() returned '%wZ'\n", &SymbolicLinkName);
Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT("Serenum: IoSetDeviceInterfaceState() failed with status 0x%08lx\n", Status);
goto ByeBye;
}
RtlFreeUnicodeString(&SymbolicLinkName);
#endif
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->Common.IsFDO = TRUE;
DeviceExtension->Common.PnpState = dsStopped;
DeviceExtension->Pdo = Pdo;
IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERENUM_TAG, 0, 0);
Fdo->Flags |= DO_POWER_PAGABLE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT("Serenum: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
IoDeleteDevice(Fdo);
return Status;
}
Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
SerenumFdoStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PCOMMON_DEVICE_EXTENSION DeviceExtension;
DPRINT("Serenum: SerenumFdoStartDevice() called\n");
DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->PnpState == dsStopped);
DeviceExtension->PnpState = dsStarted;
return STATUS_SUCCESS;
}
NTSTATUS
SerenumFdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
ULONG NumPDO;
ULONG i;
NTSTATUS Status = STATUS_SUCCESS;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.IsFDO);
/* Do enumeration if needed */
if (!(DeviceExtension->Flags & FLAG_ENUMERATION_DONE))
{
ASSERT(DeviceExtension->AttachedPdo == NULL);
/* Detect plug-and-play devices */
Status = SerenumDetectPnpDevice(DeviceObject, DeviceExtension->LowerDevice);
if (Status == STATUS_DEVICE_NOT_CONNECTED)
{
/* Detect legacy devices */
Status = SerenumDetectLegacyDevice(DeviceObject, DeviceExtension->LowerDevice);
if (Status == STATUS_DEVICE_NOT_CONNECTED)
Status = STATUS_SUCCESS;
}
DeviceExtension->Flags |= FLAG_ENUMERATION_DONE;
}
NumPDO = (DeviceExtension->AttachedPdo != NULL ? 1 : 0);
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
PagedPool,
sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (NumPDO - 1),
SERENUM_TAG);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
/* Fill returned structure */
DeviceRelations->Count = NumPDO;
for (i = 0; i < NumPDO; i++)
{
ObReferenceObject(DeviceExtension->AttachedPdo);
DeviceRelations->Objects[i] = DeviceExtension->AttachedPdo;
}
*pDeviceRelations = DeviceRelations;
return Status;
}
NTSTATUS
SerenumFdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
/* FIXME: do all these minor functions
IRP_MN_QUERY_REMOVE_DEVICE 0x1
IRP_MN_REMOVE_DEVICE 0x2
IRP_MN_CANCEL_REMOVE_DEVICE 0x3
IRP_MN_STOP_DEVICE 0x4
IRP_MN_QUERY_STOP_DEVICE 0x5
IRP_MN_CANCEL_STOP_DEVICE 0x6
IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) 0x7
IRP_MN_QUERY_INTERFACE (optional) 0x8
IRP_MN_QUERY_CAPABILITIES (optional) 0x9
IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional or required) 0xb
IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
IRP_MN_SURPRISE_REMOVAL 0x17
*/
case IRP_MN_START_DEVICE: /* 0x0 */
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
Status = SerenumFdoStartDevice(DeviceObject, Irp);
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations;
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = SerenumFdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
default:
DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
return ForwardIrpAndForget(DeviceObject, Irp);
}
break;
}
default:
{
DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+20
View File
@@ -0,0 +1,20 @@
# $Id: makefile 12852 2005-01-06 13:58:04Z mf $
PATH_TO_TOP = ../../..
TARGET_TYPE = driver
TARGET_NAME = serenum
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
TARGET_OBJECTS = \
detect.o \
fdo.o \
misc.o \
pdo.o \
serenum.o
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
+201
View File
@@ -0,0 +1,201 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial enumerator driver
* FILE: drivers/dd/serenum/misc.c
* PURPOSE: Misceallenous operations
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "serenum.h"
#include <stdarg.h>
NTSTATUS
SerenumDuplicateUnicodeString(
OUT PUNICODE_STRING Destination,
IN PUNICODE_STRING Source,
IN POOL_TYPE PoolType)
{
if (Source == NULL)
{
RtlInitUnicodeString(Destination, NULL);
return STATUS_SUCCESS;
}
Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength);
if (Destination->Buffer == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Destination->MaximumLength = Source->MaximumLength;
Destination->Length = Source->Length;
RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength);
return STATUS_SUCCESS;
}
/* I really want ANSI strings as last arguments because
* PnP ids are ANSI-encoded in PnP device string
* identification */
NTSTATUS
SerenumInitMultiSzString(
OUT PUNICODE_STRING Destination,
... /* list of PCSZ */)
{
va_list args;
PCSZ Source;
ANSI_STRING AnsiString;
UNICODE_STRING UnicodeString;
ULONG DestinationSize = 0;
NTSTATUS Status = STATUS_SUCCESS;
/* Calculate length needed for destination unicode string */
va_start(args, Destination);
Source = va_arg(args, PCSZ);
while (Source != NULL)
{
RtlInitAnsiString(&AnsiString, Source);
DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString)
+ sizeof(WCHAR) /* final NULL */;
Source = va_arg(args, PCSZ);
}
va_end(args);
if (DestinationSize == 0)
{
RtlInitUnicodeString(Destination, NULL);
return STATUS_SUCCESS;
}
/* Initialize destination string */
DestinationSize += sizeof(WCHAR); // final NULL
Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, SERENUM_TAG);
if (!Destination->Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
Destination->Length = 0;
Destination->MaximumLength = (USHORT)DestinationSize;
/* Copy arguments to destination string */
/* Use a temporary unicode string, which buffer is shared with
* destination string, to copy arguments */
UnicodeString.Length = Destination->Length;
UnicodeString.MaximumLength = Destination->MaximumLength;
UnicodeString.Buffer = Destination->Buffer;
va_start(args, Destination);
Source = va_arg(args, PCSZ);
while (Source != NULL)
{
RtlInitAnsiString(&AnsiString, Source);
Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(Destination->Buffer, SERENUM_TAG);
break;
}
Destination->Length += UnicodeString.Length + sizeof(WCHAR);
UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR);
UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1;
UnicodeString.Length = 0;
Source = va_arg(args, PCSZ);
}
va_end(args);
if (NT_SUCCESS(Status))
{
/* Finish multi-sz string */
Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0';
Destination->Length += sizeof(WCHAR);
}
return Status;
}
NTSTATUS STDCALL
ForwardIrpAndWaitCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned)
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice;
KEVENT Event;
NTSTATUS Status;
ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
DPRINT("Serenum: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
if (NT_SUCCESS(Status))
Status = Irp->IoStatus.Status;
}
return Status;
}
NTSTATUS STDCALL
ForwardIrpToLowerDeviceAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT LowerDevice;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.IsFDO);
LowerDevice = DeviceExtension->LowerDevice;
DPRINT("Serenum: calling lower device 0x%p [%wZ]\n",
LowerDevice, &LowerDevice->DriverObject->DriverName);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(LowerDevice, Irp);
}
NTSTATUS STDCALL
ForwardIrpToAttachedFdoAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT Fdo;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(!DeviceExtension->Common.IsFDO);
Fdo = DeviceExtension->AttachedFdo;
DPRINT("Serenum: calling attached Fdo 0x%p [%wZ]\n",
Fdo, &Fdo->DriverObject->DriverName);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(Fdo, Irp);
}
NTSTATUS STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice;
ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(LowerDevice, Irp);
}
+313
View File
@@ -0,0 +1,313 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial enumerator driver
* FILE: drivers/bus/serenum/pdo.c
* PURPOSE: IRP_MJ_PNP operations for PDOs
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
#define NDEBUG
#include "serenum.h"
static NTSTATUS
SerenumPdoStartDevice(
IN PDEVICE_OBJECT DeviceObject)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.PnpState == dsStopped);
DeviceExtension->Common.PnpState = dsStarted;
return STATUS_SUCCESS;
}
static NTSTATUS
SerenumPdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
ULONG IdType;
PUNICODE_STRING SourceString;
UNICODE_STRING String;
NTSTATUS Status;
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
RtlInitUnicodeString(&String, NULL);
switch (IdType)
{
case BusQueryDeviceID:
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
SourceString = &DeviceExtension->DeviceId;
break;
}
case BusQueryHardwareIDs:
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
SourceString = &DeviceExtension->HardwareIds;
break;
}
case BusQueryCompatibleIDs:
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
SourceString = &DeviceExtension->CompatibleIds;
break;
case BusQueryInstanceID:
{
/* We don't have any instance id to report, and
* this query is optional, so ignore it.
*/
*Information = Irp->IoStatus.Information;
return Irp->IoStatus.Status;
}
default:
DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
return STATUS_NOT_SUPPORTED;
}
Status = SerenumDuplicateUnicodeString(
&String,
SourceString,
PagedPool);
*Information = (ULONG_PTR)String.Buffer;
return Status;
}
static NTSTATUS
SerenumPdoQueryDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.IsFDO);
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(
PagedPool,
sizeof(DEVICE_RELATIONS),
SERENUM_TAG);
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
ObReferenceObject(DeviceObject);
DeviceRelations->Objects[0] = DeviceObject;
*pDeviceRelations = DeviceRelations;
return STATUS_SUCCESS;
}
NTSTATUS
SerenumPdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
/* FIXME: do all these minor functions
IRP_MN_QUERY_REMOVE_DEVICE 0x1
IRP_MN_REMOVE_DEVICE 0x2
IRP_MN_CANCEL_REMOVE_DEVICE 0x3
IRP_MN_STOP_DEVICE 0x4
IRP_MN_QUERY_STOP_DEVICE 0x5
IRP_MN_CANCEL_STOP_DEVICE 0x6
IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations (optional) 0x7
IRP_MN_QUERY_INTERFACE (required or optional) 0x8
IRP_MN_READ_CONFIG (required or optional) 0xf
IRP_MN_WRITE_CONFIG (required or optional) 0x10
IRP_MN_EJECT (required or optional) 0x11
IRP_MN_SET_LOCK (required or optional) 0x12
IRP_MN_QUERY_ID / BusQueryDeviceID 0x13
IRP_MN_QUERY_ID / BusQueryCompatibleIDs (optional) 0x13
IRP_MN_QUERY_ID / BusQueryInstanceID (optional) 0x13
IRP_MN_QUERY_PNP_DEVICE_STATE (optional) 0x14
IRP_MN_DEVICE_USAGE_NOTIFICATION (required or optional) 0x16
IRP_MN_SURPRISE_REMOVAL 0x17
*/
case IRP_MN_START_DEVICE: /* 0x0 */
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
Status = SerenumPdoStartDevice(DeviceObject);
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x7 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case RemovalRelations:
{
return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
}
case TargetDeviceRelation:
{
PDEVICE_RELATIONS DeviceRelations;
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
Status = SerenumPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
default:
{
DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
break;
}
case IRP_MN_QUERY_CAPABILITIES: /* 0x9 */
{
PDEVICE_CAPABILITIES DeviceCapabilities;
ULONG i;
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
/* FIXME: capabilities can change with connected device */
DeviceCapabilities->LockSupported = FALSE;
DeviceCapabilities->EjectSupported = FALSE;
DeviceCapabilities->Removable = TRUE;
DeviceCapabilities->DockDevice = FALSE;
DeviceCapabilities->UniqueID = FALSE;
DeviceCapabilities->SilentInstall = FALSE;
DeviceCapabilities->RawDeviceOK = TRUE;
DeviceCapabilities->SurpriseRemovalOK = TRUE;
DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
//DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
for (i = 0; i < PowerSystemMaximum; i++)
DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
//DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
DeviceCapabilities->D1Latency = 0; /* FIXME */
DeviceCapabilities->D2Latency = 0; /* FIXME */
DeviceCapabilities->D3Latency = 0; /* FIXME */
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_RESOURCES: /* 0xa */
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n");
/* Serial devices don't need resources, except the ones of
* the serial port. This PDO is the serial device PDO, so
* report no resource by not changing Information and
* Status
*/
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0xb */
{
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
/* Serial devices don't need resources, except the ones of
* the serial port. This PDO is the serial device PDO, so
* report no resource by not changing Information and
* Status
*/
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_DEVICE_TEXT: /* 0xc */
{
switch (Stack->Parameters.QueryDeviceText.DeviceTextType)
{
case DeviceTextDescription:
{
PUNICODE_STRING Source;
PWSTR Description;
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n");
Source = &((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->DeviceDescription;
Description = ExAllocatePool(PagedPool, Source->Length + sizeof(WCHAR));
if (!Description)
Status = STATUS_INSUFFICIENT_RESOURCES;
else
{
RtlCopyMemory(Description, Source->Buffer, Source->Length);
Description[Source->Length / sizeof(WCHAR)] = L'\0';
Information = (ULONG_PTR)Description;
Status = STATUS_SUCCESS;
}
break;
}
case DeviceTextLocationInformation:
{
/* We don't have any text location to report,
* and this query is optional, so ignore it.
*/
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
default:
{
DPRINT1("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceText.DeviceTextType);
Status = STATUS_NOT_SUPPORTED;
}
}
break;
}
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0xd */
{
return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
}
case IRP_MN_QUERY_ID: /* 0x13 */
{
Status = SerenumPdoQueryId(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
{
PPNP_BUS_INFORMATION BusInfo;
DPRINT("Serenum: IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
if (!BusInfo)
Status = STATUS_INSUFFICIENT_RESOURCES;
else
{
BusInfo->BusTypeGuid = GUID_BUS_TYPE_SERENUM;
/* FIXME: real value should be PNPBus, but PNPBus seems to be
* the only value in INTERFACE_TYPE enum that doesn't work...
*/
BusInfo->LegacyBusType = PNPISABus;
/* We're the only serial bus enumerator on the computer */
BusInfo->BusNumber = 0;
Information = (ULONG_PTR)BusInfo;
Status = STATUS_SUCCESS;
}
break;
}
default:
{
/* We can't forward request to the lower driver, because
* we are a Pdo, so we don't have lower driver... */
DPRINT1("Serenum: IRP_MJ_PNP / unknown minor function 0x%lx\n", MinorFunction);
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+114
View File
@@ -0,0 +1,114 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Serial enumerator driver
* FILE: drivers/bus/serenum/serenum.c
* PURPOSE: Serial enumeration driver entry point
*
* PROGRAMMERS: Hervé Poussineau (hpoussin@reactos.com)
*/
//#define NDEBUG
#define INITGUID
#include "serenum.h"
NTSTATUS STDCALL
SerenumPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
return SerenumFdoPnp(DeviceObject, Irp);
else
return SerenumPdoPnp(DeviceObject, Irp);
}
VOID STDCALL
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
// nothing to do here yet
}
NTSTATUS STDCALL
IrpStub(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status = STATUS_NOT_SUPPORTED;
if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
{
/* Forward some IRPs to lower device */
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
case IRP_MJ_CLEANUP:
case IRP_MJ_READ:
case IRP_MJ_WRITE:
case IRP_MJ_DEVICE_CONTROL:
return ForwardIrpToLowerDeviceAndForget(DeviceObject, Irp);
default:
{
DPRINT1("Serenum: FDO stub for major function 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
DbgBreakPoint();
Status = Irp->IoStatus.Status;
}
}
}
else
{
/* Forward some IRPs to attached FDO */
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
case IRP_MJ_CLEANUP:
case IRP_MJ_READ:
case IRP_MJ_WRITE:
case IRP_MJ_DEVICE_CONTROL:
return ForwardIrpToAttachedFdoAndForget(DeviceObject, Irp);
default:
{
DPRINT1("Serenum: PDO stub for major function 0x%lx\n",
IoGetCurrentIrpStackLocation(Irp)->MajorFunction);
DbgBreakPoint();
Status = Irp->IoStatus.Status;
}
}
}
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/*
* Standard DriverEntry method.
*/
NTSTATUS STDCALL
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegPath)
{
ULONG i;
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = SerenumAddDevice;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = IrpStub;
/*DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SerialCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = SerialRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = SerialWrite;*/
//DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Serenum;
//DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SerialQueryInformation;
DriverObject->MajorFunction[IRP_MJ_PNP] = SerenumPnp;
//DriverObject->MajorFunction[IRP_MJ_POWER] = SerialPower;
return STATUS_SUCCESS;
}
+152
View File
@@ -0,0 +1,152 @@
#if defined(__GNUC__)
#include <ddk/ntddk.h>
#include <ddk/ntddser.h>
#include <ddk/wdmguid.h>
#include <stdio.h>
#include <debug.h>
#define SR_MSR_DSR 0x20
#define ExFreePoolWithTag(p, tag) ExFreePool(p)
/* FIXME: these prototypes MUST NOT be here! */
NTSTATUS STDCALL
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#elif defined(_MSC_VER)
#include <ntddk.h>
#include <ntddser.h>
#include <c:/progra~1/winddk/inc/ddk/wdm/wxp/wdmguid.h>
#include <stdio.h>
#define STDCALL
#define DPRINT1 DbgPrint("(%s:%d) ", __FILE__, __LINE__), DbgPrint
#define CHECKPOINT1 DbgPrint("(%s:%d)\n")
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
NTSTATUS STDCALL
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#define DPRINT DPRINT1
#define CHECKPOINT CHECKPOINT1
#define SR_MSR_DSR 0x20
#else
#error Unknown compiler!
#endif
typedef enum
{
dsStopped,
dsStarted,
dsPaused,
dsRemoved,
dsSurpriseRemoved
} SERENUM_DEVICE_STATE;
typedef struct _COMMON_DEVICE_EXTENSION
{
BOOLEAN IsFDO;
SERENUM_DEVICE_STATE PnpState;
} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
typedef struct _FDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
PDEVICE_OBJECT LowerDevice;
PDEVICE_OBJECT Pdo;
IO_REMOVE_LOCK RemoveLock;
PDEVICE_OBJECT AttachedPdo;
ULONG Flags;
} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
typedef struct _PDO_DEVICE_EXTENSION
{
COMMON_DEVICE_EXTENSION Common;
PDEVICE_OBJECT AttachedFdo;
UNICODE_STRING DeviceDescription; // REG_SZ
UNICODE_STRING DeviceId; // REG_SZ
UNICODE_STRING HardwareIds; // REG_MULTI_SZ
UNICODE_STRING CompatibleIds; // REG_MULTI_SZ
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
#define SERENUM_TAG TAG('S', 'e', 'r', 'e')
/* Flags */
#define FLAG_ENUMERATION_DONE 0x01
/************************************ detect.c */
NTSTATUS
SerenumDetectPnpDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT LowerDevice);
NTSTATUS
SerenumDetectLegacyDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_OBJECT LowerDevice);
/************************************ fdo.c */
NTSTATUS STDCALL
SerenumAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo);
NTSTATUS
SerenumFdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ misc.c */
NTSTATUS
SerenumDuplicateUnicodeString(
OUT PUNICODE_STRING Destination,
IN PUNICODE_STRING Source,
IN POOL_TYPE PoolType);
NTSTATUS
SerenumInitMultiSzString(
OUT PUNICODE_STRING Destination,
... /* list of ANSI_STRINGs */);
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
ForwardIrpToLowerDeviceAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
ForwardIrpToAttachedFdoAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ pdo.c */
NTSTATUS
SerenumPdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+7
View File
@@ -0,0 +1,7 @@
/* $Id$ */
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "Serial port enumerator\0"
#define REACTOS_STR_INTERNAL_NAME "serenum\0"
#define REACTOS_STR_ORIGINAL_FILENAME "serenum.sys\0"
#include <reactos/version.rc>
@@ -0,0 +1,97 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/circularbuffer.c
* PURPOSE: Operations on a circular buffer
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
NTSTATUS
InitializeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG BufferSize)
{
DPRINT("Serial: InitializeCircularBuffer(pBuffer %p, BufferSize %lu)\n", pBuffer, BufferSize);
pBuffer->Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, BufferSize * sizeof(UCHAR), SERIAL_TAG);
if (!pBuffer->Buffer)
return STATUS_INSUFFICIENT_RESOURCES;
pBuffer->Length = BufferSize;
pBuffer->ReadPosition = pBuffer->WritePosition = 0;
return STATUS_SUCCESS;
}
NTSTATUS
FreeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer)
{
DPRINT("Serial: FreeCircularBuffer(pBuffer %p)\n", pBuffer);
ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
return STATUS_SUCCESS;
}
BOOLEAN
IsCircularBufferEmpty(
IN PCIRCULAR_BUFFER pBuffer)
{
DPRINT("Serial: IsCircularBufferEmpty(pBuffer %p)\n", pBuffer);
return (pBuffer->ReadPosition == pBuffer->WritePosition);
}
NTSTATUS
PushCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
IN UCHAR Entry)
{
ULONG NextPosition;
DPRINT("Serial: PushCircularBufferEntry(pBuffer %p, Entry 0x%x)\n", pBuffer, Entry);
ASSERT(pBuffer->Length);
NextPosition = (pBuffer->WritePosition + 1) % pBuffer->Length;
if (NextPosition == pBuffer->ReadPosition)
return STATUS_BUFFER_TOO_SMALL;
pBuffer->Buffer[pBuffer->WritePosition] = Entry;
pBuffer->WritePosition = NextPosition;
return STATUS_SUCCESS;
}
NTSTATUS
PopCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
OUT PUCHAR Entry)
{
DPRINT("Serial: PopCircularBufferEntry(pBuffer %p)\n", pBuffer);
ASSERT(pBuffer->Length);
if (IsCircularBufferEmpty(pBuffer))
return STATUS_ARRAY_BOUNDS_EXCEEDED;
*Entry = pBuffer->Buffer[pBuffer->ReadPosition];
pBuffer->ReadPosition = (pBuffer->ReadPosition + 1) % pBuffer->Length;
return STATUS_SUCCESS;
}
NTSTATUS
IncreaseCircularBufferSize(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG NewBufferSize)
{
PUCHAR NewBuffer;
DPRINT("Serial: IncreaseCircularBufferSize(pBuffer %p, NewBufferSize %lu)\n", pBuffer, NewBufferSize);
ASSERT(pBuffer->Length);
if (pBuffer->Length > NewBufferSize)
return STATUS_INVALID_PARAMETER;
else if (pBuffer->Length == NewBufferSize)
return STATUS_SUCCESS;
NewBuffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, NewBufferSize * sizeof(UCHAR), SERIAL_TAG);
if (!NewBuffer)
return STATUS_INSUFFICIENT_RESOURCES;
RtlCopyMemory(NewBuffer, pBuffer->Buffer, pBuffer->Length * sizeof(UCHAR));
ExFreePoolWithTag(pBuffer->Buffer, SERIAL_TAG);
pBuffer->Buffer = NewBuffer;
pBuffer->Length = NewBufferSize;
return STATUS_SUCCESS;
}
+24
View File
@@ -0,0 +1,24 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/cleanup.c
* PURPOSE: Serial IRP_MJ_CLEANUP operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
SerialCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("Serial: IRP_MJ_CLEANUP\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
+29
View File
@@ -0,0 +1,29 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/close.c
* PURPOSE: Serial IRP_MJ_CLOSE operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
SerialClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSERIAL_DEVICE_EXTENSION pDeviceExtension;
DPRINT("Serial: IRP_MJ_CLOSE\n");
pDeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
pDeviceExtension->IsOpened = FALSE;
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
+60
View File
@@ -0,0 +1,60 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/create.c
* PURPOSE: Serial IRP_MJ_CREATE operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
SerialCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PFILE_OBJECT FileObject;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DPRINT("Serial: IRP_MJ_CREATE\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
FileObject = Stack->FileObject;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (Stack->Parameters.Create.Options & FILE_DIRECTORY_FILE)
{
CHECKPOINT;
Status = STATUS_NOT_A_DIRECTORY;
goto ByeBye;
}
if (FileObject->FileName.Length != 0 ||
FileObject->RelatedFileObject != NULL)
{
CHECKPOINT;
Status = STATUS_ACCESS_DENIED;
goto ByeBye;
}
if(DeviceExtension->IsOpened)
{
DPRINT("Serial: COM%lu is already opened", DeviceExtension->ComPort);
Status = STATUS_ACCESS_DENIED;
goto ByeBye;
}
DPRINT("Serial: open COM%lu: successfull\n", DeviceExtension->ComPort);
DeviceExtension->IsOpened = TRUE;
Status = STATUS_SUCCESS;
ByeBye:
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+840
View File
@@ -0,0 +1,840 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/devctrl.c
* PURPOSE: Serial IRP_MJ_DEVICE_CONTROL operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
#define IO_METHOD_FROM_CTL_CODE(ctlCode) (ctlCode&0x00000003)
static VOID
SerialGetUserBuffers(
IN PIRP Irp,
IN ULONG IoControlCode,
OUT PVOID* BufferIn,
OUT PVOID* BufferOut)
{
ASSERT(Irp);
ASSERT(BufferIn);
ASSERT(BufferOut);
switch (IO_METHOD_FROM_CTL_CODE(IoControlCode))
{
case METHOD_BUFFERED:
*BufferIn = *BufferOut = Irp->AssociatedIrp.SystemBuffer;
return;
case METHOD_IN_DIRECT:
case METHOD_OUT_DIRECT:
*BufferIn = Irp->AssociatedIrp.SystemBuffer;
*BufferOut = MmGetSystemAddressForMdl(Irp->MdlAddress);
return;
case METHOD_NEITHER:
*BufferIn = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.Type3InputBuffer;
*BufferOut = Irp->UserBuffer;
return;
}
/* Should never happen */
}
NTSTATUS STDCALL
SerialSetBaudRate(
IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
IN ULONG NewBaudRate)
{
USHORT divisor;
PUCHAR ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
ULONG BaudRate;
NTSTATUS Status = STATUS_SUCCESS;
if (NewBaudRate & SERIAL_BAUD_USER)
{
BaudRate = NewBaudRate & ~SERIAL_BAUD_USER;
divisor = (USHORT)(BAUD_CLOCK / (CLOCKS_PER_BIT * BaudRate));
}
else
{
switch (NewBaudRate)
{
case SERIAL_BAUD_075: divisor = 0x600; BaudRate = 75; break;
case SERIAL_BAUD_110: divisor = 0x400; BaudRate = 110; break;
case SERIAL_BAUD_134_5: divisor = 0x360; BaudRate = 134; break;
case SERIAL_BAUD_150: divisor = 0x300; BaudRate = 150; break;
case SERIAL_BAUD_300: divisor = 0x180; BaudRate = 300; break;
case SERIAL_BAUD_600: divisor = 0xc0; BaudRate = 600; break;
case SERIAL_BAUD_1200: divisor = 0x60; BaudRate = 1200; break;
case SERIAL_BAUD_1800: divisor = 0x40; BaudRate = 1800; break;
case SERIAL_BAUD_2400: divisor = 0x30; BaudRate = 2400; break;
case SERIAL_BAUD_4800: divisor = 0x18; BaudRate = 4800; break;
case SERIAL_BAUD_7200: divisor = 0x10; BaudRate = 7200; break;
case SERIAL_BAUD_9600: divisor = 0xc; BaudRate = 9600; break;
case SERIAL_BAUD_14400: divisor = 0x8; BaudRate = 14400; break;
case SERIAL_BAUD_38400: divisor = 0x3; BaudRate = 38400; break;
case SERIAL_BAUD_57600: divisor = 0x2; BaudRate = 57600; break;
case SERIAL_BAUD_115200: divisor = 0x1; BaudRate = 115200; break;
case SERIAL_BAUD_56K: divisor = 0x2; BaudRate = 57600; break;
case SERIAL_BAUD_128K: divisor = 0x1; BaudRate = 115200; break;
default: Status = STATUS_INVALID_PARAMETER;
}
}
if (NT_SUCCESS(Status))
{
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
UCHAR Lcr;
DPRINT("Serial: SerialSetBaudRate(COM%lu, %lu Bauds)\n", DeviceExtension->ComPort, BaudRate);
/* Set Bit 7 of LCR to expose baud registers */
Lcr = READ_PORT_UCHAR(SER_LCR(ComPortBase));
WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr | SR_LCR_DLAB);
/* Write the baud rate */
WRITE_PORT_UCHAR(SER_DLL(ComPortBase), divisor & 0xff);
WRITE_PORT_UCHAR(SER_DLM(ComPortBase), divisor >> 8);
/* Switch back to normal registers */
WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
if (NT_SUCCESS(Status))
DeviceExtension->BaudRate = BaudRate;
return Status;
}
NTSTATUS STDCALL
SerialSetLineControl(
IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
IN PSERIAL_LINE_CONTROL NewSettings)
{
PUCHAR ComPortBase;
UCHAR Lcr = 0;
NTSTATUS Status;
DPRINT("Serial: SerialSetLineControl(COM%lu, Settings { %lu %lu %lu })\n",
DeviceExtension->ComPort, NewSettings->StopBits, NewSettings->Parity, NewSettings->WordLength);
/* Verify parameters */
switch (NewSettings->WordLength)
{
case 5: Lcr |= SR_LCR_CS5; break;
case 6: Lcr |= SR_LCR_CS6; break;
case 7: Lcr |= SR_LCR_CS7; break;
case 8: Lcr |= SR_LCR_CS8; break;
default: return STATUS_INVALID_PARAMETER;
}
if (NewSettings->WordLength < 5 || NewSettings->WordLength > 8)
return STATUS_INVALID_PARAMETER;
switch (NewSettings->Parity)
{
case NO_PARITY: Lcr |= SR_LCR_PNO; break;
case ODD_PARITY: Lcr |= SR_LCR_POD; break;
case EVEN_PARITY: Lcr |= SR_LCR_PEV; break;
case MARK_PARITY: Lcr |= SR_LCR_PMK; break;
case SPACE_PARITY: Lcr |= SR_LCR_PSP; break;
default: return STATUS_INVALID_PARAMETER;
}
switch (NewSettings->StopBits)
{
case STOP_BIT_1:
Lcr |= SR_LCR_ST1;
break;
case STOP_BITS_1_5:
if (NewSettings->WordLength != 5)
return STATUS_INVALID_PARAMETER;
Lcr |= SR_LCR_ST2;
break;
case STOP_BITS_2:
if (NewSettings->WordLength < 6 || NewSettings->WordLength > 8)
return STATUS_INVALID_PARAMETER;
Lcr |= SR_LCR_ST2;
break;
default:
return STATUS_INVALID_PARAMETER;
}
/* Update current parameters */
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (!NT_SUCCESS(Status))
return Status;
WRITE_PORT_UCHAR(SER_LCR(ComPortBase), Lcr);
/* Read junk out of RBR */
READ_PORT_UCHAR(SER_RBR(ComPortBase));
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
DeviceExtension->SerialLineControl = *NewSettings;
return Status;
}
BOOLEAN
SerialClearPerfStats(
IN PSERIAL_DEVICE_EXTENSION DeviceExtension)
{
RtlZeroMemory(&DeviceExtension->SerialPerfStats, sizeof(SERIALPERF_STATS));
DeviceExtension->BreakInterruptErrorCount = 0;
return TRUE;
}
BOOLEAN
SerialGetPerfStats(IN PIRP pIrp)
{
PSERIAL_DEVICE_EXTENSION pDeviceExtension;
pDeviceExtension = (PSERIAL_DEVICE_EXTENSION)
IoGetCurrentIrpStackLocation(pIrp)->DeviceObject->DeviceExtension;
/*
* we assume buffer is big enough to hold SerialPerfStats structure
* caller must verify this
*/
RtlCopyMemory(
pIrp->AssociatedIrp.SystemBuffer,
&pDeviceExtension->SerialPerfStats,
sizeof(SERIALPERF_STATS)
);
return TRUE;
}
NTSTATUS
SerialGetCommProp(
OUT PSERIAL_COMMPROP pCommProp,
IN PSERIAL_DEVICE_EXTENSION DeviceExtension)
{
RtlZeroMemory(pCommProp, sizeof(SERIAL_COMMPROP));
pCommProp->PacketLength = sizeof(SERIAL_COMMPROP);
pCommProp->PacketVersion = 2;
pCommProp->ServiceMask = SERIAL_SP_SERIALCOMM;
pCommProp->MaxTxQueue = pCommProp->CurrentTxQueue = DeviceExtension->OutputBuffer.Length - 1;
pCommProp->MaxRxQueue = pCommProp->CurrentRxQueue = DeviceExtension->InputBuffer.Length - 1;
pCommProp->ProvSubType = 1; // PST_RS232;
pCommProp->ProvCapabilities = SERIAL_PCF_DTRDSR | SERIAL_PCF_INTTIMEOUTS | SERIAL_PCF_PARITY_CHECK
| SERIAL_PCF_RTSCTS | SERIAL_PCF_SETXCHAR | SERIAL_PCF_SPECIALCHARS | SERIAL_PCF_TOTALTIMEOUTS
| SERIAL_PCF_XONXOFF;
pCommProp->SettableParams = SERIAL_SP_BAUD | SERIAL_SP_DATABITS | SERIAL_SP_HANDSHAKING
| SERIAL_SP_PARITY | SERIAL_SP_PARITY_CHECK | SERIAL_SP_STOPBITS;
/* SettableBaud is related to Uart type */
pCommProp->SettableBaud = SERIAL_BAUD_075 | SERIAL_BAUD_110 | SERIAL_BAUD_134_5
| SERIAL_BAUD_150 | SERIAL_BAUD_300 | SERIAL_BAUD_600 | SERIAL_BAUD_1200
| SERIAL_BAUD_1800 | SERIAL_BAUD_2400 | SERIAL_BAUD_4800 | SERIAL_BAUD_7200
| SERIAL_BAUD_9600 | SERIAL_BAUD_USER;
pCommProp->MaxBaud = SERIAL_BAUD_9600;
if (DeviceExtension->UartType >= Uart16450)
{
pCommProp->SettableBaud |= SERIAL_BAUD_14400 | SERIAL_BAUD_19200 | SERIAL_BAUD_38400;
pCommProp->MaxBaud = SERIAL_BAUD_38400;
}
if (DeviceExtension->UartType >= Uart16550)
{
pCommProp->SettableBaud |= SERIAL_BAUD_56K | SERIAL_BAUD_57600 | SERIAL_BAUD_115200 | SERIAL_BAUD_128K;
pCommProp->MaxBaud = SERIAL_BAUD_115200;
}
pCommProp->SettableData = SERIAL_DATABITS_5 | SERIAL_DATABITS_6 | SERIAL_DATABITS_7 | SERIAL_DATABITS_8;
pCommProp->SettableStopParity = SERIAL_STOPBITS_10 | SERIAL_STOPBITS_15 | SERIAL_STOPBITS_20
| SERIAL_PARITY_NONE | SERIAL_PARITY_ODD | SERIAL_PARITY_EVEN | SERIAL_PARITY_MARK | SERIAL_PARITY_SPACE;
return STATUS_SUCCESS;
}
NTSTATUS
SerialGetCommStatus(
OUT PSERIAL_STATUS pSerialStatus,
IN PSERIAL_DEVICE_EXTENSION DeviceExtension)
{
KIRQL Irql;
RtlZeroMemory(pSerialStatus, sizeof(SERIAL_STATUS));
pSerialStatus->Errors = 0;
if (DeviceExtension->BreakInterruptErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_BREAK;
if (DeviceExtension->SerialPerfStats.FrameErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_FRAMING;
if (DeviceExtension->SerialPerfStats.SerialOverrunErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_OVERRUN;
if (DeviceExtension->SerialPerfStats.BufferOverrunErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_QUEUEOVERRUN;
if (DeviceExtension->SerialPerfStats.ParityErrorCount)
pSerialStatus->Errors |= SERIAL_ERROR_PARITY;
pSerialStatus->HoldReasons = 0; /* FIXME */
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
pSerialStatus->AmountInInQueue = (DeviceExtension->InputBuffer.WritePosition + DeviceExtension->InputBuffer.Length
- DeviceExtension->InputBuffer.ReadPosition) % DeviceExtension->InputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
pSerialStatus->AmountInOutQueue = (DeviceExtension->OutputBuffer.WritePosition + DeviceExtension->OutputBuffer.Length
- DeviceExtension->OutputBuffer.ReadPosition) % DeviceExtension->OutputBuffer.Length;
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
pSerialStatus->EofReceived = FALSE; /* always FALSE */
pSerialStatus->WaitForImmediate = FALSE; /* always FALSE */
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
SerialDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
ULONG IoControlCode;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
ULONG LengthIn, LengthOut;
ULONG_PTR Information = 0;
PVOID BufferIn, BufferOut;
PUCHAR ComPortBase;
NTSTATUS Status;
DPRINT("Serial: IRP_MJ_DEVICE_CONTROL dispatch\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
LengthIn = Stack->Parameters.DeviceIoControl.InputBufferLength;
LengthOut = Stack->Parameters.DeviceIoControl.OutputBufferLength;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
IoControlCode = Stack->Parameters.DeviceIoControl.IoControlCode;
SerialGetUserBuffers(Irp, IoControlCode, &BufferIn, &BufferOut);
/* FIXME: need to probe buffers */
/* FIXME: see http://www.osronline.com/ddkx/serial/serref_61bm.htm */
switch (IoControlCode)
{
case IOCTL_SERIAL_CLEAR_STATS:
{
DPRINT("Serial: IOCTL_SERIAL_CLEAR_STATS\n");
KeSynchronizeExecution(
DeviceExtension->Interrupt,
(PKSYNCHRONIZE_ROUTINE)SerialClearPerfStats,
DeviceExtension);
Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_CLR_DTR:
{
DPRINT("Serial: IOCTL_SERIAL_CLR_DTR\n");
/* FIXME: If the handshake flow control of the device is configured to
* automatically use DTR, return STATUS_INVALID_PARAMETER */
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
DeviceExtension->MCR &= ~SR_MCR_DTR;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
break;
}
case IOCTL_SERIAL_CLR_RTS:
{
DPRINT("Serial: IOCTL_SERIAL_CLR_RTS\n");
/* FIXME: If the handshake flow control of the device is configured to
* automatically use RTS, return STATUS_INVALID_PARAMETER */
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
DeviceExtension->MCR &= ~SR_MCR_RTS;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
break;
}
case IOCTL_SERIAL_CONFIG_SIZE:
{
/* Obsolete on Microsoft Windows 2000+ */
PULONG pConfigSize;
DPRINT("Serial: IOCTL_SERIAL_CONFIG_SIZE\n");
if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pConfigSize = (PULONG)BufferOut;
*pConfigSize = 0;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_BAUD_RATE:
{
DPRINT("Serial: IOCTL_SERIAL_GET_BAUD_RATE\n");
if (LengthOut < sizeof(SERIAL_BAUD_RATE))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
((PSERIAL_BAUD_RATE)BufferOut)->BaudRate = DeviceExtension->BaudRate;
Information = sizeof(SERIAL_BAUD_RATE);
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_CHARS:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_GET_CHARS not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_GET_COMMSTATUS:
{
DPRINT("Serial: IOCTL_SERIAL_GET_COMMSTATUS\n");
if (LengthOut < sizeof(SERIAL_STATUS))
{
DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n");
Status = STATUS_BUFFER_TOO_SMALL;
}
else if (BufferOut == NULL)
{
DPRINT("Serial: return STATUS_INVALID_PARAMETER\n");
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = SerialGetCommStatus((PSERIAL_STATUS)BufferOut, DeviceExtension);
Information = sizeof(SERIAL_STATUS);
}
break;
}
case IOCTL_SERIAL_GET_DTRRTS:
{
PULONG pDtrRts;
DPRINT("Serial: IOCTL_SERIAL_GET_DTRRTS\n");
if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pDtrRts = (PULONG)BufferOut;
*pDtrRts = 0;
if (DeviceExtension->MCR & SR_MCR_DTR)
*pDtrRts |= SERIAL_DTR_STATE;
if (DeviceExtension->MCR & SR_MCR_RTS)
*pDtrRts |= SERIAL_RTS_STATE;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_HANDFLOW:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_GET_HANDFLOW not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_GET_LINE_CONTROL:
{
DPRINT("Serial: IOCTL_SERIAL_GET_LINE_CONTROL\n");
if (LengthOut < sizeof(SERIAL_LINE_CONTROL))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
*((PSERIAL_LINE_CONTROL)BufferOut) = DeviceExtension->SerialLineControl;
Information = sizeof(SERIAL_LINE_CONTROL);
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_MODEM_CONTROL:
{
PULONG pMCR;
DPRINT("Serial: IOCTL_SERIAL_GET_MODEM_CONTROL\n");
if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pMCR = (PULONG)BufferOut;
*pMCR = DeviceExtension->MCR;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS:
{
PULONG pMSR;
DPRINT("Serial: IOCTL_SERIAL_GET_MODEMSTATUS\n");
if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pMSR = (PULONG)BufferOut;
*pMSR = DeviceExtension->MSR;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_PROPERTIES:
{
DPRINT("Serial: IOCTL_SERIAL_GET_PROPERTIES\n");
if (LengthOut < sizeof(SERIAL_COMMPROP))
{
DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n");
Status = STATUS_BUFFER_TOO_SMALL;
}
else if (BufferOut == NULL)
{
DPRINT("Serial: return STATUS_INVALID_PARAMETER\n");
Status = STATUS_INVALID_PARAMETER;
}
else
{
Status = SerialGetCommProp((PSERIAL_COMMPROP)BufferOut, DeviceExtension);
Information = sizeof(SERIAL_COMMPROP);
}
break;
}
case IOCTL_SERIAL_GET_STATS:
{
DPRINT("Serial: IOCTL_SERIAL_GET_STATS\n");
if (LengthOut < sizeof(SERIALPERF_STATS))
{
DPRINT("Serial: return STATUS_BUFFER_TOO_SMALL\n");
Status = STATUS_BUFFER_TOO_SMALL;
}
else if (BufferOut == NULL)
{
DPRINT("Serial: return STATUS_INVALID_PARAMETER\n");
Status = STATUS_INVALID_PARAMETER;
}
else
{
KeSynchronizeExecution(DeviceExtension->Interrupt,
(PKSYNCHRONIZE_ROUTINE)SerialGetPerfStats, Irp);
Status = STATUS_SUCCESS;
Information = sizeof(SERIALPERF_STATS);
}
break;
}
case IOCTL_SERIAL_GET_TIMEOUTS:
{
DPRINT("Serial: IOCTL_SERIAL_GET_TIMEOUTS\n");
if (LengthOut != sizeof(SERIAL_TIMEOUTS) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
*(PSERIAL_TIMEOUTS)BufferOut = DeviceExtension->SerialTimeOuts;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_GET_WAIT_MASK:
{
PULONG pWaitMask;
DPRINT("Serial: IOCTL_SERIAL_GET_WAIT_MASK\n");
if (LengthOut != sizeof(ULONG) || BufferOut == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pWaitMask = (PULONG)BufferOut;
*pWaitMask = DeviceExtension->WaitMask;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_IMMEDIATE_CHAR:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_IMMEDIATE_CHAR not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_LSRMST_INSERT:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_LSRMST_INSERT not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_PURGE:
{
KIRQL Irql;
DPRINT("Serial: IOCTL_SERIAL_PURGE\n");
/* FIXME: SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT
* should stop current request */
if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
ULONG PurgeMask = *(PULONG)BufferIn;
Status = STATUS_SUCCESS;
/* FIXME: use SERIAL_PURGE_RXABORT and SERIAL_PURGE_TXABORT flags */
if (PurgeMask & SERIAL_PURGE_RXCLEAR)
{
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
DeviceExtension->InputBuffer.ReadPosition = DeviceExtension->InputBuffer.WritePosition = 0;
if (DeviceExtension->UartType >= Uart16550A)
{
/* Clear also Uart FIFO */
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_RCVR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
}
if (PurgeMask & SERIAL_PURGE_TXCLEAR)
{
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
DeviceExtension->OutputBuffer.ReadPosition = DeviceExtension->OutputBuffer.WritePosition = 0;
if (DeviceExtension->UartType >= Uart16550A)
{
/* Clear also Uart FIFO */
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), SR_FCR_CLEAR_XMIT);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
}
}
break;
}
case IOCTL_SERIAL_RESET_DEVICE:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_RESET_DEVICE not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_BAUD_RATE:
{
PULONG pNewBaudRate;
DPRINT("Serial: IOCTL_SERIAL_SET_BAUD_RATE\n");
if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pNewBaudRate = (PULONG)BufferIn;
Status = SerialSetBaudRate(DeviceExtension, *pNewBaudRate);
}
break;
}
case IOCTL_SERIAL_SET_BREAK_OFF:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_OFF not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_BREAK_ON:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_BREAK_ON not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_CHARS:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_CHARS not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_DTR:
{
/* FIXME: If the handshake flow control of the device is configured to
* automatically use DTR, return STATUS_INVALID_PARAMETER */
DPRINT("Serial: IOCTL_SERIAL_SET_DTR\n");
if (!(DeviceExtension->MCR & SR_MCR_DTR))
{
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
DeviceExtension->MCR |= SR_MCR_DTR;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
else
Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_SET_FIFO_CONTROL:
{
DPRINT("Serial: IOCTL_SERIAL_SET_FIFO_CONTROL\n");
if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
WRITE_PORT_UCHAR(SER_FCR(ComPortBase), (UCHAR)((*(PULONG)BufferIn) & 0xff));
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
break;
}
case IOCTL_SERIAL_SET_HANDFLOW:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_HANDFLOW not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_LINE_CONTROL:
{
DPRINT("Serial: IOCTL_SERIAL_SET_LINE_CONTROL\n");
if (LengthIn < sizeof(SERIAL_LINE_CONTROL))
Status = STATUS_BUFFER_TOO_SMALL;
else if (BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
Status = SerialSetLineControl(DeviceExtension, (PSERIAL_LINE_CONTROL)BufferIn);
break;
}
case IOCTL_SERIAL_SET_MODEM_CONTROL:
{
PULONG pMCR;
DPRINT("Serial: IOCTL_SERIAL_SET_MODEM_CONTROL\n");
if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
pMCR = (PULONG)BufferIn;
DeviceExtension->MCR = (UCHAR)(*pMCR & 0xff);
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
break;
}
case IOCTL_SERIAL_SET_QUEUE_SIZE:
{
if (LengthIn < sizeof(SERIAL_QUEUE_SIZE ))
return STATUS_BUFFER_TOO_SMALL;
else if (BufferIn == NULL)
return STATUS_INVALID_PARAMETER;
else
{
KIRQL Irql;
PSERIAL_QUEUE_SIZE NewQueueSize = (PSERIAL_QUEUE_SIZE)BufferIn;
Status = STATUS_SUCCESS;
if (NewQueueSize->InSize > DeviceExtension->InputBuffer.Length)
{
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
Status = IncreaseCircularBufferSize(&DeviceExtension->InputBuffer, NewQueueSize->InSize);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
}
if (NT_SUCCESS(Status) && NewQueueSize->OutSize > DeviceExtension->OutputBuffer.Length)
{
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
Status = IncreaseCircularBufferSize(&DeviceExtension->OutputBuffer, NewQueueSize->OutSize);
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
}
}
break;
}
case IOCTL_SERIAL_SET_RTS:
{
/* FIXME: If the handshake flow control of the device is configured to
* automatically use DTR, return STATUS_INVALID_PARAMETER */
DPRINT("Serial: IOCTL_SERIAL_SET_RTS\n");
if (!(DeviceExtension->MCR & SR_MCR_RTS))
{
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (NT_SUCCESS(Status))
{
DeviceExtension->MCR |= SR_MCR_RTS;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
}
}
else
Status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_SET_TIMEOUTS:
{
DPRINT("Serial: IOCTL_SERIAL_SET_TIMEOUTS\n");
if (LengthIn != sizeof(SERIAL_TIMEOUTS) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
DeviceExtension->SerialTimeOuts = *(PSERIAL_TIMEOUTS)BufferIn;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_SET_WAIT_MASK:
{
PULONG pWaitMask;
DPRINT("Serial: IOCTL_SERIAL_SET_WAIT_MASK\n");
if (LengthIn != sizeof(ULONG) || BufferIn == NULL)
Status = STATUS_INVALID_PARAMETER;
else
{
pWaitMask = (PULONG)BufferIn;
DeviceExtension->WaitMask = *pWaitMask;
Status = STATUS_SUCCESS;
}
break;
}
case IOCTL_SERIAL_SET_XOFF:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_XOFF not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_SET_XON:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_SET_XON not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_WAIT_ON_MASK:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_WAIT_ON_MASK not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
case IOCTL_SERIAL_XOFF_COUNTER:
{
/* FIXME */
DPRINT1("Serial: IOCTL_SERIAL_XOFF_COUNTER not implemented.\n");
Status = STATUS_NOT_IMPLEMENTED;
break;
}
default:
{
/* Pass Irp to lower driver */
DPRINT("Serial: Unknown IOCTL code 0x%x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceExtension->LowerDevice, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+76
View File
@@ -0,0 +1,76 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/info.c
* PURPOSE: Serial IRP_MJ_QUERY_INFORMATION operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG2
#include "serial.h"
NTSTATUS STDCALL
SerialQueryInformation(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PIO_STACK_LOCATION Stack;
PVOID SystemBuffer;
ULONG BufferLength;
ULONG_PTR Information = 0;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
BufferLength = Stack->Parameters.QueryFile.Length;
switch (Stack->Parameters.QueryFile.FileInformationClass)
{
case FileStandardInformation:
{
PFILE_STANDARD_INFORMATION StandardInfo = (PFILE_STANDARD_INFORMATION)SystemBuffer;
DPRINT("Serial: IRP_MJ_QUERY_INFORMATION / FileStandardInformation\n");
if (BufferLength < sizeof(FILE_STANDARD_INFORMATION))
Status = STATUS_BUFFER_OVERFLOW;
else
{
StandardInfo->AllocationSize.QuadPart = 0;
StandardInfo->EndOfFile.QuadPart = 0;
StandardInfo->Directory = FALSE;
StandardInfo->NumberOfLinks = 0;
StandardInfo->DeletePending = FALSE; /* FIXME: should be TRUE sometimes */
Status = STATUS_SUCCESS;
}
break;
}
case FilePositionInformation:
{
PFILE_POSITION_INFORMATION PositionInfo = (PFILE_POSITION_INFORMATION)SystemBuffer;
DPRINT("Serial: IRP_MJ_QUERY_INFORMATION / FilePositionInformation\n");
if (BufferLength < sizeof(PFILE_POSITION_INFORMATION))
Status = STATUS_BUFFER_OVERFLOW;
else
{
PositionInfo->CurrentByteOffset.QuadPart = 0;
Status = STATUS_SUCCESS;
}
break;
}
default:
{
DPRINT("Serial: IRP_MJ_QUERY_INFORMATION: Unexpected file information class 0x%02x\n", Stack->Parameters.QueryFile.FileInformationClass);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+194
View File
@@ -0,0 +1,194 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/bus/serial/legacy.c
* PURPOSE: Legacy serial port enumeration
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
* Mark Junker (mjscod@gmx.de)
*/
#define NDEBUG
#include "serial.h"
UART_TYPE
SerialDetectUartType(
IN PUCHAR BaseAddress)
{
UCHAR Lcr, TestLcr;
UCHAR OldScr, Scr5A, ScrA5;
BOOLEAN FifoEnabled;
UCHAR NewFifoStatus;
Lcr = READ_PORT_UCHAR(SER_LCR(BaseAddress));
WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr ^ 0xFF);
TestLcr = READ_PORT_UCHAR(SER_LCR(BaseAddress)) ^ 0xFF;
WRITE_PORT_UCHAR(SER_LCR(BaseAddress), Lcr);
/* Accessing the LCR must work for a usable serial port */
if (TestLcr != Lcr)
return UartUnknown;
/* Ensure that all following accesses are done as required */
READ_PORT_UCHAR(SER_RBR(BaseAddress));
READ_PORT_UCHAR(SER_IER(BaseAddress));
READ_PORT_UCHAR(SER_IIR(BaseAddress));
READ_PORT_UCHAR(SER_LCR(BaseAddress));
READ_PORT_UCHAR(SER_MCR(BaseAddress));
READ_PORT_UCHAR(SER_LSR(BaseAddress));
READ_PORT_UCHAR(SER_MSR(BaseAddress));
READ_PORT_UCHAR(SER_SCR(BaseAddress));
/* Test scratch pad */
OldScr = READ_PORT_UCHAR(SER_SCR(BaseAddress));
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0x5A);
Scr5A = READ_PORT_UCHAR(SER_SCR(BaseAddress));
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), 0xA5);
ScrA5 = READ_PORT_UCHAR(SER_SCR(BaseAddress));
WRITE_PORT_UCHAR(SER_SCR(BaseAddress), OldScr);
/* When non-functional, we have a 8250 */
if (Scr5A != 0x5A || ScrA5 != 0xA5)
return Uart8250;
/* Test FIFO type */
FifoEnabled = (READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0x80) != 0;
WRITE_PORT_UCHAR(SER_FCR(BaseAddress), SR_FCR_ENABLE_FIFO);
NewFifoStatus = READ_PORT_UCHAR(SER_IIR(BaseAddress)) & 0xC0;
if (!FifoEnabled)
WRITE_PORT_UCHAR(SER_FCR(BaseAddress), 0);
switch (NewFifoStatus)
{
case 0x00:
return Uart16450;
case 0x40:
case 0x80:
/* Not sure about this but the documentation says that 0x40
* indicates an unusable FIFO but my tests only worked
* with 0x80 */
return Uart16550;
}
/* FIFO is only functional for 16550A+ */
return Uart16550A;
}
static NTSTATUS
DetectLegacyDevice(
IN PDRIVER_OBJECT DriverObject,
IN ULONG ComPortBase,
IN ULONG Irq,
IN PULONG pComPortNumber OPTIONAL)
{
ULONG ResourceListSize;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
BOOLEAN ConflictDetected;
UART_TYPE UartType;
PDEVICE_OBJECT Pdo = NULL;
PDEVICE_OBJECT Fdo;
KIRQL Dirql;
NTSTATUS Status;
/* Create resource list */
ResourceListSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, ResourceListSize, SERIAL_TAG);
if (!ResourceList)
return STATUS_INSUFFICIENT_RESOURCES;
ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = InterfaceTypeUndefined;
ResourceList->List[0].BusNumber = -1; /* unknown */
ResourceList->List[0].PartialResourceList.Version = 1;
ResourceList->List[0].PartialResourceList.Revision = 1;
ResourceList->List[0].PartialResourceList.Count = 2;
ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
ResourceDescriptor->Type = CmResourceTypePort;
ResourceDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
ResourceDescriptor->u.Port.Start.u.HighPart = 0;
ResourceDescriptor->u.Port.Start.u.LowPart = ComPortBase;
ResourceDescriptor->u.Port.Length = 8;
ResourceDescriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[1];
ResourceDescriptor->Type = CmResourceTypeInterrupt;
ResourceDescriptor->ShareDisposition = CmResourceShareShared;
ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
ResourceDescriptor->u.Interrupt.Vector = HalGetInterruptVector(
Internal, 0, 0, Irq,
&Dirql,
&ResourceDescriptor->u.Interrupt.Affinity);
ResourceDescriptor->u.Interrupt.Level = (ULONG)Dirql;
/* Report resource list */
Status = IoReportResourceForDetection(
DriverObject, ResourceList, ResourceListSize,
NULL, NULL, 0,
&ConflictDetected);
if (Status == STATUS_CONFLICTING_ADDRESSES)
{
DPRINT("Serial: conflict detected for serial port at 0x%lx (Irq %lu)\n", ComPortBase, Irq);
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
return STATUS_DEVICE_NOT_CONNECTED;
}
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
return Status;
}
/* Test if port exists */
UartType = SerialDetectUartType((PUCHAR)ComPortBase);
/* Report device if detected... */
if (UartType != UartUnknown)
{
Status = IoReportDetectedDevice(
DriverObject,
ResourceList->List[0].InterfaceType, ResourceList->List[0].BusNumber, -1 /* unknown */,
ResourceList, NULL,
TRUE,
&Pdo);
if (NT_SUCCESS(Status))
{
Status = SerialAddDeviceInternal(DriverObject, Pdo, UartType, pComPortNumber, &Fdo);
if (NT_SUCCESS(Status))
{
Status = SerialPnpStartDevice(Fdo, ResourceList);
}
}
}
else
{
/* Release resources */
Status = IoReportResourceForDetection(
DriverObject, NULL, 0,
NULL, NULL, 0,
&ConflictDetected);
Status = STATUS_DEVICE_NOT_CONNECTED;
}
ExFreePoolWithTag(ResourceList, SERIAL_TAG);
return Status;
}
NTSTATUS
DetectLegacyDevices(
IN PDRIVER_OBJECT DriverObject)
{
ULONG ComPortBase[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
ULONG Irq[] = { 4, 3, 4, 3 };
ULONG ComPortNumber[] = { 1, 2, 3, 4 };
ULONG i;
NTSTATUS Status;
NTSTATUS ReturnedStatus = STATUS_SUCCESS;
for (i = 0; i < sizeof(ComPortBase)/sizeof(ComPortBase[0]); i++)
{
Status = DetectLegacyDevice(DriverObject, ComPortBase[i], Irq[i], &ComPortNumber[i]);
if (!NT_SUCCESS(Status) && Status != STATUS_DEVICE_NOT_CONNECTED)
ReturnedStatus = Status;
DPRINT("Serial: Legacy device at 0x%x (IRQ %lu): status = 0x%08lx\n", ComPortBase[i], Irq[i], Status);
}
return ReturnedStatus;
}
+13 -1
View File
@@ -6,7 +6,19 @@ TARGET_TYPE = driver
TARGET_NAME = serial
TARGET_OBJECTS = serial.o
TARGET_OBJECTS = \
circularbuffer.o \
cleanup.o \
close.o \
create.o \
devctrl.o \
info.o \
legacy.o \
misc.o \
pnp.o \
power.o \
rw.o \
serial.o
TARGET_CFLAGS = -Wall -Werror -D__USE_W32API
+215
View File
@@ -0,0 +1,215 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/misc.c
* PURPOSE: Misceallenous operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
ForwardIrpAndWaitCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
if (Irp->PendingReturned)
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
KEVENT Event;
NTSTATUS Status;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
DPRINT("Serial: Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
IoSetCompletionRoutine(Irp, ForwardIrpAndWaitCompletion, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
if (NT_SUCCESS(Status))
Status = Irp->IoStatus.Status;
}
return Status;
}
NTSTATUS STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_OBJECT LowerDevice = ((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(LowerDevice, Irp);
}
VOID STDCALL
SerialReceiveByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID Unused1,
IN PVOID Unused2)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PUCHAR ComPortBase;
UCHAR Byte;
KIRQL Irql;
UCHAR IER;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
while (READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_DATA_RECEIVED)
{
Byte = READ_PORT_UCHAR(SER_RBR(ComPortBase));
DPRINT("Serial: Byte received on COM%lu: 0x%02x\n",
DeviceExtension->ComPort, Byte);
Status = PushCircularBufferEntry(&DeviceExtension->InputBuffer, Byte);
if (NT_SUCCESS(Status))
DeviceExtension->SerialPerfStats.ReceivedCount++;
else
DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
}
KeSetEvent(&DeviceExtension->InputBufferNotEmpty, 0, FALSE);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
/* allow new interrupts */
IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_DATA_RECEIVED);
}
VOID STDCALL
SerialSendByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID Unused1,
IN PVOID Unused2)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PUCHAR ComPortBase;
UCHAR Byte;
KIRQL Irql;
UCHAR IER;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)pDeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
while (!IsCircularBufferEmpty(&DeviceExtension->OutputBuffer)
&& READ_PORT_UCHAR(SER_LSR(ComPortBase)) & SR_LSR_THR_EMPTY)
{
Status = PopCircularBufferEntry(&DeviceExtension->OutputBuffer, &Byte);
if (!NT_SUCCESS(Status))
break;
WRITE_PORT_UCHAR(SER_THR(ComPortBase), Byte);
DPRINT("Serial: Byte sent to COM%lu: 0x%02x\n",
DeviceExtension->ComPort, Byte);
DeviceExtension->SerialPerfStats.TransmittedCount++;
}
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
/* allow new interrupts */
IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_THR_EMPTY);
}
BOOLEAN STDCALL
SerialInterruptService(
IN PKINTERRUPT Interrupt,
IN OUT PVOID ServiceContext)
{
PDEVICE_OBJECT DeviceObject;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PUCHAR ComPortBase;
UCHAR Iir;
DeviceObject = (PDEVICE_OBJECT)ServiceContext;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
Iir = READ_PORT_UCHAR(SER_IIR(ComPortBase));
if (Iir == 0xff)
return TRUE;
Iir &= SR_IIR_ID_MASK;
if ((Iir & SR_IIR_SELF) != 0) { return FALSE; }
switch (Iir)
{
case SR_IIR_MSR_CHANGE:
{
UCHAR MSR, IER;
DPRINT("Serial: SR_IIR_MSR_CHANGE\n");
MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
if (MSR & SR_MSR_CTS_CHANGED)
{
if (MSR & SR_MSR_CTS)
KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
else
; /* FIXME: stop transmission */
}
if (MSR & SR_MSR_DSR_CHANGED)
{
if (MSR & SR_MSR_DSR)
KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
else
; /* FIXME: stop reception */
}
IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER | SR_IER_MSR_CHANGE);
return TRUE;
}
case SR_IIR_THR_EMPTY:
{
DPRINT("Serial: SR_IIR_THR_EMPTY\n");
KeInsertQueueDpc(&DeviceExtension->SendByteDpc, NULL, NULL);
return TRUE;
}
case SR_IIR_DATA_RECEIVED:
{
DPRINT("Serial: SR_IIR_DATA_RECEIVED\n");
KeInsertQueueDpc(&DeviceExtension->ReceivedByteDpc, NULL, NULL);
return TRUE;
}
case SR_IIR_ERROR:
{
UCHAR LSR;
DPRINT("Serial: SR_IIR_ERROR\n");
LSR = READ_PORT_UCHAR(SER_LSR(ComPortBase));
if (LSR & SR_LSR_OVERRUN_ERROR)
InterlockedIncrement(&DeviceExtension->SerialPerfStats.SerialOverrunErrorCount);
if (LSR & SR_LSR_PARITY_ERROR)
InterlockedIncrement(&DeviceExtension->SerialPerfStats.ParityErrorCount);
if (LSR & SR_LSR_FRAMING_ERROR)
InterlockedIncrement(&DeviceExtension->SerialPerfStats.FrameErrorCount);
if (LSR & SR_LSR_BREAK_INT)
InterlockedIncrement(&DeviceExtension->BreakInterruptErrorCount);
return TRUE;
}
}
return FALSE;
}
+389
View File
@@ -0,0 +1,389 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/pnp.c
* PURPOSE: Serial IRP_MJ_PNP operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
/* FIXME: call IoAcquireRemoveLock/IoReleaseRemoveLock around each I/O operation */
#define INITGUID
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
SerialAddDeviceInternal(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo,
IN UART_TYPE UartType,
IN PULONG pComPortNumber OPTIONAL,
OUT PDEVICE_OBJECT* pFdo OPTIONAL)
{
PDEVICE_OBJECT Fdo = NULL;
PSERIAL_DEVICE_EXTENSION DeviceExtension = NULL;
NTSTATUS Status;
WCHAR DeviceNameBuffer[32];
UNICODE_STRING DeviceName;
//UNICODE_STRING SymbolicLinkName;
static ULONG DeviceNumber = 0;
static ULONG ComPortNumber = 1;
DPRINT("Serial: SerialAddDeviceInternal called\n");
/* Create new device object */
swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
Status = IoCreateDevice(DriverObject,
sizeof(SERIAL_DEVICE_EXTENSION),
&DeviceName,
FILE_DEVICE_SERIAL_PORT,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoCreateDevice() failed with status 0x%08x\n", Status);
Fdo = NULL;
goto ByeBye;
}
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(SERIAL_DEVICE_EXTENSION));
/* Register device interface */
#if 0 /* FIXME: activate */
Status = IoRegisterDeviceInterface(Pdo, &GUID_DEVINTERFACE_COMPORT, NULL, &SymbolicLinkName);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoRegisterDeviceInterface() failed with status 0x%08x\n", Status);
goto ByeBye;
}
DPRINT1("Serial: IoRegisterDeviceInterface() returned '%wZ'\n", &SymbolicLinkName);
Status = IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoSetDeviceInterfaceState() failed with status 0x%08x\n", Status);
goto ByeBye;
}
RtlFreeUnicodeString(&SymbolicLinkName);
#endif
DeviceExtension->SerialPortNumber = DeviceNumber++;
if (pComPortNumber == NULL)
DeviceExtension->ComPort = ComPortNumber++;
else
DeviceExtension->ComPort = *pComPortNumber;
DeviceExtension->Pdo = Pdo;
DeviceExtension->PnpState = dsStopped;
DeviceExtension->UartType = UartType;
Status = InitializeCircularBuffer(&DeviceExtension->InputBuffer, 16);
if (!NT_SUCCESS(Status)) goto ByeBye;
Status = InitializeCircularBuffer(&DeviceExtension->OutputBuffer, 16);
if (!NT_SUCCESS(Status)) goto ByeBye;
IoInitializeRemoveLock(&DeviceExtension->RemoveLock, SERIAL_TAG, 0, 0);
KeInitializeSpinLock(&DeviceExtension->InputBufferLock);
KeInitializeSpinLock(&DeviceExtension->OutputBufferLock);
KeInitializeEvent(&DeviceExtension->InputBufferNotEmpty, NotificationEvent, FALSE);
KeInitializeDpc(&DeviceExtension->ReceivedByteDpc, SerialReceiveByte, DeviceExtension);
KeInitializeDpc(&DeviceExtension->SendByteDpc, SerialSendByte, DeviceExtension);
Fdo->Flags |= DO_POWER_PAGABLE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoAttachDeviceToDeviceStackSafe() failed with status 0x%08x\n", Status);
goto ByeBye;
}
Fdo->Flags |= DO_BUFFERED_IO;
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
if (pFdo)
{
*pFdo = Fdo;
}
return STATUS_SUCCESS;
ByeBye:
if (Fdo)
{
FreeCircularBuffer(&DeviceExtension->InputBuffer);
FreeCircularBuffer(&DeviceExtension->OutputBuffer);
IoDeleteDevice(Fdo);
}
return Status;
}
NTSTATUS STDCALL
SerialAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
/* Serial.sys is a legacy driver. AddDevice is called once
* with a NULL Pdo just after the driver initialization.
* Detect this case and return success.
*/
if (Pdo == NULL)
return STATUS_SUCCESS;
/* We have here a PDO that does not correspond to a legacy
* serial port. So call the internal AddDevice function.
*/
return SerialAddDeviceInternal(DriverObject, Pdo, UartUnknown, NULL, NULL);
}
NTSTATUS STDCALL
SerialPnpStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST ResourceList)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
WCHAR DeviceNameBuffer[32];
UNICODE_STRING DeviceName;
WCHAR LinkNameBuffer[32];
UNICODE_STRING LinkName;
WCHAR ComPortBuffer[32];
UNICODE_STRING ComPort;
ULONG Vector = 0;
ULONG i, j;
UCHAR IER;
KIRQL Dirql;
KAFFINITY Affinity = 0;
KINTERRUPT_MODE InterruptMode = Latched;
BOOLEAN ShareInterrupt = TRUE;
OBJECT_ATTRIBUTES objectAttributes;
PUCHAR ComPortBase;
UNICODE_STRING KeyName;
HANDLE hKey;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->PnpState == dsStopped);
DeviceExtension->BaudRate = 19200 | SERIAL_BAUD_USER;
DeviceExtension->BaseAddress = 0;
Dirql = 0;
for (i = 0; i < ResourceList->Count; i++)
{
for (j = 0; j < ResourceList->List[i].PartialResourceList.Count; j++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor = &ResourceList->List[i].PartialResourceList.PartialDescriptors[j];
switch (PartialDescriptor->Type)
{
case CmResourceTypePort:
if (PartialDescriptor->u.Port.Length < 8)
return STATUS_INSUFFICIENT_RESOURCES;
if (DeviceExtension->BaseAddress != 0)
return STATUS_UNSUCCESSFUL;
DeviceExtension->BaseAddress = PartialDescriptor->u.Port.Start.u.LowPart;
break;
case CmResourceTypeInterrupt:
if (Dirql != 0)
return STATUS_UNSUCCESSFUL;
Dirql = (KIRQL)PartialDescriptor->u.Interrupt.Level;
Vector = PartialDescriptor->u.Interrupt.Vector;
Affinity = PartialDescriptor->u.Interrupt.Affinity;
if (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED)
InterruptMode = Latched;
else
InterruptMode = LevelSensitive;
ShareInterrupt = (PartialDescriptor->ShareDisposition == CmResourceShareShared);
break;
}
}
}
DPRINT("Serial: New COM port. Base = 0x%lx, Irql = %u\n",
DeviceExtension->BaseAddress, Dirql);
if (!DeviceExtension->BaseAddress)
return STATUS_INSUFFICIENT_RESOURCES;
if (!Dirql)
return STATUS_INSUFFICIENT_RESOURCES;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
if (DeviceExtension->UartType == UartUnknown)
DeviceExtension->UartType = SerialDetectUartType(ComPortBase);
/* Get current settings */
DeviceExtension->MCR = READ_PORT_UCHAR(SER_MCR(ComPortBase));
DeviceExtension->MSR = READ_PORT_UCHAR(SER_MSR(ComPortBase));
DeviceExtension->WaitMask = 0;
/* Set baud rate */
Status = SerialSetBaudRate(DeviceExtension, DeviceExtension->BaudRate);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: SerialSetBaudRate() failed with status 0x%08x\n", Status);
return Status;
}
/* Set line control */
DeviceExtension->SerialLineControl.StopBits = STOP_BIT_1;
DeviceExtension->SerialLineControl.Parity = NO_PARITY;
DeviceExtension->SerialLineControl.WordLength = 8;
Status = SerialSetLineControl(DeviceExtension, &DeviceExtension->SerialLineControl);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: SerialSetLineControl() failed with status 0x%08x\n", Status);
return Status;
}
/* Clear receive/transmit buffers */
if (DeviceExtension->UartType >= Uart16550A)
{
/* 16550 UARTs also have FIFO queues, but they are unusable due to a bug */
WRITE_PORT_UCHAR(SER_FCR(ComPortBase),
SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT);
}
/* Create link \DosDevices\COMX -> \Device\SerialX */
swprintf(DeviceNameBuffer, L"\\Device\\Serial%lu", DeviceExtension->SerialPortNumber);
swprintf(LinkNameBuffer, L"\\DosDevices\\COM%lu", DeviceExtension->ComPort);
swprintf(ComPortBuffer, L"COM%lu", DeviceExtension->ComPort);
RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
RtlInitUnicodeString(&LinkName, LinkNameBuffer);
RtlInitUnicodeString(&ComPort, ComPortBuffer);
Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoCreateSymbolicLink() failed with status 0x%08x\n", Status);
return Status;
}
/* Connect interrupt and enable them */
Status = IoConnectInterrupt(
&DeviceExtension->Interrupt, SerialInterruptService,
DeviceObject, NULL,
Vector, Dirql, Dirql,
InterruptMode, ShareInterrupt,
Affinity, FALSE);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: IoConnectInterrupt() failed with status 0x%08x\n", Status);
IoDeleteSymbolicLink(&LinkName);
return Status;
}
/* Write an entry value under HKLM\HARDWARE\DeviceMap\SERIALCOMM */
/* This step is not mandatory, so don't exit in case of error */
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\DeviceMap\\SERIALCOMM");
InitializeObjectAttributes(&objectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = ZwCreateKey(&hKey, KEY_SET_VALUE, &objectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
if (NT_SUCCESS(Status))
{
/* Key = \Device\Serialx, Value = COMx */
ZwSetValueKey(hKey, &DeviceName, 0, REG_SZ, &ComPortBuffer, ComPort.Length + sizeof(WCHAR));
ZwClose(hKey);
}
DeviceExtension->PnpState = dsStarted;
/* Activate interrupt modes */
IER = READ_PORT_UCHAR(SER_IER(ComPortBase));
IER |= SR_IER_DATA_RECEIVED | SR_IER_THR_EMPTY | SR_IER_LSR_CHANGE | SR_IER_MSR_CHANGE;
WRITE_PORT_UCHAR(SER_IER(ComPortBase), IER);
/* Activate DTR, RTS */
DeviceExtension->MCR |= SR_MCR_DTR | SR_MCR_RTS;
WRITE_PORT_UCHAR(SER_MCR(ComPortBase), DeviceExtension->MCR);
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
SerialPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = 0;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
case IRP_MN_START_DEVICE:
{
BOOLEAN ConflictDetected;
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* FIXME: first HACK: PnP manager can send multiple
* IRP_MN_START_DEVICE for one device
*/
if (((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->PnpState != dsStopped)
{
DPRINT1("Serial: device already started. Ignoring this irp!\n");
Status = STATUS_SUCCESS;
break;
}
/* FIXME: second HACK: verify that we have some allocated resources.
* It seems not to be always the case on some hardware
*/
if (Stack->Parameters.StartDevice.AllocatedResources == NULL)
{
DPRINT1("Serial: no allocated resources. Can't start COM%lu\n",
((PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->ComPort);
Status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
/* FIXME: third HACK: verify that we don't have resource conflict,
* because PnP manager doesn't do it automatically
*/
Status = IoReportResourceForDetection(
DeviceObject->DriverObject, Stack->Parameters.StartDevice.AllocatedResources, 0,
NULL, NULL, 0,
&ConflictDetected);
if (!NT_SUCCESS(Status))
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
Status = SerialPnpStartDevice(
DeviceObject,
Stack->Parameters.StartDevice.AllocatedResources);
break;
}
/* IRP_MN_QUERY_STOP_DEVICE (FIXME: required) */
/* IRP_MN_STOP_DEVICE (FIXME: required) */
/* IRP_MN_CANCEL_STOP_DEVICE (FIXME: required) */
/* IRP_MN_QUERY_REMOVE_DEVICE (FIXME: required) */
/* case IRP_MN_REMOVE_DEVICE (FIXME: required) */
/*{
DPRINT("Serial: IRP_MJ_PNP / IRP_MN_REMOVE_DEVICE\n");
IoAcquireRemoveLock
IoReleaseRemoveLockAndWait
pass request to DeviceExtension-LowerDriver
IoDeleteDevice(Fdo) and/or IoDetachDevice
break;
}*/
/* IRP_MN_CANCEL_REMOVE_DEVICE (FIXME: required) */
/* IRP_MN_SURPRISE_REMOVAL (FIXME: required) */
/* IRP_MN_QUERY_CAPABILITIES (optional) */
/* IRP_MN_QUERY_PNP_DEVICE_STATE (optional) */
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS (optional) */
/* IRP_MN_DEVICE_USAGE_NOTIFICATION (FIXME: required or optional ???) */
/* IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations (optional) */
/* IRP_MN_QUERY_DEVICE_RELATIONS / RemovalRelations (optional) */
/* IRP_MN_QUERY_INTERFACE (optional) */
default:
{
DPRINT1("Serial: unknown minor function 0x%x\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+24
View File
@@ -0,0 +1,24 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/power.c
* PURPOSE: Serial IRP_MJ_POWER operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
NTSTATUS STDCALL
SerialPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
DPRINT("Serial: IRP_MJ_POWER dispatch\n");
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
+305
View File
@@ -0,0 +1,305 @@
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/create.c
* PURPOSE: Serial IRP_MJ_READ/IRP_MJ_WRITE operations
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#define NDEBUG
#include "serial.h"
static PVOID
SerialGetUserBuffer(IN PIRP Irp)
{
ASSERT(Irp);
return Irp->AssociatedIrp.SystemBuffer;
}
static VOID
ReadBytes(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PWORKITEM_DATA WorkItemData)
{
PSERIAL_DEVICE_EXTENSION DeviceExtension;
PUCHAR ComPortBase;
ULONG Length;
PUCHAR Buffer;
UCHAR ReceivedByte;
KTIMER TotalTimeoutTimer;
KIRQL Irql;
ULONG ObjectCount;
PVOID ObjectsArray[2];
ULONG_PTR Information = 0;
NTSTATUS Status;
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
Buffer = SerialGetUserBuffer(Irp);
DPRINT("Serial: UseIntervalTimeout = %s, IntervalTimeout = %lu\n",
WorkItemData->UseIntervalTimeout ? "YES" : "NO",
WorkItemData->UseIntervalTimeout ? WorkItemData->IntervalTimeout.QuadPart : 0);
DPRINT("Serial: UseTotalTimeout = %s\n",
WorkItemData->UseTotalTimeout ? "YES" : "NO");
ObjectCount = 1;
ObjectsArray[0] = &DeviceExtension->InputBufferNotEmpty;
if (WorkItemData->UseTotalTimeout)
{
KeInitializeTimer(&TotalTimeoutTimer);
KeSetTimer(&TotalTimeoutTimer, WorkItemData->TotalTimeoutTime, NULL);
ObjectsArray[ObjectCount] = &TotalTimeoutTimer;
ObjectCount++;
}
/* while buffer is not fully filled */
while (Length > 0)
{
/* read already received bytes from buffer */
KeAcquireSpinLock(&DeviceExtension->InputBufferLock, &Irql);
while (!IsCircularBufferEmpty(&DeviceExtension->InputBuffer)
&& Length > 0)
{
PopCircularBufferEntry(&DeviceExtension->InputBuffer, &ReceivedByte);
DPRINT("Serial: reading byte from buffer: 0x%02x\n", ReceivedByte);
Buffer[Information++] = ReceivedByte;
Length--;
}
KeClearEvent(&DeviceExtension->InputBufferNotEmpty);
KeReleaseSpinLock(&DeviceExtension->InputBufferLock, Irql);
if (WorkItemData->DontWait
&& !(WorkItemData->ReadAtLeastOneByte && Information == 0))
{
DPRINT("Serial: buffer empty. Don't wait more bytes\n");
break;
}
Status = KeWaitForMultipleObjects(
ObjectCount,
ObjectsArray,
WaitAny,
Executive,
KernelMode,
FALSE,
(WorkItemData->UseIntervalTimeout && Information > 0) ? &WorkItemData->IntervalTimeout : NULL,
NULL);
if (Status == STATUS_TIMEOUT /* interval timeout */
|| Status == STATUS_WAIT_1) /* total timeout */
{
DPRINT("Serial: timeout when reading bytes. Status = 0x%08lx\n", Status);
break;
}
}
/* stop total timeout timer */
if (WorkItemData->UseTotalTimeout)
KeCancelTimer(&TotalTimeoutTimer);
Irp->IoStatus.Information = Information;
if (Information == 0)
Irp->IoStatus.Status = STATUS_TIMEOUT;
else
Irp->IoStatus.Status = STATUS_SUCCESS;
}
static VOID STDCALL
SerialReadWorkItem(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID pWorkItemData /* real type PWORKITEM_DATA */)
{
PWORKITEM_DATA WorkItemData;
PIRP Irp;
DPRINT("Serial: SerialReadWorkItem() called\n");
WorkItemData = (PWORKITEM_DATA)pWorkItemData;
Irp = WorkItemData->Irp;
ReadBytes(DeviceObject, Irp, WorkItemData);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoFreeWorkItem(WorkItemData->IoWorkItem);
ExFreePoolWithTag(pWorkItemData, SERIAL_TAG);
}
NTSTATUS STDCALL
SerialRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
ULONG Length;
PUCHAR Buffer;
PWORKITEM_DATA WorkItemData;
PIO_WORKITEM WorkItem;
NTSTATUS Status;
DPRINT("Serial: IRP_MJ_READ\n");
Stack = IoGetCurrentIrpStackLocation(Irp);
Length = Stack->Parameters.Read.Length;
Buffer = SerialGetUserBuffer(Irp);
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if (Stack->Parameters.Read.ByteOffset.QuadPart != 0 || Buffer == NULL)
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
if (Length == 0)
{
Status = STATUS_SUCCESS;
goto ByeBye;
}
/* Allocate memory for parameters */
WorkItemData = ExAllocatePoolWithTag(PagedPool, sizeof(WORKITEM_DATA), SERIAL_TAG);
if (!WorkItemData)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto ByeBye;
}
RtlZeroMemory(WorkItemData, sizeof(WORKITEM_DATA));
WorkItemData->Irp = Irp;
/* Calculate time outs */
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant > 0 &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant < INFINITE)
{
/* read at least one byte, and at most bytes already received */
WorkItemData->DontWait = TRUE;
WorkItemData->ReadAtLeastOneByte = TRUE;
}
else if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout == INFINITE &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant == 0 &&
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier == 0)
{
/* read only bytes that are already in buffer */
WorkItemData->DontWait = TRUE;
}
else
{
/* use timeouts */
if (DeviceExtension->SerialTimeOuts.ReadIntervalTimeout != 0)
{
WorkItemData->UseIntervalTimeout = TRUE;
WorkItemData->IntervalTimeout.QuadPart = DeviceExtension->SerialTimeOuts.ReadIntervalTimeout;
}
if (DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier != 0 ||
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant != 0)
{
ULONG TotalTimeout;
LARGE_INTEGER SystemTime;
WorkItemData->UseTotalTimeout = TRUE;
TotalTimeout = DeviceExtension->SerialTimeOuts.ReadTotalTimeoutConstant +
DeviceExtension->SerialTimeOuts.ReadTotalTimeoutMultiplier * Length;
KeQuerySystemTime(&SystemTime);
WorkItemData->TotalTimeoutTime.QuadPart = SystemTime.QuadPart +
TotalTimeout * 10000;
}
}
/* Pend IRP */
WorkItem = IoAllocateWorkItem(DeviceObject);
if (WorkItem)
{
WorkItemData->IoWorkItem = WorkItem;
IoQueueWorkItem(WorkItem, SerialReadWorkItem, DelayedWorkQueue, WorkItemData);
IoMarkIrpPending(Irp);
return STATUS_PENDING;
}
/* insufficient resources, we can't pend the Irp */
CHECKPOINT;
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(WorkItemData, SERIAL_TAG);
goto ByeBye;
}
ReadBytes(DeviceObject, Irp, WorkItemData);
Status = Irp->IoStatus.Status;
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
ByeBye:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS STDCALL
SerialWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack;
PSERIAL_DEVICE_EXTENSION DeviceExtension;
ULONG Length;
ULONG_PTR Information = 0;
PUCHAR Buffer;
PUCHAR ComPortBase;
KIRQL Irql;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("Serial: IRP_MJ_WRITE\n");
/* FIXME: pend operation if possible */
/* FIXME: use write timeouts */
Stack = IoGetCurrentIrpStackLocation(Irp);
Length = Stack->Parameters.Write.Length;
Buffer = SerialGetUserBuffer(Irp);
DeviceExtension = (PSERIAL_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ComPortBase = (PUCHAR)DeviceExtension->BaseAddress;
if (Stack->Parameters.Write.ByteOffset.QuadPart != 0 || Buffer == NULL)
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
if (!NT_SUCCESS(Status))
goto ByeBye;
/* push bytes into output buffer */
KeAcquireSpinLock(&DeviceExtension->OutputBufferLock, &Irql);
while (Information < Length)
{
Status = PushCircularBufferEntry(&DeviceExtension->OutputBuffer, Buffer[Information]);
if (!NT_SUCCESS(Status))
{
DPRINT("Serial: buffer overrun on COM%lu\n", DeviceExtension->ComPort);
DeviceExtension->SerialPerfStats.BufferOverrunErrorCount++;
break;
}
Information++;
}
KeReleaseSpinLock(&DeviceExtension->OutputBufferLock, Irql);
IoReleaseRemoveLock(&DeviceExtension->RemoveLock, (PVOID)DeviceExtension->ComPort);
/* send bytes */
SerialSendByte(NULL, DeviceExtension, NULL, NULL);
ByeBye:
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
+51 -153
View File
@@ -1,160 +1,58 @@
/* $Id$
*
* Serial driver
* Written by Jason Filby (jasonfilby@yahoo.com)
* For ReactOS (www.reactos.com)
*
/* $Id:
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: drivers/dd/serial/serial.c
* PURPOSE: Serial driver loading/unloading
*
* PROGRAMMERS: Hervé Poussineau (poussine@freesurf.fr)
*/
#include <ddk/ntddk.h>
//#include <internal/mmhal.h>
//#include "../../../ntoskrnl/include/internal/i386/io.h"
//#include "../../../ntoskrnl/include/internal/io.h"
//#define NDEBUG
#include "serial.h"
#define outb_p(a,p) WRITE_PORT_UCHAR((PUCHAR)a,p)
#define outw_p(a,p) WRITE_PORT_USHORT((PUSHORT)a,p)
#define inb_p(p) READ_PORT_UCHAR((PUCHAR)p)
#define NDEBUG
#include <debug.h>
#define COM1 0x3F8
#define COM2 0x2F8
#define COM3 0x3E8
#define COM4 0x2E8
#define UART_BAUDRATE 96 // 1200 BPS
#define UART_LCRVAL 0x1b // 0x1b for 8e1
#define UARY_FCRVAL 0x7
int uart_detect(unsigned base)
VOID STDCALL
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
// Returns 0 if no UART detected
outb_p(base+4, 0x10);
if ((inb_p(base+6) & 0xf0)) return 0;
return 1;
};
int irq_setup(unsigned base)
{
// Returns -1 if not found -- otherwise returns interrupt level
char ier, mcr, imrm, imrs, maskm, masks, irqm, irqs;
__asm("cli"); // disable all CPU interrupts
ier = inb_p(base+1); // read IER
outb_p(base+1,0); // disable all UART ints
while (!(inb_p(base+5)&0x20)); // wait for the THR to be empty
mcr = inb_p(base+4); // read MCR
outb_p(base+4,0x0F); // connect UART to irq line
imrm = inb_p(0x21); // read contents of master ICU mask register
imrs = inb_p(0xA1); // read contents of slave ICU mask register
outb_p(0xA0,0x0A); // next read access to 0xA0 reads out IRR
outb_p(0x20,0x0A); // next read access to 0x20 reads out IRR
outb_p(base+1,2); // let's generate interrupts...
maskm = inb_p(0x20); // this clears all bits except for the one
masks = inb_p(0xA0); // that corresponds to the int
outb_p(base+1,0); // drop the int line
maskm &= ~inb_p(0x20); // this clears all bits except for the one
masks &= ~inb_p(0xA0); // that corresponds to the int
outb_p(base+1,2); // and raise it again just to be sure...
maskm &= inb_p(0x20); // this clears all bits except for the one
masks &= inb_p(0xA0); // that corresponds to the int
outb_p(0xA1,~masks); // now let us unmask this interrupt only
outb_p(0x21,~maskm);
outb_p(0xA0,0x0C); // enter polled mode
outb_p(0x20,0x0C); // that order is important with Pentium/PCI systems
irqs = inb_p(0xA0); // and accept the interrupt
irqm = inb_p(0x20);
inb_p(base+2); // reset transmitter interrupt in UART
outb_p(base+4,mcr); // restore old value of MCR
outb_p(base+1,ier); // restore old value of IER
if (masks) outb_p(0xA0,0x20); // send an EOI to slave
if (maskm) outb_p(0x20,0x20); // send an EOI to master
outb_p(0x21,imrm); // restore old mask register contents
outb_p(0xA1,imrs);
__asm("sti");
if (irqs&0x80) // slave interrupt occured
return (irqs&0x07)+8;
if (irqm&0x80) // master interrupt occured
return irqm&0x07;
return -1;
};
void uart_init(unsigned uart_base)
{
// Initialize the UART
outb_p(uart_base+3, 0x80);
outw_p(uart_base, UART_BAUDRATE);
outb_p(uart_base+3, UART_LCRVAL);
outb_p(uart_base+4, 0);
};
unsigned uart_getchar(unsigned uart_base)
{
unsigned x;
x=(inb_p(uart_base+5) & 0x9f) << 8;
if(x & 0x100) x|=((unsigned)inb_p(uart_base)) & 0xff;
return x;
};
void InitializeSerial(void)
{
unsigned comports[4] = { COM1, COM2, COM3, COM4 };
char *comname[4] = { "COM1", "COM2", "COM3", "COM4" };
int i, irq_level;
for (i=0; i<4; i++)
{
if(uart_detect(comports[i])==0)
{
DbgPrint("%s not detected\n", comname[i]);
} else {
uart_init(comports[i]);
irq_level=irq_setup(comports[i]);
if(irq_level==-1)
{
DbgPrint("Warning: IRQ not detected!\n");
} else {
DbgPrint("%s hooked to interrupt level %d\n", comname[i], irq_level);
};
};
};
};
// For testing purposes
void testserial(void)
{
int i=0;
char testc;
union {
unsigned val;
char character;
} x;
DbgPrint("Testing serial input...\n");
while(i==0) {
x.val=uart_getchar(COM1);
// if(!x.val) continue;
// if(x.val & 0x100)
testc=inb_p(COM1);
// DbgPrint("(%x-%c) %c\n", x.val, x.character, testc);
};
};
// nothing to do here yet
}
/*
* Standard DriverEntry method.
*/
NTSTATUS STDCALL
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegPath)
{
DbgPrint("Serial Driver 0.0.2\n");
// InitializeSerial();
// testserial();
return(STATUS_SUCCESS);
};
ULONG i;
static BOOLEAN FirstTime = TRUE;
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = SerialAddDevice;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
DriverObject->MajorFunction[i] = ForwardIrpAndForget;
DriverObject->MajorFunction[IRP_MJ_CREATE] = SerialCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SerialClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SerialCleanup;
DriverObject->MajorFunction[IRP_MJ_READ] = SerialRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = SerialWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SerialDeviceControl;
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = SerialQueryInformation;
DriverObject->MajorFunction[IRP_MJ_PNP] = SerialPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = SerialPower;
/* FIXME: It seems that DriverEntry function may be called more
* than once. Do only legacy detection the first time. */
if (FirstTime)
{
FirstTime = FALSE;
return DetectLegacyDevices(DriverObject);
}
else
{
DPRINT1("Serial: DriverEntry called for the second time!\n");
return STATUS_SUCCESS;
}
}
+353
View File
@@ -0,0 +1,353 @@
#if defined(__GNUC__)
#include <ddk/ntddk.h>
#include <ddk/ntddser.h>
#include <stdio.h>
#include <debug.h>
/* FIXME: these prototypes MUST NOT be here! */
NTSTATUS STDCALL
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#elif defined(_MSC_VER)
#include <ntddk.h>
#include <ntddser.h>
#include <stdio.h>
#define STDCALL
#define DPRINT1 DbgPrint("(%s:%d) ", __FILE__, __LINE__), DbgPrint
#define CHECKPOINT1 DbgPrint("(%s:%d)\n", __FILE__, __LINE__)
#define TAG(A, B, C, D) (ULONG)(((A)<<0) + ((B)<<8) + ((C)<<16) + ((D)<<24))
NTSTATUS STDCALL
IoAttachDeviceToDeviceStackSafe(
IN PDEVICE_OBJECT SourceDevice,
IN PDEVICE_OBJECT TargetDevice,
OUT PDEVICE_OBJECT *AttachedToDeviceObject);
#ifdef NDEBUG2
#define DPRINT
#define CHECKPOINT
#else
#define DPRINT DPRINT1
#define CHECKPOINT CHECKPOINT1
#undef NDEBUG
#endif
#else
#error Unknown compiler!
#endif
typedef enum
{
dsStopped,
dsStarted,
dsPaused,
dsRemoved,
dsSurpriseRemoved
} SERIAL_DEVICE_STATE;
typedef enum
{
UartUnknown,
Uart8250, /* initial version */
Uart16450, /* + 38.4 Kbps */
Uart16550, /* + 115 Kbps */
Uart16550A,/* + FIFO 16 bytes */
Uart16650, /* + FIFO 32 bytes, 230 Kbps, power management, auto-flow */
Uart16750 /* + FIFO 64 bytes, 460 Kbps */
} UART_TYPE;
typedef struct _CIRCULAR_BUFFER
{
PUCHAR Buffer;
ULONG Length;
ULONG ReadPosition;
ULONG WritePosition;
} CIRCULAR_BUFFER, *PCIRCULAR_BUFFER;
typedef struct _SERIAL_DEVICE_EXTENSION
{
PDEVICE_OBJECT Pdo;
PDEVICE_OBJECT LowerDevice;
SERIAL_DEVICE_STATE PnpState;
IO_REMOVE_LOCK RemoveLock;
ULONG SerialPortNumber;
ULONG ComPort;
ULONG BaudRate;
ULONG BaseAddress;
PKINTERRUPT Interrupt;
KDPC ReceivedByteDpc;
KDPC SendByteDpc;
SERIAL_LINE_CONTROL SerialLineControl;
UART_TYPE UartType;
ULONG WaitMask;
ULONG BreakInterruptErrorCount;
SERIALPERF_STATS SerialPerfStats;
SERIAL_TIMEOUTS SerialTimeOuts;
BOOLEAN IsOpened;
KEVENT InputBufferNotEmpty;
CIRCULAR_BUFFER InputBuffer;
KSPIN_LOCK InputBufferLock;
CIRCULAR_BUFFER OutputBuffer;
KSPIN_LOCK OutputBufferLock;
/* Current values */
UCHAR MCR; /* Base+4, Modem Control Register */
UCHAR MSR; /* Base+6, Modem Status Register */
} SERIAL_DEVICE_EXTENSION, *PSERIAL_DEVICE_EXTENSION;
typedef struct _WORKITEM_DATA
{
PIRP Irp;
PIO_WORKITEM IoWorkItem;
BOOLEAN UseIntervalTimeout;
BOOLEAN UseTotalTimeout;
LARGE_INTEGER IntervalTimeout;
LARGE_INTEGER TotalTimeoutTime;
BOOLEAN DontWait;
BOOLEAN ReadAtLeastOneByte;
} WORKITEM_DATA, *PWORKITEM_DATA;
#define SERIAL_TAG TAG('S', 'e', 'r', 'l')
#define INFINITE ((ULONG)-1)
/* Baud master clock */
#define BAUD_CLOCK 1843200
#define CLOCKS_PER_BIT 16
/* UART registers and bits */
#define SER_RBR(x) ((x)+0) /* Receive Register */
#define SER_THR(x) ((x)+0) /* Transmit Register */
#define SER_DLL(x) ((x)+0) /* Baud Rate Divisor LSB */
#define SER_IER(x) ((x)+1) /* Interrupt Enable Register */
#define SR_IER_DATA_RECEIVED 0x01
#define SR_IER_THR_EMPTY 0x02
#define SR_IER_LSR_CHANGE 0x04
#define SR_IER_MSR_CHANGE 0x08
#define SR_IER_SLEEP_MODE 0x10 /* Uart >= 16750 */
#define SR_IER_LOW_POWER 0x20 /* Uart >= 16750 */
#define SER_DLM(x) ((x)+1) /* Baud Rate Divisor MSB */
#define SER_IIR(x) ((x)+2) /* Interrupt Identification Register */
#define SR_IIR_SELF 0x00
#define SR_IIR_ID_MASK 0x07
#define SR_IIR_MSR_CHANGE SR_IIR_SELF
#define SR_IIR_THR_EMPTY (SR_IIR_SELF | 2)
#define SR_IIR_DATA_RECEIVED (SR_IIR_SELF | 4)
#define SR_IIR_ERROR (SR_IIR_SELF | 6)
#define SER_FCR(x) ((x)+2) /* FIFO Control Register (Uart >= 16550A) */
#define SR_FCR_ENABLE_FIFO 0x01
#define SR_FCR_CLEAR_RCVR (0x02 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_CLEAR_XMIT (0x04 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_1_BYTE (0x00 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_4_BYTES (0x40 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_8_BYTES (0x80 | SR_FCR_ENABLE_FIFO)
#define SR_FCR_14_BYTES (0xC0 | SR_FCR_ENABLE_FIFO)
#define SER_LCR(x) ((x)+3) /* Line Control Register */
#define SR_LCR_CS5 0x00
#define SR_LCR_CS6 0x01
#define SR_LCR_CS7 0x02
#define SR_LCR_CS8 0x03
#define SR_LCR_ST1 0x00
#define SR_LCR_ST2 0x04
#define SR_LCR_PNO 0x00
#define SR_LCR_POD 0x08
#define SR_LCR_PEV 0x18
#define SR_LCR_PMK 0x28
#define SR_LCR_PSP 0x38
#define SR_LCR_BRK 0x40
#define SR_LCR_DLAB 0x80
#define SER_MCR(x) ((x)+4) /* Modem Control Register */
#define SR_MCR_DTR 0x01
#define SR_MCR_RTS 0x02
#define SER_LSR(x) ((x)+5) /* Line Status Register */
#define SR_LSR_DATA_RECEIVED 0x01
#define SR_LSR_OVERRUN_ERROR 0x02
#define SR_LSR_PARITY_ERROR 0x04
#define SR_LSR_FRAMING_ERROR 0x08
#define SR_LSR_BREAK_INT 0x10
#define SR_LSR_THR_EMPTY 0x20
#define SR_LSR_TSR_EMPTY 0x40
#define SR_LSR_ERROR_IN_FIFO 0x80 /* Uart >= 16550A */
#define SER_MSR(x) ((x)+6) /* Modem Status Register */
#define SR_MSR_CTS_CHANGED 0x01
#define SR_MSR_DSR_CHANGED 0x02
#define SR_MSR_RI_CHANGED 0x04
#define SR_MSR_DCD_CHANGED 0x08
#define SR_MSR_CTS 0x10 /* Clear To Send */
#define SR_MSR_DSR 0x20 /* Data Set Ready */
#define SI_MSR_RI 0x40 /* Ring Indicator */
#define SR_MSR_DCD 0x80 /* Data Carrier Detect */
#define SER_SCR(x) ((x)+7) /* Scratch Pad Register */
/************************************ circularbuffer.c */
/* FIXME: transform these functions into #define? */
NTSTATUS
InitializeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG BufferSize);
NTSTATUS
FreeCircularBuffer(
IN PCIRCULAR_BUFFER pBuffer);
BOOLEAN
IsCircularBufferEmpty(
IN PCIRCULAR_BUFFER pBuffer);
NTSTATUS
PushCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
IN UCHAR Entry);
NTSTATUS
PopCircularBufferEntry(
IN PCIRCULAR_BUFFER pBuffer,
OUT PUCHAR Entry);
NTSTATUS
IncreaseCircularBufferSize(
IN PCIRCULAR_BUFFER pBuffer,
IN ULONG NewBufferSize);
/************************************ cleanup.c */
NTSTATUS STDCALL
SerialCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ close.c */
NTSTATUS STDCALL
SerialClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ create.c */
NTSTATUS STDCALL
SerialCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ devctrl.c */
NTSTATUS STDCALL
SerialDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
SerialSetBaudRate(
IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
IN ULONG NewBaudRate);
NTSTATUS STDCALL
SerialSetLineControl(
IN PSERIAL_DEVICE_EXTENSION DeviceExtension,
IN PSERIAL_LINE_CONTROL NewSettings);
/************************************ info.c */
NTSTATUS STDCALL
SerialQueryInformation(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ legacy.c */
UART_TYPE
SerialDetectUartType(
IN PUCHAR ComPortBase);
NTSTATUS
DetectLegacyDevices(
IN PDRIVER_OBJECT DriverObject);
/************************************ misc.c */
NTSTATUS
ForwardIrpAndWait(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
ForwardIrpAndForget(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
VOID STDCALL
SerialReceiveByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID pByte, // real type UCHAR
IN PVOID Unused);
VOID STDCALL
SerialSendByte(
IN PKDPC Dpc,
IN PVOID pDeviceExtension, // real type PSERIAL_DEVICE_EXTENSION
IN PVOID Unused1,
IN PVOID Unused2);
BOOLEAN STDCALL
SerialInterruptService(
IN PKINTERRUPT Interrupt,
IN OUT PVOID ServiceContext);
/************************************ pnp.c */
NTSTATUS STDCALL
SerialAddDeviceInternal(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo,
IN UART_TYPE UartType,
IN PULONG pComPortNumber OPTIONAL,
OUT PDEVICE_OBJECT* pFdo OPTIONAL);
NTSTATUS STDCALL
SerialAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo);
NTSTATUS STDCALL
SerialPnpStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PCM_RESOURCE_LIST ResourceList);
NTSTATUS STDCALL
SerialPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ power.c */
NTSTATUS STDCALL
SerialPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
/************************************ rw.c */
NTSTATUS STDCALL
SerialRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
NTSTATUS STDCALL
SerialWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp);
+12 -1
View File
@@ -1,6 +1,17 @@
<module name="serial" type="kernelmodedriver" installbase="system32/drivers" installname="serial.sys">
<define name="__USE_W32API" />
<library>ntoskrnl</library>
<library>hal</library>
<file>serial.c</file>
<file>circularbuffer.c</file>
<file>cleanup.c</file>
<file>close.c</file>
<file>create.c</file>
<file>devctrl.c</file>
<file>info.c</file>
<file>legacy.c</file>
<file>misc.c</file>
<file>pnp.c</file>
<file>power.c</file>
<file>rw.c</file>
<file>serial.rc</file>
</module>
+246 -71
View File
@@ -49,15 +49,26 @@ NpfsFindListeningServerInstance(PNPFS_PIPE Pipe)
{
PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter;
KIRQL oldIrql;
PIRP Irp;
CurrentEntry = Pipe->WaiterListHead.Flink;
while (CurrentEntry != &Pipe->WaiterListHead)
{
Waiter = CONTAINING_RECORD(CurrentEntry, NPFS_WAITER_ENTRY, Entry);
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
if (Waiter->Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
return Waiter->Fcb;
IoAcquireCancelSpinLock(&oldIrql);
if (!Irp->Cancel)
{
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(oldIrql);
return Waiter->Fcb;
}
IoReleaseCancelSpinLock(oldIrql);
}
CurrentEntry = CurrentEntry->Flink;
@@ -73,6 +84,7 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
{
PLIST_ENTRY CurrentEntry;
PNPFS_WAITER_ENTRY Waiter;
PIRP Irp;
CurrentEntry = Pipe->WaiterListHead.Flink;
while (CurrentEntry != &Pipe->WaiterListHead)
@@ -82,14 +94,12 @@ NpfsSignalAndRemoveListeningServerInstance(PNPFS_PIPE Pipe,
{
DPRINT("Server found! Fcb %p\n", Waiter->Fcb);
KeSetEvent(Waiter->Irp->UserEvent, 0, FALSE);
Waiter->Irp->UserIosb->Status = FILE_PIPE_CONNECTED_STATE;
Waiter->Irp->UserIosb->Information = 0;
IoCompleteRequest(Waiter->Irp, IO_NO_INCREMENT);
RemoveEntryList(&Waiter->Entry);
ExFreePool(Waiter);
return;
Irp = CONTAINING_RECORD(Waiter, IRP, Tail.Overlay.DriverContext);
Irp->IoStatus.Status = STATUS_PIPE_CONNECTED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
CurrentEntry = CurrentEntry->Flink;
}
@@ -142,40 +152,14 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
KeUnlockMutex(&DeviceExt->PipeListLock);
/*
* Step 2. Search for listening server FCB.
*/
/*
* Acquire the lock for FCB lists. From now on no modifications to the
* FCB lists are allowed, because it can cause various misconsistencies.
*/
KeLockMutex(&Pipe->FcbListLock);
if (!SpecialAccess)
{
ServerFcb = NpfsFindListeningServerInstance(Pipe);
if (ServerFcb == NULL)
{
/* Not found, bail out with error for FILE_OPEN requests. */
DPRINT("No listening server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
}
else if (IsListEmpty(&Pipe->ServerFcbListHead))
{
DPRINT("No server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* Step 3. Create the client FCB.
* Step 2. Create the client FCB.
*/
ClientFcb = ExAllocatePool(NonPagedPool, sizeof(NPFS_FCB));
if (ClientFcb == NULL)
@@ -192,11 +176,14 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ClientFcb->PipeEnd = FILE_PIPE_CLIENT_END;
ClientFcb->OtherSide = NULL;
ClientFcb->PipeState = SpecialAccess ? 0 : FILE_PIPE_DISCONNECTED_STATE;
InitializeListHead(&ClientFcb->ReadRequestListHead);
DPRINT("Fcb: %x\n", ClientFcb);
/* Initialize data list. */
if (Pipe->OutboundQuota)
{
ClientFcb->Data = ExAllocatePool(NonPagedPool, Pipe->OutboundQuota);
ClientFcb->Data = ExAllocatePool(PagedPool, Pipe->OutboundQuota);
if (ClientFcb->Data == NULL)
{
DPRINT("No memory!\n");
@@ -217,9 +204,78 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ClientFcb->ReadDataAvailable = 0;
ClientFcb->WriteQuotaAvailable = Pipe->OutboundQuota;
ClientFcb->MaxDataLength = Pipe->OutboundQuota;
KeInitializeSpinLock(&ClientFcb->DataListLock);
ExInitializeFastMutex(&ClientFcb->DataListLock);
KeInitializeEvent(&ClientFcb->ConnectEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->Event, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->ReadEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&ClientFcb->WriteEvent, SynchronizationEvent, FALSE);
/*
* Step 3. Search for listening server FCB.
*/
if (!SpecialAccess)
{
/*
* WARNING: Point of no return! Once we get the server FCB it's
* possible that we completed a wait request and so we have to
* complete even this request.
*/
ServerFcb = NpfsFindListeningServerInstance(Pipe);
if (ServerFcb == NULL)
{
PLIST_ENTRY CurrentEntry;
PNPFS_FCB Fcb;
/*
* If no waiting server FCB was found then try to pick
* one of the listing server FCB on the pipe.
*/
CurrentEntry = Pipe->ServerFcbListHead.Flink;
while (CurrentEntry != &Pipe->ServerFcbListHead)
{
Fcb = CONTAINING_RECORD(CurrentEntry, NPFS_FCB, FcbListEntry);
if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
ServerFcb = Fcb;
break;
}
CurrentEntry = CurrentEntry->Flink;
}
/*
* No one is listening to me?! I'm so lonely... :(
*/
if (ServerFcb == NULL)
{
/* Not found, bail out with error for FILE_OPEN requests. */
DPRINT("No listening server fcb found!\n");
if (ClientFcb->Data)
ExFreePool(ClientFcb->Data);
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_PIPE_BUSY;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_PIPE_BUSY;
}
}
else
{
/* Signal the server thread and remove it from the waiter list */
/* FIXME: Merge this with the NpfsFindListeningServerInstance routine. */
NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
}
}
else if (IsListEmpty(&Pipe->ServerFcbListHead))
{
DPRINT("No server fcb found!\n");
KeUnlockMutex(&Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
/*
* Step 4. Add the client FCB to a list and connect it if possible.
@@ -235,9 +291,6 @@ NpfsCreate(PDEVICE_OBJECT DeviceObject,
ServerFcb->OtherSide = ClientFcb;
ClientFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
ServerFcb->PipeState = FILE_PIPE_CONNECTED_STATE;
/* Signal the server thread and remove it from the waiter list */
NpfsSignalAndRemoveListeningServerInstance(Pipe, ServerFcb);
}
KeUnlockMutex(&Pipe->FcbListLock);
@@ -413,13 +466,16 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
if (Pipe->InboundQuota)
{
Fcb->Data = ExAllocatePool(NonPagedPool, Pipe->InboundQuota);
Fcb->Data = ExAllocatePool(PagedPool, Pipe->InboundQuota);
if (Fcb->Data == NULL)
{
ExFreePool(Fcb);
if (NewPipe)
{
KeLockMutex(&DeviceExt->PipeListLock);
RemoveEntryList(&Pipe->PipeListEntry);
KeUnlockMutex(&DeviceExt->PipeListLock);
RtlFreeUnicodeString(&Pipe->PipeName);
ExFreePool(Pipe);
}
@@ -439,26 +495,25 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Pipe->InboundQuota;
Fcb->MaxDataLength = Pipe->InboundQuota;
KeInitializeSpinLock(&Fcb->DataListLock);
InitializeListHead(&Fcb->ReadRequestListHead);
ExInitializeFastMutex(&Fcb->DataListLock);
Pipe->CurrentInstances++;
KeLockMutex(&Pipe->FcbListLock);
InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
KeUnlockMutex(&Pipe->FcbListLock);
Fcb->Pipe = Pipe;
Fcb->PipeEnd = FILE_PIPE_SERVER_END;
Fcb->PipeState = FILE_PIPE_LISTENING_STATE;
Fcb->OtherSide = NULL;
KeInitializeEvent(&Fcb->ConnectEvent,
SynchronizationEvent,
FALSE);
DPRINT("Fcb: %x\n", Fcb);
KeInitializeEvent(&Fcb->Event,
SynchronizationEvent,
FALSE);
KeInitializeEvent(&Fcb->ConnectEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&Fcb->ReadEvent, SynchronizationEvent, FALSE);
KeInitializeEvent(&Fcb->WriteEvent, SynchronizationEvent, FALSE);
KeLockMutex(&Pipe->FcbListLock);
InsertTailList(&Pipe->ServerFcbListHead, &Fcb->FcbListEntry);
KeUnlockMutex(&Pipe->FcbListLock);
FileObject->FsContext = Fcb;
@@ -471,6 +526,142 @@ NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject,
}
NTSTATUS STDCALL
NpfsCleanup(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
PNPFS_FCB Fcb, OtherSide;
PNPFS_PIPE Pipe;
BOOL Server;
DPRINT("NpfsCleanup(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
IoStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FileObject = IoStack->FileObject;
Fcb = FileObject->FsContext;
if (Fcb == NULL)
{
DPRINT("Success!\n");
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
DPRINT("Fcb %x\n", Fcb);
Pipe = Fcb->Pipe;
DPRINT("Cleaning pipe %wZ\n", &Pipe->PipeName);
KeLockMutex(&Pipe->FcbListLock);
Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
if (Server)
{
/* FIXME: Clean up existing connections here ?? */
DPRINT("Server\n");
}
else
{
DPRINT("Client\n");
}
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
OtherSide = Fcb->OtherSide;
/* Lock the server first */
if (Server)
{
ExAcquireFastMutex(&Fcb->DataListLock);
ExAcquireFastMutex(&OtherSide->DataListLock);
}
else
{
ExAcquireFastMutex(&OtherSide->DataListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
}
OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
OtherSide->OtherSide = NULL;
/*
* Signaling the write event. If is possible that an other
* thread waits for an empty buffer.
*/
KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
if (Server)
{
ExReleaseFastMutex(&Fcb->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
else
{
ExReleaseFastMutex(&OtherSide->DataListLock);
ExReleaseFastMutex(&Fcb->DataListLock);
}
}
else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
PLIST_ENTRY Entry;
PNPFS_WAITER_ENTRY WaitEntry = NULL;
BOOLEAN Complete = FALSE;
KIRQL oldIrql;
PIRP tmpIrp;
Entry = Fcb->Pipe->WaiterListHead.Flink;
while (Entry != &Fcb->Pipe->WaiterListHead)
{
WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
if (WaitEntry->Fcb == Fcb)
{
RemoveEntryList(Entry);
tmpIrp = CONTAINING_RECORD(WaitEntry, IRP, Tail.Overlay.DriverContext);
IoAcquireCancelSpinLock(&oldIrql);
if (!tmpIrp->Cancel)
{
IoSetCancelRoutine(tmpIrp, NULL);
Complete = TRUE;
}
IoReleaseCancelSpinLock(oldIrql);
if (Complete)
{
tmpIrp->IoStatus.Status = STATUS_PIPE_BROKEN;
tmpIrp->IoStatus.Information = 0;
IoCompleteRequest(tmpIrp, IO_NO_INCREMENT);
}
break;
}
Entry = Entry->Flink;
}
}
Fcb->PipeState = FILE_PIPE_CLOSING_STATE;
KeUnlockMutex(&Pipe->FcbListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
if (Fcb->Data)
{
ExFreePool(Fcb->Data);
Fcb->Data = NULL;
Fcb->ReadPtr = NULL;
Fcb->WritePtr = NULL;
}
ExReleaseFastMutex(&Fcb->DataListLock);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
DPRINT("Success!\n");
return STATUS_SUCCESS;
}
NTSTATUS STDCALL
NpfsClose(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
@@ -509,7 +700,6 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
if (Server)
{
/* FIXME: Clean up existing connections here ?? */
DPRINT("Server\n");
Pipe->CurrentInstances--;
}
@@ -518,27 +708,12 @@ NpfsClose(PDEVICE_OBJECT DeviceObject,
DPRINT("Client\n");
}
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
if (Fcb->OtherSide)
{
Fcb->OtherSide->PipeState = FILE_PIPE_CLOSING_STATE;
Fcb->OtherSide->OtherSide = NULL;
/*
* Signaling the write event. If is possible that an other
* thread waits for an empty buffer.
*/
KeSetEvent(&Fcb->OtherSide->Event, IO_NO_INCREMENT, FALSE);
}
Fcb->PipeState = 0;
}
ASSERT (Fcb->PipeState == FILE_PIPE_CLOSING_STATE);
FileObject->FsContext = NULL;
RemoveEntryList(&Fcb->FcbListEntry);
if (Fcb->Data)
ExFreePool(Fcb->Data);
ExFreePool(Fcb);
KeUnlockMutex(&Pipe->FcbListLock);
+110 -45
View File
@@ -18,22 +18,23 @@
/* FUNCTIONS *****************************************************************/
static VOID
static VOID STDCALL
NpfsListeningCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PNPFS_WAITER_ENTRY Waiter;
DPRINT1("NpfsListeningCancelRoutine() called\n");
/* FIXME: Not tested. */
Waiter = Irp->Tail.Overlay.DriverContext[0];
RemoveEntryList(&Waiter->Entry);
ExFreePool(Waiter);
Waiter = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
IoReleaseCancelSpinLock(Irp->CancelIrql);
KeLockMutex(&Waiter->Fcb->Pipe->FcbListLock);
RemoveEntryList(&Waiter->Entry);
KeUnlockMutex(&Waiter->Fcb->Pipe->FcbListLock);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@ -45,31 +46,33 @@ NpfsAddListeningServerInstance(PIRP Irp,
PNPFS_FCB Fcb)
{
PNPFS_WAITER_ENTRY Entry;
KIRQL OldIrql;
KIRQL oldIrql;
Entry = ExAllocatePool(NonPagedPool, sizeof(NPFS_WAITER_ENTRY));
if (Entry == NULL)
return STATUS_INSUFFICIENT_RESOURCES;
Entry = (PNPFS_WAITER_ENTRY)&Irp->Tail.Overlay.DriverContext;
Entry->Irp = Irp;
Entry->Fcb = Fcb;
KeLockMutex(&Fcb->Pipe->FcbListLock);
IoMarkIrpPending(Irp);
InsertTailList(&Fcb->Pipe->WaiterListHead, &Entry->Entry);
IoAcquireCancelSpinLock(&OldIrql);
IoAcquireCancelSpinLock(&oldIrql);
if (!Irp->Cancel)
{
Irp->Tail.Overlay.DriverContext[0] = Entry;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, NpfsListeningCancelRoutine);
IoReleaseCancelSpinLock(OldIrql);
IoReleaseCancelSpinLock(oldIrql);
KeUnlockMutex(&Fcb->Pipe->FcbListLock);
return STATUS_PENDING;
}
/* IRP has already been cancelled */
IoReleaseCancelSpinLock(OldIrql);
DPRINT1("FIXME: Remove waiter entry!\n");
IoReleaseCancelSpinLock(oldIrql);
RemoveEntryList(&Entry->Entry);
ExFreePool(Entry);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeUnlockMutex(&Fcb->Pipe->FcbListLock);
return STATUS_CANCELLED;
}
@@ -164,38 +167,100 @@ NpfsConnectPipe(PIRP Irp,
static NTSTATUS
NpfsDisconnectPipe(PNPFS_FCB Fcb)
{
DPRINT("NpfsDisconnectPipe()\n");
NTSTATUS Status;
PNPFS_FCB OtherSide;
PNPFS_PIPE Pipe;
BOOL Server;
if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
return STATUS_SUCCESS;
DPRINT("NpfsDisconnectPipe()\n");
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
/* FIXME: Shouldn't this be FILE_PIPE_CLOSING_STATE? */
Fcb->OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
Pipe = Fcb->Pipe;
KeLockMutex(&Pipe->FcbListLock);
/* FIXME: remove data queue(s) */
Fcb->OtherSide->OtherSide = NULL;
if (Fcb->PipeState == FILE_PIPE_DISCONNECTED_STATE)
{
DPRINT("Pipe is already disconnected\n");
Status = STATUS_SUCCESS;
}
else if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
Server = (Fcb->PipeEnd == FILE_PIPE_SERVER_END);
OtherSide = Fcb->OtherSide;
Fcb->OtherSide = NULL;
/* Lock the server first */
if (Server)
{
ExAcquireFastMutex(&Fcb->DataListLock);
ExAcquireFastMutex(&OtherSide->DataListLock);
}
else
{
ExAcquireFastMutex(&OtherSide->DataListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
}
OtherSide->PipeState = FILE_PIPE_DISCONNECTED_STATE;
OtherSide->OtherSide = NULL;
/*
* Signaling the write event. If is possible that an other
* thread waits for an empty buffer.
*/
KeSetEvent(&OtherSide->ReadEvent, IO_NO_INCREMENT, FALSE);
KeSetEvent(&OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
if (Server)
{
ExReleaseFastMutex(&Fcb->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
else
{
ExReleaseFastMutex(&OtherSide->DataListLock);
ExReleaseFastMutex(&OtherSide->DataListLock);
}
Status = STATUS_SUCCESS;
}
else if (Fcb->PipeState == FILE_PIPE_LISTENING_STATE)
{
PLIST_ENTRY Entry;
PNPFS_WAITER_ENTRY WaitEntry = NULL;
BOOLEAN Complete = FALSE;
PIRP Irp = NULL;
DPRINT("Pipe disconnected\n");
return STATUS_SUCCESS;
}
Entry = Fcb->Pipe->WaiterListHead.Flink;
while (Entry != &Fcb->Pipe->WaiterListHead)
{
WaitEntry = CONTAINING_RECORD(Entry, NPFS_WAITER_ENTRY, Entry);
if (WaitEntry->Fcb == Fcb)
{
RemoveEntryList(Entry);
Irp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.DriverContext);
Complete = (NULL == IoSetCancelRoutine(Irp, NULL));
break;
}
Entry = Entry->Flink;
}
if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
{
if (Irp)
{
if (Complete)
{
Irp->IoStatus.Status = STATUS_PIPE_BROKEN;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
Fcb->PipeState = FILE_PIPE_DISCONNECTED_STATE;
Fcb->OtherSide = NULL;
/* FIXME: remove data queue(s) */
DPRINT("Pipe disconnected\n");
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
Status = STATUS_SUCCESS;
}
else if (Fcb->PipeState == FILE_PIPE_CLOSING_STATE)
{
Status = STATUS_PIPE_CLOSING;
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
KeUnlockMutex(&Pipe->FcbListLock);
return Status;
}
+7 -3
View File
@@ -27,6 +27,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
NTSTATUS Status;
DPRINT("Named Pipe FSD 0.0.2\n");
ASSERT (sizeof(NPFS_CONTEXT) <= sizeof (((PIRP)NULL)->Tail.Overlay.DriverContext));
ASSERT (sizeof(NPFS_WAITER_ENTRY) <= sizeof(((PIRP)NULL)->Tail.Overlay.DriverContext));
DriverObject->MajorFunction[IRP_MJ_CREATE] = NpfsCreate;
DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] =
@@ -40,7 +43,7 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
NpfsSetInformation;
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] =
NpfsQueryVolumeInformation;
// DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpfsCleanup;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = NpfsCleanup;
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = NpfsFlushBuffers;
// DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] =
// NpfsDirectoryControl;
@@ -73,8 +76,9 @@ DriverEntry(PDRIVER_OBJECT DriverObject,
/* initialize the device extension */
DeviceExtension = DeviceObject->DeviceExtension;
InitializeListHead(&DeviceExtension->PipeListHead);
KeInitializeMutex(&DeviceExtension->PipeListLock,
0);
InitializeListHead(&DeviceExtension->ThreadListHead);
KeInitializeMutex(&DeviceExtension->PipeListLock, 0);
DeviceExtension->EmptyWaiterCount = 0;
/* set the size quotas */
DeviceExtension->MinQuota = PAGE_SIZE;
+26 -4
View File
@@ -6,7 +6,9 @@
typedef struct _NPFS_DEVICE_EXTENSION
{
LIST_ENTRY PipeListHead;
LIST_ENTRY ThreadListHead;
KMUTEX PipeListLock;
ULONG EmptyWaiterCount;
ULONG MinQuota;
ULONG DefaultQuota;
ULONG MaxQuota;
@@ -20,6 +22,7 @@ typedef struct _NPFS_PIPE
LIST_ENTRY ServerFcbListHead;
LIST_ENTRY ClientFcbListHead;
LIST_ENTRY WaiterListHead;
LIST_ENTRY EmptyBufferListHead;
ULONG PipeType;
ULONG ReadMode;
ULONG WriteMode;
@@ -39,25 +42,43 @@ typedef struct _NPFS_FCB
struct ETHREAD *Thread;
PNPFS_PIPE Pipe;
KEVENT ConnectEvent;
KEVENT Event;
KEVENT ReadEvent;
KEVENT WriteEvent;
ULONG PipeEnd;
ULONG PipeState;
ULONG ReadDataAvailable;
ULONG WriteQuotaAvailable;
LIST_ENTRY ReadRequestListHead;
PVOID Data;
PVOID ReadPtr;
PVOID WritePtr;
ULONG MaxDataLength;
KSPIN_LOCK DataListLock; /* Data queue lock */
FAST_MUTEX DataListLock; /* Data queue lock */
} NPFS_FCB, *PNPFS_FCB;
typedef struct _NPFS_CONTEXT
{
LIST_ENTRY ListEntry;
PKEVENT WaitEvent;
} NPFS_CONTEXT, *PNPFS_CONTEXT;
typedef struct _NPFS_THREAD_CONTEXT
{
ULONG Count;
KEVENT Event;
PNPFS_DEVICE_EXTENSION DeviceExt;
LIST_ENTRY ListEntry;
PVOID WaitObjectArray[MAXIMUM_WAIT_OBJECTS];
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
PIRP WaitIrpArray[MAXIMUM_WAIT_OBJECTS];
} NPFS_THREAD_CONTEXT, *PNPFS_THREAD_CONTEXT;
typedef struct _NPFS_WAITER_ENTRY
{
LIST_ENTRY Entry;
PIRP Irp;
PNPFS_PIPE Pipe;
PNPFS_FCB Fcb;
} NPFS_WAITER_ENTRY, *PNPFS_WAITER_ENTRY;
@@ -76,6 +97,7 @@ extern NPAGED_LOOKASIDE_LIST NpfsPipeDataLookasideList;
NTSTATUS STDCALL NpfsCreate(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsCreateNamedPipe(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsClose(PDEVICE_OBJECT DeviceObject, PIRP Irp);
NTSTATUS STDCALL NpfsRead(PDEVICE_OBJECT DeviceObject, PIRP Irp);
+497 -140
View File
@@ -46,114 +46,427 @@ VOID HexDump(PUCHAR Buffer, ULONG Length)
}
#endif
static VOID STDCALL
NpfsReadWriteCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PNPFS_CONTEXT Context;
PNPFS_DEVICE_EXTENSION DeviceExt;
PIO_STACK_LOCATION IoStack;
PNPFS_FCB Fcb;
BOOLEAN Complete = FALSE;
DPRINT("NpfsReadWriteCancelRoutine(DeviceObject %x, Irp %x)\n", DeviceObject, Irp);
IoReleaseCancelSpinLock(Irp->CancelIrql);
Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
Fcb = IoStack->FileObject->FsContext;
KeLockMutex(&DeviceExt->PipeListLock);
ExAcquireFastMutex(&Fcb->DataListLock);
switch(IoStack->MajorFunction)
{
case IRP_MJ_READ:
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* we are not the first in the list, remove an complete us */
RemoveEntryList(&Context->ListEntry);
Complete = TRUE;
}
else
{
KeSetEvent(&Fcb->ReadEvent, IO_NO_INCREMENT, FALSE);
}
break;
default:
KEBUGCHECK(0);
}
ExReleaseFastMutex(&Fcb->DataListLock);
KeUnlockMutex(&DeviceExt->PipeListLock);
if (Complete)
{
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
static VOID STDCALL
NpfsWaiterThread(PVOID InitContext)
{
PNPFS_THREAD_CONTEXT ThreadContext = (PNPFS_THREAD_CONTEXT) InitContext;
ULONG CurrentCount;
ULONG Count = 0;
PIRP Irp = NULL;
PIRP NextIrp;
NTSTATUS Status;
BOOLEAN Terminate = FALSE;
BOOLEAN Cancel = FALSE;
PIO_STACK_LOCATION IoStack = NULL;
PNPFS_CONTEXT Context;
PNPFS_CONTEXT NextContext;
PNPFS_FCB Fcb;
KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
while (1)
{
CurrentCount = ThreadContext->Count;
KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock);
if (Irp)
{
if (Cancel)
{
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
else
{
switch (IoStack->MajorFunction)
{
case IRP_MJ_READ:
NpfsRead(IoStack->DeviceObject, Irp);
break;
default:
KEBUGCHECK(0);
}
}
}
if (Terminate)
{
break;
}
Status = KeWaitForMultipleObjects(CurrentCount,
ThreadContext->WaitObjectArray,
WaitAny,
Executive,
KernelMode,
FALSE,
NULL,
ThreadContext->WaitBlockArray);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
KeLockMutex(&ThreadContext->DeviceExt->PipeListLock);
Count = Status - STATUS_SUCCESS;
ASSERT (Count < CurrentCount);
if (Count > 0)
{
Irp = ThreadContext->WaitIrpArray[Count];
ThreadContext->Count--;
ThreadContext->DeviceExt->EmptyWaiterCount++;
ThreadContext->WaitObjectArray[Count] = ThreadContext->WaitObjectArray[ThreadContext->Count];
ThreadContext->WaitIrpArray[Count] = ThreadContext->WaitIrpArray[ThreadContext->Count];
Cancel = (NULL == IoSetCancelRoutine(Irp, NULL));
Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
IoStack = IoGetCurrentIrpStackLocation(Irp);
if (Cancel)
{
Fcb = IoStack->FileObject->FsContext;
ExAcquireFastMutex(&Fcb->DataListLock);
RemoveEntryList(&Context->ListEntry);
switch (IoStack->MajorFunction)
{
case IRP_MJ_READ:
if (!IsListEmpty(&Fcb->ReadRequestListHead))
{
/* put the next request on the wait list */
NextContext = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
ThreadContext->WaitObjectArray[ThreadContext->Count] = NextContext->WaitEvent;
NextIrp = CONTAINING_RECORD(NextContext, IRP, Tail.Overlay.DriverContext);
ThreadContext->WaitIrpArray[ThreadContext->Count] = NextIrp;
ThreadContext->Count++;
ThreadContext->DeviceExt->EmptyWaiterCount--;
}
break;
default:
KEBUGCHECK(0);
}
ExReleaseFastMutex(&Fcb->DataListLock);
}
}
else
{
/* someone has add a new wait request */
Irp = NULL;
}
if (ThreadContext->Count == 1 && ThreadContext->DeviceExt->EmptyWaiterCount >= MAXIMUM_WAIT_OBJECTS)
{
/* it exist an other thread with empty wait slots, we can remove our thread from the list */
RemoveEntryList(&ThreadContext->ListEntry);
ThreadContext->DeviceExt->EmptyWaiterCount -= MAXIMUM_WAIT_OBJECTS - 1;
Terminate = TRUE;
}
}
KeUnlockMutex(&ThreadContext->DeviceExt->PipeListLock);
ExFreePool(ThreadContext);
}
static NTSTATUS
NpfsAddWaitingReadWriteRequest(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PLIST_ENTRY ListEntry;
PNPFS_THREAD_CONTEXT ThreadContext = NULL;
NTSTATUS Status;
HANDLE hThread;
KIRQL oldIrql;
PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
PNPFS_DEVICE_EXTENSION DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;;
DPRINT("NpfsAddWaitingReadWriteRequest(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
KeLockMutex(&DeviceExt->PipeListLock);
ListEntry = DeviceExt->ThreadListHead.Flink;
while (ListEntry != &DeviceExt->ThreadListHead)
{
ThreadContext = CONTAINING_RECORD(ListEntry, NPFS_THREAD_CONTEXT, ListEntry);
if (ThreadContext->Count < MAXIMUM_WAIT_OBJECTS)
{
break;
}
ListEntry = ListEntry->Flink;
}
if (ListEntry == &DeviceExt->ThreadListHead)
{
ThreadContext = ExAllocatePool(NonPagedPool, sizeof(NPFS_THREAD_CONTEXT));
if (ThreadContext == NULL)
{
KeUnlockMutex(&DeviceExt->PipeListLock);
return STATUS_NO_MEMORY;
}
ThreadContext->DeviceExt = DeviceExt;
KeInitializeEvent(&ThreadContext->Event, SynchronizationEvent, FALSE);
ThreadContext->Count = 1;
ThreadContext->WaitObjectArray[0] = &ThreadContext->Event;
DPRINT("Creating a new system thread for waiting read/write requests\n");
Status = PsCreateSystemThread(&hThread,
THREAD_ALL_ACCESS,
NULL,
NULL,
NULL,
NpfsWaiterThread,
(PVOID)ThreadContext);
if (!NT_SUCCESS(Status))
{
ExFreePool(ThreadContext);
KeUnlockMutex(&DeviceExt->PipeListLock);
return Status;
}
InsertHeadList(&DeviceExt->ThreadListHead, &ThreadContext->ListEntry);
DeviceExt->EmptyWaiterCount += MAXIMUM_WAIT_OBJECTS - 1;
}
IoMarkIrpPending(Irp);
IoAcquireCancelSpinLock(&oldIrql);
if (Irp->Cancel)
{
IoReleaseCancelSpinLock(oldIrql);
Status = STATUS_CANCELLED;
}
else
{
IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
IoReleaseCancelSpinLock(oldIrql);
ThreadContext->WaitObjectArray[ThreadContext->Count] = Context->WaitEvent;
ThreadContext->WaitIrpArray[ThreadContext->Count] = Irp;
ThreadContext->Count++;
DeviceExt->EmptyWaiterCount--;
KeSetEvent(&ThreadContext->Event, IO_NO_INCREMENT, FALSE);
Status = STATUS_SUCCESS;
}
KeUnlockMutex(&DeviceExt->PipeListLock);
return Status;
}
NTSTATUS STDCALL
NpfsRead(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
NpfsRead(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IoStack;
PFILE_OBJECT FileObject;
NTSTATUS Status;
PNPFS_DEVICE_EXTENSION DeviceExt;
KIRQL OldIrql;
ULONG Information;
NTSTATUS OriginalStatus = STATUS_SUCCESS;
PNPFS_FCB Fcb;
PNPFS_FCB WriterFcb;
PNPFS_PIPE Pipe;
PNPFS_CONTEXT Context;
KEVENT Event;
ULONG Length;
PVOID Buffer;
ULONG Information;
ULONG CopyLength;
ULONG TempLength;
BOOLEAN IsOriginalRequest = TRUE;
PVOID Buffer;
DPRINT("NpfsRead(DeviceObject %p Irp %p)\n", DeviceObject, Irp);
DeviceExt = (PNPFS_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
IoStack = IoGetCurrentIrpStackLocation(Irp);
FileObject = IoStack->FileObject;
Fcb = FileObject->FsContext;
Pipe = Fcb->Pipe;
WriterFcb = Fcb->OtherSide;
DPRINT("NpfsRead(DeviceObject %p, Irp %p)\n", DeviceObject, Irp);
if (Irp->MdlAddress == NULL)
{
DPRINT("Irp->MdlAddress == NULL\n");
Status = STATUS_UNSUCCESSFUL;
Information = 0;
goto done;
}
{
DPRINT("Irp->MdlAddress == NULL\n");
Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
goto done;
}
FileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
Fcb = FileObject->FsContext;
Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
if (Fcb->Data == NULL)
{
DPRINT("Pipe is NOT readable!\n");
Status = STATUS_UNSUCCESSFUL;
Information = 0;
goto done;
}
{
DPRINT1("Pipe is NOT readable!\n");
Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
goto done;
}
Status = STATUS_SUCCESS;
Length = IoStack->Parameters.Read.Length;
Information = 0;
ExAcquireFastMutex(&Fcb->DataListLock);
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
while (1)
{
/* FIXME: check if in blocking mode */
if (Fcb->ReadDataAvailable == 0)
if (IoIsOperationSynchronous(Irp))
{
InsertTailList(&Fcb->ReadRequestListHead, &Context->ListEntry);
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Context->WaitEvent = &Event;
ExReleaseFastMutex(&Fcb->DataListLock);
Status = KeWaitForSingleObject(&Event,
Executive,
KernelMode,
FALSE,
NULL);
if (!NT_SUCCESS(Status))
{
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
}
KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
if (Information > 0)
{
Status = STATUS_SUCCESS;
KEBUGCHECK(0);
}
ExAcquireFastMutex(&Fcb->DataListLock);
}
Irp->IoStatus.Information = 0;
}
else
{
KIRQL oldIrql;
if (IsListEmpty(&Fcb->ReadRequestListHead) ||
Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* this is a new request */
Irp->IoStatus.Information = 0;
Context->WaitEvent = &Fcb->ReadEvent;
InsertTailList(&Fcb->ReadRequestListHead, &Context->ListEntry);
if (Fcb->ReadRequestListHead.Flink != &Context->ListEntry)
{
/* there was already a request on the list */
IoAcquireCancelSpinLock(&oldIrql);
if (Irp->Cancel)
{
IoReleaseCancelSpinLock(oldIrql);
RemoveEntryList(&Context->ListEntry);
ExReleaseFastMutex(&Fcb->DataListLock);
Status = STATUS_CANCELLED;
goto done;
}
}
IoSetCancelRoutine(Irp, NpfsReadWriteCancelRoutine);
IoReleaseCancelSpinLock(oldIrql);
ExReleaseFastMutex(&Fcb->DataListLock);
IoMarkIrpPending(Irp);
Status = STATUS_PENDING;
goto done;
}
}
}
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
{
while (1)
{
Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
Information = Irp->IoStatus.Information;
Length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
ASSERT (Information <= Length);
Buffer += Information;
Length -= Information;
Status = STATUS_SUCCESS;
while (1)
{
if (Fcb->ReadDataAvailable == 0)
{
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
}
if (Information > 0 &&
(Fcb->Pipe->ReadMode != FILE_PIPE_BYTE_STREAM_MODE ||
Fcb->PipeState != FILE_PIPE_CONNECTED_STATE))
{
break;
}
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
{
DPRINT("PipeState: %x\n", Fcb->PipeState);
Status = STATUS_PIPE_BROKEN;
goto done;
}
break;
}
ExReleaseFastMutex(&Fcb->DataListLock);
if (IoIsOperationSynchronous(Irp))
{
/* Wait for ReadEvent to become signaled */
/* Wait for ReadEvent to become signaled */
DPRINT("Waiting for readable data (%S)\n", Pipe->PipeName.Buffer);
Status = KeWaitForSingleObject(&Fcb->Event,
UserRequest,
KernelMode,
FALSE,
NULL);
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
KeAcquireSpinLock(&Fcb->DataListLock, &OldIrql);
}
if (Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE)
{
DPRINT("Byte stream mode\n");
/* Byte stream mode */
while (Length > 0 && Fcb->ReadDataAvailable > 0)
{
DPRINT("Waiting for readable data (%wZ)\n", &Fcb->Pipe->PipeName);
Status = KeWaitForSingleObject(&Fcb->ReadEvent,
UserRequest,
KernelMode,
FALSE,
NULL);
DPRINT("Finished waiting (%wZ)! Status: %x\n", &Fcb->Pipe->PipeName, Status);
ExAcquireFastMutex(&Fcb->DataListLock);
}
else
{
PNPFS_CONTEXT Context = (PNPFS_CONTEXT)&Irp->Tail.Overlay.DriverContext;
Context->WaitEvent = &Fcb->ReadEvent;
Status = NpfsAddWaitingReadWriteRequest(DeviceObject, Irp);
if (NT_SUCCESS(Status))
{
Status = STATUS_PENDING;
}
ExAcquireFastMutex(&Fcb->DataListLock);
break;
}
}
if (Fcb->Pipe->ReadMode == FILE_PIPE_BYTE_STREAM_MODE)
{
DPRINT("Byte stream mode\n");
/* Byte stream mode */
while (Length > 0 && Fcb->ReadDataAvailable > 0)
{
CopyLength = RtlRosMin(Fcb->ReadDataAvailable, Length);
if (Fcb->ReadPtr + CopyLength <= Fcb->Data + Fcb->MaxDataLength)
{
memcpy(Buffer, Fcb->ReadPtr, CopyLength);
Fcb->ReadPtr += CopyLength;
if (Fcb->ReadPtr == Fcb->Data + Fcb->MaxDataLength)
{
Fcb->ReadPtr = Fcb->Data;
}
}
else
{
TempLength = Fcb->Data + Fcb->MaxDataLength - Fcb->ReadPtr;
memcpy(Buffer, Fcb->ReadPtr, TempLength);
memcpy(Buffer + TempLength, Fcb->Data, CopyLength - TempLength);
Fcb->ReadPtr = Fcb->Data + CopyLength - TempLength;
}
{
memcpy(Buffer, Fcb->ReadPtr, CopyLength);
Fcb->ReadPtr += CopyLength;
if (Fcb->ReadPtr == Fcb->Data + Fcb->MaxDataLength)
{
Fcb->ReadPtr = Fcb->Data;
}
}
else
{
TempLength = Fcb->Data + Fcb->MaxDataLength - Fcb->ReadPtr;
memcpy(Buffer, Fcb->ReadPtr, TempLength);
memcpy(Buffer + TempLength, Fcb->Data, CopyLength - TempLength);
Fcb->ReadPtr = Fcb->Data + CopyLength - TempLength;
}
Buffer += CopyLength;
Length -= CopyLength;
@@ -161,22 +474,25 @@ NpfsRead(PDEVICE_OBJECT DeviceObject,
Fcb->ReadDataAvailable -= CopyLength;
Fcb->WriteQuotaAvailable += CopyLength;
}
}
if (Length == 0)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event);
break;
}
}
else
{
DPRINT("Message mode\n");
if (Length == 0)
{
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
}
KeResetEvent(&Fcb->ReadEvent);
break;
}
}
else
{
DPRINT("Message mode\n");
/* Message mode */
if (Fcb->ReadDataAvailable)
{
/* Message mode */
if (Fcb->ReadDataAvailable)
{
/* Truncate the message if the receive buffer is too small */
CopyLength = RtlRosMin(Fcb->ReadDataAvailable, Length);
memcpy(Buffer, Fcb->Data, CopyLength);
@@ -189,45 +505,85 @@ NpfsRead(PDEVICE_OBJECT DeviceObject,
Information = CopyLength;
if (Fcb->ReadDataAvailable > Length)
{
memmove(Fcb->Data, Fcb->Data + Length,
Fcb->ReadDataAvailable - Length);
Fcb->ReadDataAvailable -= Length;
Status = STATUS_MORE_ENTRIES;
}
{
memmove(Fcb->Data, Fcb->Data + Length,
Fcb->ReadDataAvailable - Length);
Fcb->ReadDataAvailable -= Length;
Status = STATUS_MORE_ENTRIES;
}
else
{
Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
}
}
{
KeResetEvent(&Fcb->ReadEvent);
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&Fcb->OtherSide->WriteEvent, IO_NO_INCREMENT, FALSE);
}
Fcb->ReadDataAvailable = 0;
Fcb->WriteQuotaAvailable = Fcb->MaxDataLength;
}
}
if (Information > 0)
{
if (Fcb->PipeState == FILE_PIPE_CONNECTED_STATE)
{
KeSetEvent(&WriterFcb->Event, IO_NO_INCREMENT, FALSE);
}
KeResetEvent(&Fcb->Event);
break;
}
if (Information > 0)
{
break;
}
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
if (IoIsOperationSynchronous(Irp))
{
RemoveEntryList(&Context->ListEntry);
if (!IsListEmpty(&Fcb->ReadRequestListHead))
{
Context = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
KeSetEvent(Context->WaitEvent, IO_NO_INCREMENT, FALSE);
}
}
ExReleaseFastMutex(&Fcb->DataListLock);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
KeReleaseSpinLock(&Fcb->DataListLock, OldIrql);
DPRINT("NpfsRead done (Status %lx)\n", Status);
return Status;
}
else
{
if (IsOriginalRequest)
{
IsOriginalRequest = FALSE;
OriginalStatus = Status;
}
if (Status == STATUS_PENDING)
{
ExReleaseFastMutex(&Fcb->DataListLock);
DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
return OriginalStatus;
}
RemoveEntryList(&Context->ListEntry);
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (IsListEmpty(&Fcb->ReadRequestListHead))
{
ExReleaseFastMutex(&Fcb->DataListLock);
DPRINT("NpfsRead done (Status %lx)\n", OriginalStatus);
return OriginalStatus;
}
Context = CONTAINING_RECORD(Fcb->ReadRequestListHead.Flink, NPFS_CONTEXT, ListEntry);
Irp = CONTAINING_RECORD(Context, IRP, Tail.Overlay.DriverContext);
}
}
done:
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Information;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
if (Status != STATUS_PENDING)
{
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
DPRINT("NpfsRead done (Status %lx)\n", Status);
return Status;
}
NTSTATUS STDCALL
NpfsWrite(PDEVICE_OBJECT DeviceObject,
PIRP Irp)
@@ -241,7 +597,6 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
NTSTATUS Status = STATUS_SUCCESS;
ULONG Length;
ULONG Offset;
KIRQL OldIrql;
ULONG Information;
ULONG CopyLength;
ULONG TempLength;
@@ -293,7 +648,7 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
Status = STATUS_SUCCESS;
Buffer = MmGetSystemAddressForMdl (Irp->MdlAddress);
KeAcquireSpinLock(&ReaderFcb->DataListLock, &OldIrql);
ExAcquireFastMutex(&ReaderFcb->DataListLock);
#ifndef NDEBUG
DPRINT("Length %d Buffer %x Offset %x\n",Length,Buffer,Offset);
HexDump(Buffer, Length);
@@ -303,22 +658,24 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
{
if (ReaderFcb->WriteQuotaAvailable == 0)
{
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
KeReleaseSpinLock(&ReaderFcb->DataListLock, OldIrql);
KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
if (Fcb->PipeState != FILE_PIPE_CONNECTED_STATE)
{
Status = STATUS_PIPE_BROKEN;
ExReleaseFastMutex(&ReaderFcb->DataListLock);
goto done;
}
ExReleaseFastMutex(&ReaderFcb->DataListLock);
DPRINT("Waiting for buffer space (%S)\n", Pipe->PipeName.Buffer);
Status = KeWaitForSingleObject(&Fcb->Event,
UserRequest,
Status = KeWaitForSingleObject(&Fcb->WriteEvent,
UserRequest,
KernelMode,
FALSE,
NULL);
DPRINT("Finished waiting (%S)! Status: %x\n", Pipe->PipeName.Buffer, Status);
ExAcquireFastMutex(&ReaderFcb->DataListLock);
/*
* It's possible that the event was signaled because the
* other side of pipe was closed.
@@ -327,9 +684,9 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
{
DPRINT("PipeState: %x\n", Fcb->PipeState);
Status = STATUS_PIPE_BROKEN;
ExReleaseFastMutex(&ReaderFcb->DataListLock);
goto done;
}
KeAcquireSpinLock(&ReaderFcb->DataListLock, &OldIrql);
}
if (Pipe->WriteMode == FILE_PIPE_BYTE_STREAM_MODE)
@@ -365,8 +722,8 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
if (Length == 0)
{
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event);
KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->WriteEvent);
break;
}
}
@@ -383,16 +740,16 @@ NpfsWrite(PDEVICE_OBJECT DeviceObject,
ReaderFcb->WriteQuotaAvailable = 0;
}
if (Information > 0)
{
KeSetEvent(&ReaderFcb->Event, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->Event);
break;
}
if (Information > 0)
{
KeSetEvent(&ReaderFcb->ReadEvent, IO_NO_INCREMENT, FALSE);
KeResetEvent(&Fcb->WriteEvent);
break;
}
}
}
KeReleaseSpinLock(&ReaderFcb->DataListLock, OldIrql);
ExReleaseFastMutex(&ReaderFcb->DataListLock);
done:
Irp->IoStatus.Status = Status;
+1 -1
View File
@@ -36,7 +36,7 @@ NpfsQueryFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
DPRINT("NpfsQueryFsDeviceInformation() finished.\n");
return STATUS_SUCCESS;
return STATUS_SUCCESS;
}
+13
View File
@@ -49,6 +49,19 @@ VfatCleanupFile(PVFAT_IRP_CONTEXT IrpContext)
if (pFcb->Flags & FCB_DELETE_PENDING &&
pFcb->OpenHandleCount == 1)
{
PFILE_OBJECT tmpFileObject;
tmpFileObject = pFcb->FileObject;
if (tmpFileObject != NULL)
{
pFcb->FileObject = NULL;
#ifdef USE_ROS_CC_AND_FS
CcRosReleaseFileCache(tmpFileObject);
#else
CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
#endif
ObDereferenceObject(tmpFileObject);
}
#if 0
/* FIXME:
* CcPurgeCacheSection is unimplemented.
+1 -4
View File
@@ -43,11 +43,8 @@ VfatCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
pFcb->RefCount--;
FileObject->FsContext2 = NULL;
}
else if (FileObject->FileName.Buffer)
else
{
// This a FO, that was created outside from FSD.
// Some FO's are created with IoCreateStreamFileObject() insid from FSD.
// This FO's haven't a FileName.
if (FileObject->DeletePending)
{
if (pFcb->Flags & FCB_DELETE_PENDING)
+7 -27
View File
@@ -191,10 +191,10 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
while (pFCB)
{
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
Index = pFCB->Hash.Hash % pVCB->HashTableSize;
ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
pFCB->RefCount--;
if (pFCB->RefCount <= 0 && (!vfatFCBIsDirectory (pFCB) || pFCB->Flags & FCB_DELETE_PENDING))
if (pFCB->RefCount == 0)
{
tmpFcb = pFCB->parentFcb;
RemoveEntryList (&pFCB->FcbListEntry);
@@ -227,22 +227,6 @@ vfatReleaseFCB(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
}
entry->next = pFCB->Hash.next;
}
if (vfatFCBIsDirectory(pFCB))
{
/* Uninitialize file cache if initialized for this file object. */
if (pFCB->FileObject->SectionObjectPointer->SharedCacheMap)
{
#ifdef USE_ROS_CC_AND_FS
CcRosReleaseFileCache(pFCB->FileObject);
#else
CcUninitializeCacheMap(pFCB->FileObject, NULL, NULL);
#endif
}
vfatDestroyCCB(pFCB->FileObject->FsContext2);
pFCB->FileObject->FsContext2 = NULL;
pFCB->FileObject->FsContext = NULL;
ObDereferenceObject(pFCB->FileObject);
}
vfatDestroyFCB (pFCB);
}
else
@@ -259,8 +243,8 @@ vfatAddFCBToTable(PDEVICE_EXTENSION pVCB, PVFATFCB pFCB)
ULONG Index;
ULONG ShortIndex;
Index = pFCB->Hash.Hash % FCB_HASH_TABLE_SIZE;
ShortIndex = pFCB->ShortHash.Hash % FCB_HASH_TABLE_SIZE;
Index = pFCB->Hash.Hash % pVCB->HashTableSize;
ShortIndex = pFCB->ShortHash.Hash % pVCB->HashTableSize;
InsertTailList (&pVCB->FcbListHead, &pFCB->FcbListEntry);
@@ -292,7 +276,7 @@ vfatGrabFCBFromTable(PDEVICE_EXTENSION pVCB, PUNICODE_STRING PathNameU)
Hash = vfatNameHash(0, PathNameU);
entry = pVCB->FcbHashTable[Hash % FCB_HASH_TABLE_SIZE];
entry = pVCB->FcbHashTable[Hash % pVCB->HashTableSize];
if (entry)
{
vfatSplitPathName(PathNameU, &DirNameU, &FileNameU);
@@ -353,6 +337,7 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
fileObject->FsContext = fcb;
fileObject->FsContext2 = newCCB;
fcb->FileObject = fileObject;
fcb->RefCount++;
#ifdef USE_ROS_CC_AND_FS
fileCacheQuantum = (vcb->FatInfo.BytesPerCluster >= PAGE_SIZE) ?
@@ -375,12 +360,7 @@ vfatFCBInitializeCacheFromVolume (PVCB vcb, PVFATFCB fcb)
#endif
fcb->Flags |= FCB_CACHE_INITIALIZED;
#ifdef USE_ROS_CC_AND_FS
return status;
#else
return STATUS_SUCCESS;
#endif
}
PVFATFCB
+47 -51
View File
@@ -268,69 +268,65 @@ VfatSetDispositionInformation(PFILE_OBJECT FileObject,
PDEVICE_OBJECT DeviceObject,
PFILE_DISPOSITION_INFORMATION DispositionInfo)
{
NTSTATUS Status = STATUS_SUCCESS;
#ifdef DBG
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
#endif
DPRINT ("FsdSetDispositionInformation()\n");
DPRINT ("FsdSetDispositionInformation()\n");
ASSERT(DeviceExt != NULL);
ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
ASSERT(FCB != NULL);
ASSERT(DeviceExt != NULL);
ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
ASSERT(FCB != NULL);
if (*FCB->Attributes & FILE_ATTRIBUTE_READONLY)
{
if (!DispositionInfo->DeleteFile)
{
/* undelete the file */
FCB->Flags &= ~FCB_DELETE_PENDING;
FileObject->DeletePending = FALSE;
return STATUS_SUCCESS;
}
if (FCB->Flags & FCB_DELETE_PENDING)
{
/* stream already marked for deletion. just update the file object */
FileObject->DeletePending = TRUE;
return STATUS_SUCCESS;
}
if (*FCB->Attributes & FILE_ATTRIBUTE_READONLY)
{
return STATUS_CANNOT_DELETE;
}
}
if (vfatFCBIsRoot(FCB) ||
if (vfatFCBIsRoot(FCB) ||
(FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
(FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
{
{
// we cannot delete a '.', '..' or the root directory
return STATUS_ACCESS_DENIED;
}
}
if (DispositionInfo->DeleteFile)
{
if (MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{
if (FCB->OpenHandleCount > 1)
{
DPRINT1("%d %x\n", FCB->OpenHandleCount, CcGetFileObjectFromSectionPtrs(FileObject->SectionObjectPointer));
Status = STATUS_ACCESS_DENIED;
}
else
{
FCB->Flags |= FCB_DELETE_PENDING;
FileObject->DeletePending = TRUE;
}
}
else
{
DPRINT("MmFlushImageSection returned FALSE\n");
Status = STATUS_CANNOT_DELETE;
}
if (NT_SUCCESS(Status) && vfatFCBIsDirectory(FCB))
{
if (!VfatIsDirectoryEmpty(FCB))
{
Status = STATUS_DIRECTORY_NOT_EMPTY;
FCB->Flags &= ~FCB_DELETE_PENDING;
FileObject->DeletePending = FALSE;
}
else
{
Status = STATUS_SUCCESS;
}
}
}
else
{
FileObject->DeletePending = FALSE;
}
return Status;
if (!MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
{
/* can't delete a file if its mapped into a process */
DPRINT("MmFlushImageSection returned FALSE\n");
return STATUS_CANNOT_DELETE;
}
if (vfatFCBIsDirectory(FCB) && !VfatIsDirectoryEmpty(FCB))
{
/* can't delete a non-empty directory */
return STATUS_DIRECTORY_NOT_EMPTY;
}
/* all good */
FCB->Flags |= FCB_DELETE_PENDING;
FileObject->DeletePending = TRUE;
return STATUS_SUCCESS;
}
static NTSTATUS
+23 -4
View File
@@ -372,6 +372,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
PDEVICE_OBJECT DeviceToMount;
UNICODE_STRING NameU = RTL_CONSTANT_STRING(L"\\$$Fat$$");
UNICODE_STRING VolumeNameU = RTL_CONSTANT_STRING(L"\\$$Volume$$");
ULONG HashTableSize;
FATINFO FatInfo;
DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
@@ -385,7 +387,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, NULL);
Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, &FatInfo);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
@@ -398,9 +400,24 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
goto ByeBye;
}
/* Use prime numbers for the table size */
if (FatInfo.FatType == FAT12)
{
HashTableSize = 4099; // 4096 = 4 * 1024
}
else if (FatInfo.FatType == FAT16 ||
FatInfo.FatType == FATX16)
{
HashTableSize = 16411; // 16384 = 16 * 1024
}
else
{
HashTableSize = 65537; // 65536 = 64 * 1024;
}
HashTableSize = FCB_HASH_TABLE_SIZE;
DPRINT("VFAT: Recognized volume\n");
Status = IoCreateDevice(VfatGlobalData->DriverObject,
sizeof (DEVICE_EXTENSION),
ROUND_UP(sizeof (DEVICE_EXTENSION), sizeof(DWORD)) + sizeof(HASHENTRY*) * HashTableSize,
NULL,
FILE_DEVICE_FILE_SYSTEM,
0,
@@ -413,7 +430,9 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
DeviceExt = (PVOID) DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION));
RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(DWORD)) + sizeof(HASHENTRY*) * HashTableSize);
DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(DWORD)));
DeviceExt->HashTableSize = HashTableSize;
/* use same vpb as device disk */
DeviceObject->Vpb = DeviceToMount->Vpb;
@@ -557,7 +576,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext)
/* read volume label */
ReadVolumeLabel(DeviceExt, DeviceObject->Vpb);
Status = STATUS_SUCCESS;
ByeBye:
+2 -1
View File
@@ -241,7 +241,8 @@ typedef struct DEVICE_EXTENSION
KSPIN_LOCK FcbListLock;
LIST_ENTRY FcbListHead;
struct _HASHENTRY* FcbHashTable[FCB_HASH_TABLE_SIZE];
ULONG HashTableSize;
struct _HASHENTRY** FcbHashTable;
PDEVICE_OBJECT StorageDevice;
PFILE_OBJECT FATFileObject;
+37 -5
View File
@@ -38,6 +38,7 @@ static BYTE capsDown,numDown,scrollDown;
static DWORD ctrlKeyState;
static PKINTERRUPT KbdInterrupt;
static KDPC KbdDpc;
static PIO_WORKITEM KbdWorkItem = NULL;
static BOOLEAN AlreadyOpened = FALSE;
/*
@@ -407,6 +408,24 @@ static WORD ScanToVirtual(BYTE scanCode)
}
/*
* Debug request handler
*/
static VOID STDCALL
KbdWorkItemRoutine(IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
LONG Debug;
Debug = InterlockedExchange(&DoSystemDebug, -1);
if (Debug != -1)
{
KdSystemDebugControl(Debug);
}
}
/*
* Keyboard IRQ handler
*/
@@ -419,14 +438,21 @@ KbdDpcRoutine(PKDPC Dpc,
{
PIRP Irp = (PIRP)SystemArgument2;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
if (SystemArgument1 == NULL && DoSystemDebug != -1)
{
KdSystemDebugControl(DoSystemDebug);
DoSystemDebug = -1;
if (KbdWorkItem != NULL && DoSystemDebug == 10) /* 10 is Tab + K (enter kernel debugger) */
{
IoQueueWorkItem(KbdWorkItem, (PIO_WORKITEM_ROUTINE)KbdWorkItemRoutine, DelayedWorkQueue, NULL);
}
else
{
KdSystemDebugControl(DoSystemDebug);
DoSystemDebug = -1;
}
return;
}
CHECKPOINT;
DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
DeviceObject,Irp);
@@ -436,6 +462,7 @@ KbdDpcRoutine(PKDPC Dpc,
IoStartNextPacket(DeviceObject,FALSE);
}
static BOOLEAN STDCALL
KeyboardHandler(PKINTERRUPT Interrupt,
PVOID Context)
@@ -538,7 +565,7 @@ KeyboardHandler(PKINTERRUPT Interrupt,
else if (InSysRq == TRUE && ScanToVirtual(thisKey) >= VK_A &&
ScanToVirtual(thisKey) <= VK_Z && isDown)
{
DoSystemDebug = ScanToVirtual(thisKey) - VK_A;
InterlockedExchange(&DoSystemDebug, ScanToVirtual(thisKey) - VK_A);
KeInsertQueueDpc(&KbdDpc, NULL, NULL);
return(TRUE);
}
@@ -659,6 +686,11 @@ static int InitializeKeyboard(PDEVICE_OBJECT DeviceObject)
KbdClearInput();
KeyboardConnectInterrupt(DeviceObject);
KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
KbdWorkItem = IoAllocateWorkItem(DeviceObject);
if (KbdWorkItem == NULL)
{
DPRINT("Warning: Couldn't allocate work item!\n");
}
return 0;
}
@@ -209,3 +209,28 @@ PIP_INTERFACE FindOnLinkInterface(PIP_ADDRESS Address)
return NULL;
}
NTSTATUS GetInterfaceConnectionStatus
( PIP_INTERFACE Interface, PDWORD Result ) {
NTSTATUS Status = TcpipLanGetDwordOid
( Interface, OID_GEN_HARDWARE_STATUS, Result );
if( NT_SUCCESS(Status) ) switch( *Result ) {
case NdisHardwareStatusReady:
*Result = MIB_IF_OPER_STATUS_OPERATIONAL;
break;
case NdisHardwareStatusInitializing:
*Result = MIB_IF_OPER_STATUS_CONNECTING;
break;
case NdisHardwareStatusReset:
*Result = MIB_IF_OPER_STATUS_DISCONNECTED;
break;
case NdisHardwareStatusNotReady:
*Result = MIB_IF_OPER_STATUS_DISCONNECTED;
break;
case NdisHardwareStatusClosing:
default:
*Result = MIB_IF_OPER_STATUS_NON_OPERATIONAL;
break;
}
return Status;
}

Some files were not shown because too many files have changed in this diff Show More