mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-28 04:13:35 +00:00
Merge 13831:14550 from trunk
svn path=/branches/xmlbuildsystem/; revision=14575
This commit is contained in:
@@ -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 =
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -8,6 +8,8 @@ TARGET_NAME = ftp
|
||||
|
||||
TARGET_INSTALLDIR = system32
|
||||
|
||||
TARGET_CFLAGS = -D__USE_W32API
|
||||
|
||||
TARGET_SDKLIBS = ws2_32.a iphlpapi.a
|
||||
# ntdll.a
|
||||
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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,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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <conio.h>
|
||||
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#include <pshpack1.h>
|
||||
|
||||
typedef struct _CM_PNP_BIOS_DEVICE_NODE
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
@@ -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) */
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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 |
@@ -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 */
|
||||
@@ -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'
|
||||
} */
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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) {
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
{
|
||||
|
||||
@@ -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...");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@ PATH_TO_TOP = ../..
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
DRIVERS = acpi isapnp pci
|
||||
DRIVERS = acpi isapnp pci serenum
|
||||
|
||||
all: $(DRIVERS)
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -36,7 +36,7 @@ NpfsQueryFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
|
||||
|
||||
DPRINT("NpfsQueryFsDeviceInformation() finished.\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user