4 * Copyright 1996 Alexandre Julliard
21 #define HTABLE_SIZE 0x30 /* Handle table initial size */
22 #define HTABLE_INC 0x10 /* Handle table increment */
24 static BOOL32
PROCESS_Signaled( K32OBJ
*obj
, DWORD thread_id
);
25 static BOOL32
PROCESS_Satisfied( K32OBJ
*obj
, DWORD thread_id
);
26 static void PROCESS_AddWait( K32OBJ
*obj
, DWORD thread_id
);
27 static void PROCESS_RemoveWait( K32OBJ
*obj
, DWORD thread_id
);
28 static void PROCESS_Destroy( K32OBJ
*obj
);
30 const K32OBJ_OPS PROCESS_Ops
=
32 PROCESS_Signaled
, /* signaled */
33 PROCESS_Satisfied
, /* satisfied */
34 PROCESS_AddWait
, /* add_wait */
35 PROCESS_RemoveWait
, /* remove_wait */
36 PROCESS_Destroy
/* destroy */
40 /***********************************************************************
41 * PROCESS_AllocHandleTable
43 static HANDLE_TABLE
*PROCESS_AllocHandleTable( PDB32
*process
)
45 HANDLE_TABLE
*table
= HeapAlloc( process
->system_heap
, HEAP_ZERO_MEMORY
,
46 sizeof(HANDLE_TABLE
) +
47 (HTABLE_SIZE
-1) * sizeof(HANDLE_ENTRY
) );
48 if (!table
) return NULL
;
49 table
->count
= HTABLE_SIZE
;
54 /***********************************************************************
55 * PROCESS_GrowHandleTable
57 static BOOL32
PROCESS_GrowHandleTable( PDB32
*process
)
61 table
= process
->handle_table
;
62 table
= HeapReAlloc( process
->system_heap
,
63 HEAP_ZERO_MEMORY
| HEAP_NO_SERIALIZE
, table
,
64 sizeof(HANDLE_TABLE
) +
65 (table
->count
+HTABLE_INC
-1) * sizeof(HANDLE_ENTRY
) );
68 table
->count
+= HTABLE_INC
;
69 process
->handle_table
= table
;
72 return (table
!= NULL
);
76 /***********************************************************************
79 PDB32
*PROCESS_Current(void)
81 return THREAD_Current()->process
;
85 /***********************************************************************
88 * Convert a process id to a PDB, making sure it is valid.
90 PDB32
*PROCESS_IdToPDB( DWORD id
)
94 if (!id
) return PROCESS_Current();
95 pdb
= PROCESS_ID_TO_PDB( id
);
96 if (!K32OBJ_IsValid( &pdb
->header
, K32OBJ_PROCESS
))
98 SetLastError( ERROR_INVALID_PARAMETER
);
105 /***********************************************************************
106 * PROCESS_AllocHandle
108 * Allocate a handle for a kernel object and increment its refcount.
110 HANDLE32
PROCESS_AllocHandle( K32OBJ
*ptr
, DWORD flags
)
114 PDB32
*pdb
= PROCESS_Current();
118 K32OBJ_IncCount( ptr
);
119 entry
= pdb
->handle_table
->entries
;
120 for (h
= 0; h
< pdb
->handle_table
->count
; h
++, entry
++)
121 if (!entry
->ptr
) break;
122 if ((h
< pdb
->handle_table
->count
) || PROCESS_GrowHandleTable( pdb
))
124 entry
= &pdb
->handle_table
->entries
[h
];
125 entry
->flags
= flags
;
128 return h
+ 1; /* Avoid handle 0 */
130 K32OBJ_DecCount( ptr
);
132 SetLastError( ERROR_OUTOFMEMORY
);
133 return INVALID_HANDLE_VALUE32
;
137 /***********************************************************************
140 * Retrieve a pointer to a kernel object and increments its reference count.
141 * The refcount must be decremented when the pointer is no longer used.
143 K32OBJ
*PROCESS_GetObjPtr( HANDLE32 handle
, K32OBJ_TYPE type
)
146 PDB32
*pdb
= PROCESS_Current();
150 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
151 ptr
= pdb
->handle_table
->entries
[handle
- 1].ptr
;
152 else if (handle
== 0x7fffffff) ptr
= &pdb
->header
;
154 if (ptr
&& ((type
== K32OBJ_UNKNOWN
) || (ptr
->type
== type
)))
155 K32OBJ_IncCount( ptr
);
159 if (!ptr
) SetLastError( ERROR_INVALID_HANDLE
);
164 /***********************************************************************
167 * Change the object pointer of a handle, and increment the refcount.
170 BOOL32
PROCESS_SetObjPtr( HANDLE32 handle
, K32OBJ
*ptr
, DWORD flags
)
173 K32OBJ
*old_ptr
= NULL
;
174 PDB32
*pdb
= PROCESS_Current();
177 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
179 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
-1];
180 old_ptr
= entry
->ptr
;
181 K32OBJ_IncCount( ptr
);
182 entry
->flags
= flags
;
187 SetLastError( ERROR_INVALID_HANDLE
);
190 if (old_ptr
) K32OBJ_DecCount( old_ptr
);
196 /*********************************************************************
197 * CloseHandle (KERNEL32.23)
199 BOOL32 WINAPI
CloseHandle( HANDLE32 handle
)
203 PDB32
*pdb
= PROCESS_Current();
206 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
208 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
-1];
209 if ((ptr
= entry
->ptr
))
216 if (ptr
) K32OBJ_DecCount( ptr
);
218 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
223 static int pstr_cmp( const void *ps1
, const void *ps2
)
225 return lstrcmpi32A( *(LPSTR
*)ps1
, *(LPSTR
*)ps2
);
228 /***********************************************************************
231 static BOOL32
PROCESS_FillEnvDB( PDB32
*pdb
, TDB
*pTask
, LPCSTR cmd_line
)
235 LPSTR
*pp
, *array
= NULL
;
237 /* Copy the Win16 environment, sorting it in the process */
239 env
= p
= GlobalLock16( pTask
->pdb
.environment
);
240 for (p
= env
; *p
; p
+= strlen(p
) + 1) count
++;
241 pdb
->env_db
->env_size
= (p
- env
) + 1;
242 pdb
->env_db
->environ
= HeapAlloc( pdb
->heap
, 0, pdb
->env_db
->env_size
);
243 if (!pdb
->env_db
->environ
) goto error
;
244 if (!(array
= HeapAlloc( pdb
->heap
, 0, count
* sizeof(array
[0]) )))
246 for (p
= env
, pp
= array
; *p
; p
+= strlen(p
) + 1) *pp
++ = p
;
247 qsort( array
, count
, sizeof(LPSTR
), pstr_cmp
);
248 p
= pdb
->env_db
->environ
;
249 for (pp
= array
; count
; count
--, pp
++)
255 HeapFree( pdb
->heap
, 0, array
);
258 /* Copy the command line */
259 /* Fixme: Here we rely on the hack that loader/module.c put's the unprocessed
260 commandline after the processed one in Pascal notation.
261 We may access Null data if we get called another way.
262 If we have a real CreateProcess sometimes, the problem to get an unrestricted
263 commandline will go away and we won't need that hack any longer
265 if (!(pdb
->env_db
->cmd_line
=
266 HEAP_strdupA( pdb
->heap
, 0, cmd_line
+ (unsigned char)cmd_line
[0] + 2)))
272 if (pdb
->env_db
->cmd_line
) HeapFree( pdb
->heap
, 0, pdb
->env_db
->cmd_line
);
273 if (array
) HeapFree( pdb
->heap
, 0, array
);
274 if (pdb
->env_db
->environ
) HeapFree( pdb
->heap
, 0, pdb
->env_db
->environ
);
279 /***********************************************************************
282 * Free a PDB and all associated storage.
284 static void PROCESS_FreePDB( PDB32
*pdb
)
286 pdb
->header
.type
= K32OBJ_UNKNOWN
;
287 if (pdb
->heap
) HeapDestroy( pdb
->heap
);
288 if (pdb
->handle_table
) HeapFree( pdb
->system_heap
, 0, pdb
->handle_table
);
289 if (pdb
->load_done_evt
) K32OBJ_DecCount( pdb
->load_done_evt
);
290 if (pdb
->event
) K32OBJ_DecCount( pdb
->event
);
291 DeleteCriticalSection( &pdb
->crit_section
);
292 HeapFree( SystemHeap
, 0, pdb
);
296 /***********************************************************************
299 * Allocate and fill a PDB structure.
301 static PDB32
*PROCESS_CreatePDB( PDB32
*parent
)
303 PDB32
*pdb
= HeapAlloc( SystemHeap
, HEAP_ZERO_MEMORY
, sizeof(PDB32
) );
305 if (!pdb
) return NULL
;
306 pdb
->header
.type
= K32OBJ_PROCESS
;
307 pdb
->header
.refcount
= 1;
308 pdb
->exit_code
= 0x103; /* STILL_ACTIVE */
310 pdb
->running_threads
= 1;
311 pdb
->ring0_threads
= 1;
312 pdb
->system_heap
= SystemHeap
;
313 pdb
->parent
= parent
;
315 pdb
->priority
= 8; /* Normal */
317 InitializeCriticalSection( &pdb
->crit_section
);
319 /* Allocate the events */
321 if (!(pdb
->event
= EVENT_Create( TRUE
, FALSE
))) goto error
;
322 if (!(pdb
->load_done_evt
= EVENT_Create( TRUE
, FALSE
))) goto error
;
324 /* Allocate the handle table */
326 if (!(pdb
->handle_table
= PROCESS_AllocHandleTable( pdb
))) goto error
;
330 PROCESS_FreePDB( pdb
);
335 /***********************************************************************
338 BOOL32
PROCESS_Init(void)
343 if (!(pdb
= PROCESS_CreatePDB( NULL
))) return FALSE
;
344 if (!(thdb
= THREAD_Create( pdb
, 0, NULL
, NULL
))) return FALSE
;
345 SET_CUR_THREAD( thdb
);
350 /***********************************************************************
353 * Create a new process database and associated info.
355 PDB32
*PROCESS_Create( TDB
*pTask
, LPCSTR cmd_line
)
359 PDB32
*pdb
= PROCESS_CreatePDB( PROCESS_Current() );
361 if (!pdb
) return NULL
;
362 if (!(pModule
= MODULE_GetPtr( pTask
->hModule
))) return 0;
364 /* Create the heap */
366 if (pModule
->module32
)
368 size
= PE_HEADER(pModule
->module32
)->OptionalHeader
.SizeOfHeapReserve
;
369 commit
= PE_HEADER(pModule
->module32
)->OptionalHeader
.SizeOfHeapCommit
;
376 if (!(pdb
->heap
= HeapCreate( HEAP_GROWABLE
, size
, commit
))) goto error
;
377 pdb
->heap_list
= pdb
->heap
;
379 if (!(pdb
->env_db
= HeapAlloc(pdb
->heap
, HEAP_ZERO_MEMORY
, sizeof(ENVDB
))))
381 if (!PROCESS_FillEnvDB( pdb
, pTask
, cmd_line
)) goto error
;
385 PROCESS_FreePDB( pdb
);
390 /***********************************************************************
393 static BOOL32
PROCESS_Signaled( K32OBJ
*obj
, DWORD thread_id
)
395 PDB32
*pdb
= (PDB32
*)obj
;
396 assert( obj
->type
== K32OBJ_PROCESS
);
397 return K32OBJ_OPS( pdb
->event
)->signaled( pdb
->event
, thread_id
);
401 /***********************************************************************
404 * Wait on this object has been satisfied.
406 static BOOL32
PROCESS_Satisfied( K32OBJ
*obj
, DWORD thread_id
)
408 PDB32
*pdb
= (PDB32
*)obj
;
409 assert( obj
->type
== K32OBJ_PROCESS
);
410 return K32OBJ_OPS( pdb
->event
)->satisfied( pdb
->event
, thread_id
);
414 /***********************************************************************
417 * Add thread to object wait queue.
419 static void PROCESS_AddWait( K32OBJ
*obj
, DWORD thread_id
)
421 PDB32
*pdb
= (PDB32
*)obj
;
422 assert( obj
->type
== K32OBJ_PROCESS
);
423 return K32OBJ_OPS( pdb
->event
)->add_wait( pdb
->event
, thread_id
);
427 /***********************************************************************
430 * Remove thread from object wait queue.
432 static void PROCESS_RemoveWait( K32OBJ
*obj
, DWORD thread_id
)
434 PDB32
*pdb
= (PDB32
*)obj
;
435 assert( obj
->type
== K32OBJ_PROCESS
);
436 return K32OBJ_OPS( pdb
->event
)->remove_wait( pdb
->event
, thread_id
);
440 /***********************************************************************
443 static void PROCESS_Destroy( K32OBJ
*ptr
)
445 PDB32
*pdb
= (PDB32
*)ptr
;
447 assert( ptr
->type
== K32OBJ_PROCESS
);
449 /* Close all handles */
450 for (handle
= 0; handle
< pdb
->handle_table
->count
; handle
++)
451 if (pdb
->handle_table
->entries
[handle
].ptr
) CloseHandle( handle
);
453 /* Free everything */
455 ptr
->type
= K32OBJ_UNKNOWN
;
456 PROCESS_FreePDB( pdb
);
460 /***********************************************************************
461 * ExitProcess (KERNEL32.100)
463 void WINAPI
ExitProcess( DWORD status
)
465 PDB32
*pdb
= PROCESS_Current();
468 /* FIXME: should kill all running threads of this process */
469 pdb
->exit_code
= status
;
470 EVENT_Set( pdb
->event
);
473 __RESTORE_ES
; /* Necessary for Pietrek's showseh example program */
474 TASK_KillCurrentTask( status
);
478 /***********************************************************************
479 * GetCurrentProcess (KERNEL32.198)
481 HANDLE32 WINAPI
GetCurrentProcess(void)
487 /*********************************************************************
488 * OpenProcess (KERNEL32.543)
490 HANDLE32 WINAPI
OpenProcess( DWORD access
, BOOL32 inherit
, DWORD id
)
492 PDB32
*pdb
= PROCESS_ID_TO_PDB(id
);
493 if (!K32OBJ_IsValid( &pdb
->header
, K32OBJ_PROCESS
))
495 SetLastError( ERROR_INVALID_HANDLE
);
498 return PROCESS_AllocHandle( &pdb
->header
, 0 );
502 /***********************************************************************
503 * GetCurrentProcessId (KERNEL32.199)
505 DWORD WINAPI
GetCurrentProcessId(void)
507 PDB32
*pdb
= PROCESS_Current();
508 return PDB_TO_PROCESS_ID( pdb
);
512 /***********************************************************************
513 * GetEnvironmentStrings32A (KERNEL32.210) (KERNEL32.211)
515 LPSTR WINAPI
GetEnvironmentStrings32A(void)
517 PDB32
*pdb
= PROCESS_Current();
518 return pdb
->env_db
->environ
;
522 /***********************************************************************
523 * GetEnvironmentStrings32W (KERNEL32.212)
525 LPWSTR WINAPI
GetEnvironmentStrings32W(void)
530 PDB32
*pdb
= PROCESS_Current();
532 size
= HeapSize( GetProcessHeap(), 0, pdb
->env_db
->environ
);
533 if (!(ret
= HeapAlloc( GetProcessHeap(), 0, size
* sizeof(WCHAR
) )))
535 pA
= pdb
->env_db
->environ
;
539 lstrcpyAtoW( pW
, pA
);
549 /***********************************************************************
550 * FreeEnvironmentStrings32A (KERNEL32.141)
552 BOOL32 WINAPI
FreeEnvironmentStrings32A( LPSTR ptr
)
554 PDB32
*pdb
= PROCESS_Current();
555 if (ptr
!= pdb
->env_db
->environ
)
557 SetLastError( ERROR_INVALID_PARAMETER
);
564 /***********************************************************************
565 * FreeEnvironmentStrings32W (KERNEL32.142)
567 BOOL32 WINAPI
FreeEnvironmentStrings32W( LPWSTR ptr
)
569 return HeapFree( GetProcessHeap(), 0, ptr
);
573 /***********************************************************************
574 * GetEnvironmentVariable32A (KERNEL32.213)
576 DWORD WINAPI
GetEnvironmentVariable32A( LPCSTR name
, LPSTR value
, DWORD size
)
581 p
= PROCESS_Current()->env_db
->environ
;
584 SetLastError( ERROR_INVALID_PARAMETER
);
590 res
= lstrncmpi32A( name
, p
, len
);
591 if (res
< 0) goto not_found
;
592 if (!res
&& (p
[len
] == '=')) break;
595 if (!*p
) goto not_found
;
596 if (value
) lstrcpyn32A( value
, p
+ len
+ 1, size
);
598 /* According to the Win32 docs, if there is not enough room, return
599 * the size required to hold the string plus the terminating null
601 if (size
<= len
) len
++;
605 return 0; /* FIXME: SetLastError */
609 /***********************************************************************
610 * GetEnvironmentVariable32W (KERNEL32.214)
612 DWORD WINAPI
GetEnvironmentVariable32W( LPCWSTR nameW
, LPWSTR valW
, DWORD size
)
614 LPSTR name
= HEAP_strdupWtoA( GetProcessHeap(), 0, nameW
);
615 LPSTR val
= HeapAlloc( GetProcessHeap(), 0, size
);
616 DWORD res
= GetEnvironmentVariable32A( name
, val
, size
);
617 HeapFree( GetProcessHeap(), 0, name
);
618 if (valW
) lstrcpynAtoW( valW
, val
, size
);
619 HeapFree( GetProcessHeap(), 0, val
);
624 /***********************************************************************
625 * SetEnvironmentVariable32A (KERNEL32.484)
627 BOOL32 WINAPI
SetEnvironmentVariable32A( LPCSTR name
, LPCSTR value
)
629 INT32 size
, len
, res
;
630 LPSTR p
, env
, new_env
;
631 PDB32
*pdb
= PROCESS_Current();
633 env
= p
= pdb
->env_db
->environ
;
635 /* Find a place to insert the string */
641 res
= lstrncmpi32A( name
, p
, len
);
643 if (!res
&& (p
[len
] == '=')) break;
647 if (!value
&& res
) /* Value to remove doesn't exist already */
650 /* Realloc the buffer */
652 len
= value
? strlen(name
) + strlen(value
) + 2 : 0;
653 if (!res
) len
-= strlen(p
) + 1; /* The name already exists */
654 size
= pdb
->env_db
->env_size
+ len
;
657 LPSTR next
= p
+ strlen(p
) + 1;
658 memmove( next
+ len
, next
, pdb
->env_db
->env_size
- (next
- env
) );
660 if (!(new_env
= HeapReAlloc( GetProcessHeap(), 0, env
, size
)))
662 p
= new_env
+ (p
- env
);
663 if (len
> 0) memmove( p
+ len
, p
, pdb
->env_db
->env_size
- (p
-new_env
) );
665 /* Set the new string */
673 pdb
->env_db
->env_size
= size
;
674 pdb
->env_db
->environ
= new_env
;
679 /***********************************************************************
680 * SetEnvironmentVariable32W (KERNEL32.485)
682 BOOL32 WINAPI
SetEnvironmentVariable32W( LPCWSTR name
, LPCWSTR value
)
684 LPSTR nameA
= HEAP_strdupWtoA( GetProcessHeap(), 0, name
);
685 LPSTR valueA
= HEAP_strdupWtoA( GetProcessHeap(), 0, value
);
686 BOOL32 ret
= SetEnvironmentVariable32A( nameA
, valueA
);
687 HeapFree( GetProcessHeap(), 0, nameA
);
688 HeapFree( GetProcessHeap(), 0, valueA
);
693 /***********************************************************************
694 * ExpandEnvironmentVariablesA (KERNEL32.103)
696 DWORD WINAPI
ExpandEnvironmentStrings32A( LPCSTR src
, LPSTR dst
, DWORD len
)
700 HANDLE32 heap
= GetProcessHeap();
701 LPSTR xdst
= HeapAlloc(heap
,0,10);
705 fprintf(stderr
,"ExpandEnvironmentStrings32A(%s)\n",src
);
708 memset(dst
,'\0',len
);
709 #define CHECK_FREE(n) { \
710 DWORD _needed = (n); \
712 while (cursize-(d-xdst)<_needed) { \
713 DWORD ind = d-xdst; \
716 xdst=(LPSTR)HeapReAlloc(heap,0,xdst,cursize);\
725 end
= s
;do { end
++; } while (*end
&& *end
!='%');
727 LPSTR x
= HeapAlloc(heap
,0,end
-s
+1);
730 lstrcpyn32A(x
,s
+1,end
-s
);
733 /* put expanded variable directly into
734 * destination string, so we don't have
735 * to use temporary buffers.
737 ret
= GetEnvironmentVariable32A(x
,buf
,2);
739 ret
= GetEnvironmentVariable32A(x
,d
,cursize
-(d
-xdst
));
744 CHECK_FREE(strlen(x
)+2);
761 ret
= lstrlen32A(xdst
)+1;
763 lstrcpy32A(dst
,xdst
);
764 HeapFree(heap
,0,xdst
);
768 /***********************************************************************
769 * ExpandEnvironmentVariablesA (KERNEL32.104)
771 DWORD WINAPI
ExpandEnvironmentStrings32W( LPCWSTR src
, LPWSTR dst
, DWORD len
)
773 HANDLE32 heap
= GetProcessHeap();
774 LPSTR srcA
= HEAP_strdupWtoA(heap
,0,src
);
775 LPSTR dstA
= HeapAlloc(heap
,0,len
);
776 DWORD ret
= ExpandEnvironmentStrings32A(srcA
,dstA
,len
);
778 lstrcpyAtoW(dst
,dstA
);
779 HeapFree(heap
,0,dstA
);
780 HeapFree(heap
,0,srcA
);
784 /***********************************************************************
785 * GetProcessHeap (KERNEL32.259)
787 HANDLE32 WINAPI
GetProcessHeap(void)
789 PDB32
*pdb
= PROCESS_Current();
790 return pdb
->heap
? pdb
->heap
: SystemHeap
;
794 /***********************************************************************
795 * GetThreadLocale (KERNEL32.295)
797 LCID WINAPI
GetThreadLocale(void)
799 return PROCESS_Current()->locale
;
803 /***********************************************************************
804 * SetPriorityClass (KERNEL32.503)
806 BOOL32 WINAPI
SetPriorityClass( HANDLE32 hprocess
, DWORD priorityclass
)
810 pdb
= (PDB32
*)PROCESS_GetObjPtr(hprocess
,K32OBJ_PROCESS
);
811 if (!pdb
) return FALSE
;
812 switch (priorityclass
)
814 case NORMAL_PRIORITY_CLASS
:
815 pdb
->priority
= 0x00000008;
817 case IDLE_PRIORITY_CLASS
:
818 pdb
->priority
= 0x00000004;
820 case HIGH_PRIORITY_CLASS
:
821 pdb
->priority
= 0x0000000d;
823 case REALTIME_PRIORITY_CLASS
:
824 pdb
->priority
= 0x00000018;
827 fprintf(stderr
,"SetPriorityClass: unknown priority class %ld\n",priorityclass
);
830 K32OBJ_DecCount((K32OBJ
*)pdb
);
835 /***********************************************************************
836 * GetPriorityClass (KERNEL32.250)
838 DWORD WINAPI
GetPriorityClass(HANDLE32 hprocess
)
843 pdb
= (PDB32
*)PROCESS_GetObjPtr(hprocess
,K32OBJ_PROCESS
);
847 switch (pdb
->priority
)
850 ret
= NORMAL_PRIORITY_CLASS
;
853 ret
= IDLE_PRIORITY_CLASS
;
856 ret
= HIGH_PRIORITY_CLASS
;
859 ret
= REALTIME_PRIORITY_CLASS
;
862 fprintf(stderr
,"GetPriorityClass: unknown priority %ld\n",pdb
->priority
);
864 K32OBJ_DecCount((K32OBJ
*)pdb
);
870 /***********************************************************************
871 * GetStdHandle (KERNEL32.276)
873 * FIXME: These should be allocated when a console is created, or inherited
876 HANDLE32 WINAPI
GetStdHandle( DWORD std_handle
)
880 PDB32
*pdb
= PROCESS_Current();
884 case STD_INPUT_HANDLE
:
885 if (pdb
->env_db
->hStdin
) return pdb
->env_db
->hStdin
;
888 case STD_OUTPUT_HANDLE
:
889 if (pdb
->env_db
->hStdout
) return pdb
->env_db
->hStdout
;
892 case STD_ERROR_HANDLE
:
893 if (pdb
->env_db
->hStderr
) return pdb
->env_db
->hStderr
;
897 SetLastError( ERROR_INVALID_PARAMETER
);
898 return INVALID_HANDLE_VALUE32
;
900 hFile
= FILE_DupUnixHandle( fd
);
901 if (hFile
!= HFILE_ERROR32
)
903 FILE_SetFileType( hFile
, FILE_TYPE_CHAR
);
906 case STD_INPUT_HANDLE
: pdb
->env_db
->hStdin
= hFile
; break;
907 case STD_OUTPUT_HANDLE
: pdb
->env_db
->hStdout
= hFile
; break;
908 case STD_ERROR_HANDLE
: pdb
->env_db
->hStderr
= hFile
; break;
915 /***********************************************************************
916 * SetStdHandle (KERNEL32.506)
918 BOOL32 WINAPI
SetStdHandle( DWORD std_handle
, HANDLE32 handle
)
920 PDB32
*pdb
= PROCESS_Current();
923 case STD_INPUT_HANDLE
:
924 pdb
->env_db
->hStdin
= handle
;
926 case STD_OUTPUT_HANDLE
:
927 pdb
->env_db
->hStdout
= handle
;
929 case STD_ERROR_HANDLE
:
930 pdb
->env_db
->hStderr
= handle
;
933 SetLastError( ERROR_INVALID_PARAMETER
);
937 /***********************************************************************
938 * GetProcessVersion (KERNEL32)
940 DWORD WINAPI
GetProcessVersion( DWORD processid
)
943 PDB32
*pdb
= PROCESS_IdToPDB( processid
);
946 if (!(pTask
= (TDB
*)GlobalLock16( pdb
->task
))) return 0;
947 return (pTask
->version
&0xff) | (((pTask
->version
>>8) & 0xff)<<16);
950 /***********************************************************************
951 * GetProcessFlags (KERNEL32)
953 DWORD WINAPI
GetProcessFlags( DWORD processid
)
955 PDB32
*pdb
= PROCESS_IdToPDB( processid
);
960 /***********************************************************************
961 * SetProcessWorkingSetSize (KERNEL32)
963 BOOL32 WINAPI
SetProcessWorkingSetSize(HANDLE32 hProcess
,DWORD minset
,
966 fprintf(stderr
,"SetProcessWorkingSetSize(0x%08x,%ld,%ld), STUB!\n",
967 hProcess
,minset
,maxset
972 /***********************************************************************
973 * GetProcessWorkingSetSize (KERNEL32)
975 BOOL32 WINAPI
GetProcessWorkingSetSize(HANDLE32 hProcess
,LPDWORD minset
,
978 fprintf(stderr
,"SetProcessWorkingSetSize(0x%08x,%p,%p), STUB!\n",
979 hProcess
,minset
,maxset
981 /* 32 MB working set size */
982 if (minset
) *minset
= 32*1024*1024;
983 if (maxset
) *maxset
= 32*1024*1024;
987 /***********************************************************************
988 * SetProcessShutdownParameters (KERNEL32)
990 BOOL32 WINAPI
SetProcessShutdownParameters(DWORD level
,DWORD flags
)
992 fprintf(stderr
,"SetProcessShutdownParameters(%ld,0x%08lx), STUB!\n",
998 /***********************************************************************
999 * ReadProcessMemory (KERNEL32)
1000 * FIXME: check this, if we ever run win32 binaries in different addressspaces
1001 * ... and add a sizecheck
1003 BOOL32 WINAPI
ReadProcessMemory( HANDLE32 hProcess
, LPCVOID lpBaseAddress
,
1004 LPVOID lpBuffer
, DWORD nSize
,
1005 LPDWORD lpNumberOfBytesRead
)
1007 memcpy(lpBuffer
,lpBaseAddress
,nSize
);
1008 if (lpNumberOfBytesRead
) *lpNumberOfBytesRead
= nSize
;
1012 /***********************************************************************
1013 * ConvertToGlobalHandle (KERNEL32)
1014 * FIXME: this is not correctly implemented...
1016 HANDLE32 WINAPI
ConvertToGlobalHandle(HANDLE32 h
)
1018 fprintf(stderr
,"ConvertToGlobalHandle(%d),stub!\n",h
);
1022 /***********************************************************************
1023 * RegisterServiceProcess (KERNEL32)
1025 * A service process calls this function to ensure that it continues to run
1026 * even after a user logged off.
1028 DWORD
RegisterServiceProcess(DWORD dwProcessId
, DWORD dwType
)
1030 /* I don't think that Wine needs to do anything in that function */
1031 return 1; /* success */