ReactOS  0.4.13-dev-73-gcfe54aa
handle.c
Go to the documentation of this file.
1 /*
2  * COPYRIGHT: GPLv2+ - See COPYING in the top level directory
3  * PROJECT: ReactOS Virtual DOS Machine
4  * FILE: subsystems/mvdm/ntvdm/dos/dos32krnl/handle.c
5  * PURPOSE: DOS32 Handles (Job File Table)
6  * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "ntvdm.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include "emulator.h"
17 
18 #include "dos.h"
19 #include "dos/dem.h"
20 #include "dosfiles.h"
21 #include "handle.h"
22 #include "memory.h"
23 #include "process.h"
24 
25 /* PUBLIC FUNCTIONS ***********************************************************/
26 
27 VOID DosCopyHandleTable(LPBYTE DestinationTable)
28 {
29  UINT i;
30  PDOS_PSP PspBlock;
31  LPBYTE SourceTable;
33 
34  /* Clear the table first */
35  for (i = 0; i < DEFAULT_JFT_SIZE; i++) DestinationTable[i] = 0xFF;
36 
37  /* Check if this is the initial process */
38  if (Sda->CurrentPsp == SYSTEM_PSP)
39  {
40  BYTE DescriptorId;
41  HANDLE StandardHandles[3];
42 
43  /* Get the native standard handles */
44  StandardHandles[0] = GetStdHandle(STD_INPUT_HANDLE);
45  StandardHandles[1] = GetStdHandle(STD_OUTPUT_HANDLE);
46  StandardHandles[2] = GetStdHandle(STD_ERROR_HANDLE);
47 
48  for (i = 0; i < 3; i++)
49  {
50  /* Find the corresponding SFT entry */
51  if (IsConsoleHandle(StandardHandles[i]))
52  {
53  DescriptorId = DosFindDeviceDescriptor(SysVars->ActiveCon);
54  }
55  else
56  {
57  DescriptorId = DosFindWin32Descriptor(StandardHandles[i]);
58  }
59 
60  if (DescriptorId != 0xFF)
61  {
62  Descriptor = DosGetFileDescriptor(DescriptorId);
63  }
64  else
65  {
66  /* Create a new SFT entry for it */
67  DescriptorId = DosFindFreeDescriptor();
68  if (DescriptorId == 0xFF)
69  {
70  DPRINT1("Cannot create standard handle %d, the SFT is full!\n", i);
71  continue;
72  }
73 
74  Descriptor = DosGetFileDescriptor(DescriptorId);
77 
78  if (IsConsoleHandle(StandardHandles[i]))
79  {
81 
82  Descriptor->DeviceInfo = Node->DeviceAttributes | FILE_INFO_DEVICE;
83  Descriptor->DevicePointer = SysVars->ActiveCon;
84  RtlFillMemory(Descriptor->FileName, sizeof(Descriptor->FileName), ' ');
85  RtlCopyMemory(Descriptor->FileName, Node->Name.Buffer, Node->Name.Length);
86 
87  /* Call the open routine */
88  if (Node->OpenRoutine) Node->OpenRoutine(Node);
89  }
90  else
91  {
92  Descriptor->Win32Handle = StandardHandles[i];
93  }
94  }
95 
96  Descriptor->RefCount++;
97  DestinationTable[i] = DescriptorId;
98  }
99  }
100  else
101  {
102  /* Get the parent PSP block and handle table */
103  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
104  SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr);
105 
106  /* Copy the first 20 handles into the new table */
107  for (i = 0; i < DEFAULT_JFT_SIZE; i++)
108  {
109  Descriptor = DosGetFileDescriptor(SourceTable[i]);
110  DestinationTable[i] = SourceTable[i];
111 
112  /* Increase the reference count */
113  Descriptor->RefCount++;
114  }
115  }
116 }
117 
119 {
120  PDOS_PSP PspBlock;
122  WORD Segment;
123 
124  /* Get the PSP block */
125  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
126 
127  if (NewSize == PspBlock->HandleTableSize)
128  {
129  /* No change */
130  return TRUE;
131  }
132 
133  if (PspBlock->HandleTableSize > DEFAULT_JFT_SIZE)
134  {
135  /* Get the segment of the current table */
136  Segment = (LOWORD(PspBlock->HandleTablePtr) >> 4) + HIWORD(PspBlock->HandleTablePtr);
137 
138  if (NewSize <= DEFAULT_JFT_SIZE)
139  {
140  /* Get the current handle table */
142 
143  /* Copy it to the PSP */
145 
146  /* Free the memory */
148 
149  /* Update the handle table pointer and size */
150  PspBlock->HandleTableSize = NewSize;
151  PspBlock->HandleTablePtr = MAKELONG(0x18, Sda->CurrentPsp);
152  }
153  else
154  {
155  /* Resize the memory */
157  {
158  /* Unable to resize, try allocating it somewhere else */
160  if (Segment == 0) return FALSE;
161 
162  /* Get the new handle table */
164 
165  /* Copy the handles to the new table */
167  FAR_POINTER(PspBlock->HandleTablePtr),
168  PspBlock->HandleTableSize);
169 
170  /* Update the handle table pointer */
171  PspBlock->HandleTablePtr = MAKELONG(0, Segment);
172  }
173 
174  /* Update the handle table size */
175  PspBlock->HandleTableSize = NewSize;
176  }
177  }
178  else if (NewSize > DEFAULT_JFT_SIZE)
179  {
181  if (Segment == 0) return FALSE;
182 
183  /* Get the new handle table */
185 
186  /* Copy the handles from the PSP to the new table */
188  FAR_POINTER(PspBlock->HandleTablePtr),
189  PspBlock->HandleTableSize);
190 
191  /* Update the handle table pointer and size */
192  PspBlock->HandleTableSize = NewSize;
193  PspBlock->HandleTablePtr = MAKELONG(0, Segment);
194  }
195 
196  return TRUE;
197 }
198 
199 
200 WORD DosOpenHandle(BYTE DescriptorId)
201 {
202  WORD DosHandle;
203  PDOS_PSP PspBlock;
206 
207  DPRINT("DosOpenHandle: DescriptorId 0x%02X\n", DescriptorId);
208 
209  /* Make sure the descriptor ID is valid */
210  if (Descriptor == NULL) return INVALID_DOS_HANDLE;
211 
212  /* The system PSP has no handle table */
214 
215  /* Get a pointer to the handle table */
216  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
218 
219  /* Find a free entry in the JFT */
220  for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++)
221  {
222  if (HandleTable[DosHandle] == 0xFF) break;
223  }
224 
225  /* If there are no free entries, fail */
226  if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE;
227 
228  /* Reference the descriptor */
229  Descriptor->RefCount++;
230 
231  /* Set the JFT entry to that descriptor ID */
232  HandleTable[DosHandle] = DescriptorId;
233 
234  /* Return the new handle */
235  return DosHandle;
236 }
237 
239 {
240  PDOS_PSP PspBlock;
242 
243  DPRINT("DosQueryHandle: DosHandle 0x%04X\n", DosHandle);
244 
245  /* The system PSP has no handle table */
246  if (Sda->CurrentPsp == SYSTEM_PSP) return 0xFF;
247 
248  /* Get a pointer to the handle table */
249  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
251 
252  /* Return the descriptor ID */
253  return HandleTable[DosHandle];
254 }
255 
257 {
258  BYTE DescriptorId = DosQueryHandle(DosHandle);
259 
260  if (DescriptorId == 0xFF)
261  {
263  return INVALID_DOS_HANDLE;
264  }
265 
266  return DosOpenHandle(DescriptorId);
267 }
268 
270 {
271  BYTE DescriptorId;
272  PDOS_PSP PspBlock;
275 
276  DPRINT("DosForceDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n",
277  OldHandle,
278  NewHandle);
279 
280  /* The system PSP has no handle table */
281  if (Sda->CurrentPsp == SYSTEM_PSP) return FALSE;
282 
283  /* Get a pointer to the handle table */
284  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
286 
287  /* Make sure the old handle is open */
288  if (HandleTable[OldHandle] == 0xFF) return FALSE;
289 
290  /* Check if the new handle is open */
291  if (HandleTable[NewHandle] != 0xFF)
292  {
293  /* Close it */
294  DosCloseHandle(NewHandle);
295  }
296 
297  DescriptorId = HandleTable[OldHandle];
298  Descriptor = DosGetFileDescriptor(DescriptorId);
299  if (Descriptor == NULL) return FALSE;
300 
301  /* Increment the reference count of the descriptor */
302  Descriptor->RefCount++;
303 
304  /* Make the new handle point to that descriptor */
305  HandleTable[NewHandle] = DescriptorId;
306 
307  /* Return success */
308  return TRUE;
309 }
310 
312 {
313  PDOS_PSP PspBlock;
316 
317  DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle);
318 
319  /* The system PSP has no handle table */
320  if (Sda->CurrentPsp == SYSTEM_PSP) return FALSE;
321 
322  /* Get a pointer to the handle table */
323  PspBlock = SEGMENT_TO_PSP(Sda->CurrentPsp);
325 
326  /* Make sure the handle is open */
327  if (HandleTable[DosHandle] == 0xFF) return FALSE;
328 
329  /* Make sure the descriptor is valid */
331  if (Descriptor == NULL) return FALSE;
332 
333  /* Decrement the reference count of the descriptor */
334  Descriptor->RefCount--;
335 
336  /* Check if the reference count fell to zero */
337  if (!Descriptor->RefCount)
338  {
339  if (Descriptor->DeviceInfo & FILE_INFO_DEVICE)
340  {
342 
343  /* Call the close routine, if it exists */
344  if (Node->CloseRoutine) Node->CloseRoutine(Node);
345  }
346  else
347  {
348  /* Close the Win32 handle */
349  CloseHandle(Descriptor->Win32Handle);
350  }
351  }
352 
353  /* Clear the entry in the JFT */
354  HandleTable[DosHandle] = 0xFF;
355 
356  return TRUE;
357 }
WORD LastErrorCode
Definition: dos.h:151
BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable)
Definition: memory.c:289
WORD DosDuplicateHandle(WORD DosHandle)
Definition: handle.c:256
WORD CurrentPsp
Definition: dos.h:156
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define INVALID_DOS_HANDLE
Definition: dos.h:41
PDOS_FILE_DESCRIPTOR DosGetFileDescriptor(BYTE Id)
Definition: dosfiles.c:153
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
BOOLEAN DosFreeMemory(WORD BlockData)
Definition: memory.c:418
#define DEFAULT_JFT_SIZE
Definition: handle.h:13
BYTE DosFindWin32Descriptor(HANDLE Win32Handle)
Definition: dosfiles.c:93
HANDLE WINAPI GetStdHandle(IN DWORD nStdHandle)
Definition: console.c:152
static XMS_HANDLE HandleTable[XMS_MAX_HANDLES]
Definition: himem.c:83
BYTE DosQueryHandle(WORD DosHandle)
Definition: handle.c:238
BYTE HandleTable[20]
Definition: process.h:36
#define SEG_OFF_TO_PTR(seg, off)
Definition: emulator.h:28
#define SEGMENT_TO_PSP(seg)
Definition: process.h:16
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BYTE DosFindFreeDescriptor(VOID)
Definition: dosfiles.c:69
unsigned char * LPBYTE
Definition: typedefs.h:52
#define MAKELONG(a, b)
Definition: typedefs.h:248
unsigned char BOOLEAN
VOID DosCopyHandleTable(LPBYTE DestinationTable)
Definition: handle.c:27
smooth NULL
Definition: ftsmooth.c:416
WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable)
Definition: memory.c:136
void DPRINT(...)
Definition: polytest.cpp:61
DWORD ActiveCon
Definition: dos.h:83
#define FAR_POINTER(x)
Definition: emulator.h:31
#define STD_INPUT_HANDLE
Definition: winbase.h:264
WORD HandleTableSize
Definition: process.h:39
_Inout_ PVOID Segment
Definition: exfuncs.h:893
BOOLEAN DosResizeHandleTable(WORD NewSize)
Definition: handle.c:118
DWORD HandleTablePtr
Definition: process.h:40
#define FILE_INFO_DEVICE
Definition: dosfiles.h:16
#define STD_ERROR_HANDLE
Definition: winbase.h:266
unsigned short WORD
Definition: ntddk_ex.h:93
#define IsConsoleHandle(h)
Definition: console.h:14
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned char BYTE
Definition: mem.h:68
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
PDOS_SDA Sda
Definition: dos.c:48
#define STD_OUTPUT_HANDLE
Definition: winbase.h:265
PDOS_DEVICE_NODE DosGetDriverNode(DWORD Driver)
Definition: device.c:305
PDOS_SYSVARS SysVars
Definition: dos.c:47
#define SYSTEM_PSP
Definition: dos.h:39
unsigned int UINT
Definition: ndis.h:50
#define DPRINT1
Definition: precomp.h:8
#define HIWORD(l)
Definition: typedefs.h:246
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
BOOL WINAPI CloseHandle(IN HANDLE hObject)
Definition: handle.c:129
BYTE DosFindDeviceDescriptor(DWORD DevicePointer)
Definition: dosfiles.c:123
BOOLEAN DosForceDuplicateHandle(WORD OldHandle, WORD NewHandle)
Definition: handle.c:269
BOOLEAN DosCloseHandle(WORD DosHandle)
Definition: handle.c:311
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define LOWORD(l)
Definition: pedump.c:82
WORD DosOpenHandle(BYTE DescriptorId)
Definition: handle.c:200
Definition: dlist.c:348
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966