4 * General class implementations for 16 bit Windows.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.18 2001/08/07 03:20:39 robertj
31 * Fixed close of DLL so flagged as closed, thanks Stefan Ditscheid.
33 * Revision 1.17 1998/09/24 03:30:51 robertj
34 * Added open software license.
36 * Revision 1.16 1996/02/15 14:55:02 robertj
39 * Revision 1.15 1996/01/28 02:55:33 robertj
42 * Revision 1.14 1995/12/10 11:58:37 robertj
43 * Added WIN32 registry support for PConfig objects.
45 * Revision 1.13 1995/08/24 12:40:52 robertj
46 * Changed PChannel so not a PContainer.
48 * Revision 1.12 1995/07/02 01:24:45 robertj
49 * Added running of hidden VM for DOS program in PPipeChannel.
51 * Revision 1.11 1995/06/17 00:59:23 robertj
52 * Moved PPipeChannel::Execute from common dos/windows to individual files.
54 * Revision 1.10 1995/03/12 05:00:06 robertj
55 * Re-organisation of DOS/WIN16 and WIN32 platforms to maximise common code.
56 * Used built-in equate for WIN32 API (_WIN32).
58 * Revision 1.9 1995/01/09 12:28:00 robertj
59 * Added implementation for PConfig::Environment
61 * Revision 1.8 1994/10/23 05:41:29 robertj
62 * Fixed config file bugs.
64 * Revision 1.7 1994/08/22 00:18:02 robertj
65 * Fixed bug in serial comms timers.
67 * Revision 1.6 1994/08/04 13:24:27 robertj
68 * Added DCB so can set paraemters on closed channel.
70 * Revision 1.5 1994/07/27 06:00:10 robertj
73 * Revision 1.4 1994/07/21 12:35:18 robertj
74 * *** empty log message ***
76 * Revision 1.3 1994/07/17 11:01:04 robertj
77 * Ehancements, implementation, bug fixes etc.
79 * Revision 1.2 1994/07/02 03:18:09 robertj
80 * Multi-threading implementation.
82 * Revision 1.1 1994/06/25 12:13:01 robertj
85 // Revision 1.1 1994/04/01 14:39:35 robertj
97 extern "C" HINSTANCE _hInstance
;
100 ///////////////////////////////////////////////////////////////////////////////
103 PString
PTime::GetTimeSeparator()
106 GetProfileString("intl", "sTime", ":", str
.GetPointer(100), 99);
107 str
.MakeMinimumSize();
112 BOOL
PTime::GetTimeAMPM()
114 return GetProfileInt("intl", "iTime", 0) != 0;
118 PString
PTime::GetTimeAM()
121 GetProfileString("intl", "s1159", "am", str
.GetPointer(100), 99);
122 str
.MakeMinimumSize();
127 PString
PTime::GetTimePM()
130 GetProfileString("intl", "s2359", "pm", str
.GetPointer(100), 99);
131 str
.MakeMinimumSize();
136 PString
PTime::GetDayName(Weekdays dayOfWeek
, NameType type
)
138 static const char * const weekdays
[] = {
139 "Sunday", "Monday", "Tuesday", "Wednesday",
140 "Thursday", "Friday", "Saturday"
142 static const char * const abbrev_weekdays
[] = {
143 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
146 if (LoadString(_hInstance
, dayOfWeek
+
147 (type
!= FullName
? PSTD_ID_STR_ABBREV_WEEKDAYS
: PSTD_ID_STR_WEEKDAYS
),
148 str
.GetPointer(100), 99) == 0)
149 return (type
!= FullName
? abbrev_weekdays
: weekdays
)[dayOfWeek
];
150 str
.MakeMinimumSize();
155 PString
PTime::GetDateSeparator()
158 GetProfileString("intl", "sDate", "-", str
.GetPointer(100), 99);
159 str
.MakeMinimumSize();
164 PString
PTime::GetMonthName(Months month
, NameType type
)
166 static const char * const months
[] = { "",
167 "January", "February", "March", "April", "May", "June",
168 "July", "August", "September", "October", "November", "December"
170 static const char * const abbrev_months
[] = {
171 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
172 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
175 if (LoadString(_hInstance
, month
+
176 (UINT
)(type
!= FullName
? PSTD_ID_STR_ABBREV_MONTHS
: PSTD_ID_STR_MONTHS
),
177 str
.GetPointer(100), 99) == 0)
178 return (type
!= FullName
? abbrev_months
: months
)[month
];
179 str
.MakeMinimumSize();
184 PTime::DateOrder
PTime::GetDateOrder()
186 return (DateOrder
)GetProfileInt("intl", "iDate", 0);
190 BOOL
PTime::IsDaylightSavings()
196 int PTime::GetTimeZone(TimeZoneType type
)
202 PString
PTime::GetTimeZoneString(TimeZoneType type
)
208 ///////////////////////////////////////////////////////////////////////////////
211 void PSerialChannel::Construct()
215 GetProfileString("ports", str
, "9600,n,8,1,x", &str
[5], sizeof(str
)-6);
217 if (!BuildCommDCB(str
, &deviceControlBlock
)) {
219 lastError
= BadParameter
;
224 PString
PSerialChannel::GetName() const
227 return psprintf("COM%i", os_handle
+1);
233 BOOL
PSerialChannel::IsReadBlocked(PObject
* obj
)
235 PSerialChannel
& chan
= *(PSerialChannel
*)PAssertNULL(obj
);
237 GetCommError(chan
.os_handle
, &stat
);
238 return stat
.cbInQue
<= 0 &&
239 (chan
.readTimeout
== PMaxTimeInterval
|| chan
.readTimer
.IsRunning());
243 BOOL
PSerialChannel::Read(void * buf
, PINDEX len
)
254 if (readTimeout
!= PMaxTimeInterval
)
255 readTimer
= readTimeout
;
256 if (IsReadBlocked(this))
257 PThread::Current()->Block(&PSerialChannel::IsReadBlocked
, this);
259 lastReadCount
= ReadComm(os_handle
, buf
, len
);
260 if (lastReadCount
> 0)
264 GetCommError(os_handle
, &stat
);
266 lastReadCount
= -lastReadCount
;
267 return lastReadCount
> 0;
271 BOOL
PSerialChannel::IsWriteBlocked(PObject
* obj
)
273 PSerialChannel
& chan
= *(PSerialChannel
*)PAssertNULL(obj
);
275 GetCommError(chan
.os_handle
, &stat
);
276 return stat
.cbOutQue
>= OutputQueueSize
&&
277 (chan
.writeTimeout
== PMaxTimeInterval
|| chan
.writeTimer
.IsRunning());
281 BOOL
PSerialChannel::Write(const void * buf
, PINDEX len
)
291 if (writeTimeout
!= PMaxTimeInterval
)
292 writeTimer
= writeTimeout
;
293 if (IsWriteBlocked(this))
294 PThread::Current()->Block(&PSerialChannel::IsWriteBlocked
, this);
296 lastWriteCount
= WriteComm(os_handle
, buf
, len
);
297 if (lastWriteCount
<= 0) {
299 GetCommError(os_handle
, &stat
);
301 lastWriteCount
= -lastWriteCount
;
303 return lastWriteCount
>= len
;
307 BOOL
PSerialChannel::Close()
315 BOOL retVal
= CloseComm(os_handle
) == 0;
321 BOOL
PSerialChannel::SetCommsParam(DWORD speed
, BYTE data
, Parity parity
,
322 BYTE stop
, FlowControl inputFlow
, FlowControl outputFlow
)
325 PAssert(GetCommState(os_handle
, &deviceControlBlock
) == 0,
326 POperatingSystemError
);
332 deviceControlBlock
.BaudRate
= CBR_14400
;
335 deviceControlBlock
.BaudRate
= CBR_19200
;
338 deviceControlBlock
.BaudRate
= CBR_38400
;
341 deviceControlBlock
.BaudRate
= CBR_56000
;
344 deviceControlBlock
.BaudRate
= CBR_128000
;
347 deviceControlBlock
.BaudRate
= CBR_256000
;
354 deviceControlBlock
.BaudRate
= (UINT
)speed
;
358 deviceControlBlock
.ByteSize
= data
;
362 deviceControlBlock
.Parity
= NOPARITY
;
365 deviceControlBlock
.Parity
= ODDPARITY
;
368 deviceControlBlock
.Parity
= EVENPARITY
;
371 deviceControlBlock
.Parity
= MARKPARITY
;
374 deviceControlBlock
.Parity
= SPACEPARITY
;
379 deviceControlBlock
.StopBits
= ONESTOPBIT
;
382 deviceControlBlock
.StopBits
= TWOSTOPBITS
;
387 deviceControlBlock
.fRtsflow
= FALSE
;
388 deviceControlBlock
.fInX
= FALSE
;
391 deviceControlBlock
.fRtsflow
= FALSE
;
392 deviceControlBlock
.fInX
= TRUE
;
395 deviceControlBlock
.fRtsflow
= TRUE
;
396 deviceControlBlock
.fInX
= FALSE
;
400 switch (outputFlow
) {
402 deviceControlBlock
.fOutxCtsFlow
= FALSE
;
403 deviceControlBlock
.fOutxDsrFlow
= FALSE
;
404 deviceControlBlock
.fOutX
= FALSE
;
407 deviceControlBlock
.fOutxCtsFlow
= FALSE
;
408 deviceControlBlock
.fOutxDsrFlow
= FALSE
;
409 deviceControlBlock
.fOutX
= TRUE
;
412 deviceControlBlock
.fOutxCtsFlow
= TRUE
;
413 deviceControlBlock
.fOutxDsrFlow
= FALSE
;
414 deviceControlBlock
.fOutX
= FALSE
;
421 lastError
= BadParameter
;
425 if (SetCommState(&deviceControlBlock
) < 0) {
430 PAssert(GetCommState(os_handle
, &deviceControlBlock
) == 0,
431 POperatingSystemError
);
436 BOOL
PSerialChannel::Open(const PString
& port
, DWORD speed
, BYTE data
,
437 Parity parity
, BYTE stop
, FlowControl inputFlow
, FlowControl outputFlow
)
441 os_handle
= OpenComm(port
, InputQueueSize
, OutputQueueSize
);
447 lastError
= NotFound
;
451 lastError
= DeviceInUse
;
455 lastError
= NoMemory
;
460 lastError
= BadParameter
;
464 lastError
= Miscellaneous
;
470 deviceControlBlock
.Id
= (BYTE
)os_handle
;
471 SetCommState(&deviceControlBlock
);
473 if (!SetCommsParam(speed
, data
, parity
, stop
, inputFlow
, outputFlow
)) {
474 CloseComm(os_handle
);
478 SetCommEventMask(os_handle
, EV_CTSS
|EV_DSR
|EV_RING
|EV_RLSDS
);
483 BOOL
PSerialChannel::SetSpeed(DWORD speed
)
485 return SetCommsParam(speed
,
486 0, DefaultParity
, 0, DefaultFlowControl
, DefaultFlowControl
);
490 DWORD
PSerialChannel::GetSpeed() const
492 switch (deviceControlBlock
.BaudRate
) {
520 return deviceControlBlock
.BaudRate
;
524 BOOL
PSerialChannel::SetDataBits(BYTE data
)
526 return SetCommsParam(0,
527 data
, DefaultParity
, 0, DefaultFlowControl
, DefaultFlowControl
);
531 BYTE
PSerialChannel::GetDataBits() const
533 return deviceControlBlock
.ByteSize
;
537 BOOL
PSerialChannel::SetParity(Parity parity
)
539 return SetCommsParam(0,0, parity
, 0, DefaultFlowControl
, DefaultFlowControl
);
543 PSerialChannel::Parity
PSerialChannel::GetParity() const
545 switch (deviceControlBlock
.Parity
) {
559 BOOL
PSerialChannel::SetStopBits(BYTE stop
)
561 return SetCommsParam(0,
562 0, DefaultParity
, stop
, DefaultFlowControl
, DefaultFlowControl
);
566 BYTE
PSerialChannel::GetStopBits() const
568 return (BYTE
)(deviceControlBlock
.StopBits
== ONESTOPBIT
? 1 : 2);
572 BOOL
PSerialChannel::SetInputFlowControl(FlowControl flowControl
)
574 return SetCommsParam(0,0, DefaultParity
, 0, flowControl
, DefaultFlowControl
);
578 PSerialChannel::FlowControl
PSerialChannel::GetInputFlowControl() const
580 if (deviceControlBlock
.fRtsflow
)
582 if (deviceControlBlock
.fInX
!= 0)
584 return NoFlowControl
;
588 BOOL
PSerialChannel::SetOutputFlowControl(FlowControl flowControl
)
590 return SetCommsParam(0,0, DefaultParity
, 0, DefaultFlowControl
, flowControl
);
594 PSerialChannel::FlowControl
PSerialChannel::GetOutputFlowControl() const
596 if (deviceControlBlock
.fOutxCtsFlow
!= 0)
598 if (deviceControlBlock
.fOutX
!= 0)
600 return NoFlowControl
;
604 void PSerialChannel::SetDTR(BOOL state
)
612 PAssert(EscapeCommFunction(os_handle
, state
? SETDTR
: CLRDTR
) == 0,
613 POperatingSystemError
);
617 void PSerialChannel::SetRTS(BOOL state
)
625 PAssert(EscapeCommFunction(os_handle
, state
? SETRTS
: CLRRTS
) == 0,
626 POperatingSystemError
);
630 void PSerialChannel::SetBreak(BOOL state
)
639 PAssert(SetCommBreak(os_handle
), POperatingSystemError
);
641 PAssert(ClearCommBreak(os_handle
), POperatingSystemError
);
645 BOOL
PSerialChannel::GetCTS()
653 return (GetCommEventMask(os_handle
, 0)&EV_CTSS
) != 0;
657 BOOL
PSerialChannel::GetDSR()
665 return (GetCommEventMask(os_handle
, 0)&EV_DSR
) != 0;
669 BOOL
PSerialChannel::GetDCD()
677 return (GetCommEventMask(os_handle
, 0)&EV_RLSDS
) != 0;
681 BOOL
PSerialChannel::GetRing()
689 return (GetCommEventMask(os_handle
, 0)&EV_RING
) != 0;
693 PStringList
PSerialChannel::GetPortNames()
695 static char buf
[] = "COM ";
697 for (char p
= '1'; p
<= '4'; p
++) {
699 ports
.Append(new PString(buf
));
705 ///////////////////////////////////////////////////////////////////////////////
708 BOOL
PPipeChannel::Execute()
714 if (os_handle
>= 0) {
725 } exePath
, programArguments
, workingDirectory
;
726 WORD desiredV86Pages
;
727 WORD minimumV86Pages
;
728 WORD foregroundPriority
;
729 WORD backgroundPriority
;
735 char windowTitle
[128];
737 0x40000006, // Runs in background, runs in window, close on exit
738 0x0000001f, // Emulate text mode, no monitor ports
742 0xffff, // desired memory
743 0xffff, // minimum memory
744 100, // foreground priority
745 50, // background priority
746 0x0400, // maximum EMS
748 0x4000, // maximum XMS
751 "PWLib Pipe Channel Process"
754 char * commandDotCom
= getenv("COMSPEC");
755 if (commandDotCom
== NULL
)
756 commandDotCom
= "C:\\COMMAND.COM";
757 seb
.exePath
.selector
= SELECTOROF(commandDotCom
);
758 seb
.exePath
.offset
= OFFSETOF (commandDotCom
);
760 PString commandArguments
= " /c " + subProgName
;
761 const char * argumentPointer
= commandArguments
;
762 seb
.programArguments
.selector
= SELECTOROF(argumentPointer
);
763 seb
.programArguments
.offset
= OFFSETOF (argumentPointer
);
765 static char * currentDirectory
= ".";
766 seb
.workingDirectory
.selector
= SELECTOROF(currentDirectory
);
767 seb
.workingDirectory
.offset
= OFFSETOF (currentDirectory
);
769 void (FAR
* shellEntry
)();
770 _asm mov ax
,1684h
; //Get Shell VXDs protected mode entry point
773 _asm mov word ptr
[shellEntry
], di
;
774 _asm mov word ptr
[shellEntry
+2], es
;
775 if (shellEntry
== NULL
)
778 _asm lea di
, word ptr seb
;
786 DWORD hVirtualMachine
;
787 #if defined(_MSC_VER)
792 _asm mov word ptr hVirtualMachine
, ax
; // Really EAX
793 if (hVirtualMachine
== 0)
796 if (fromChild
.IsEmpty())
799 // Wait for child to complete
802 os_handle
= _open(fromChild
, _O_RDONLY
);
803 return ConvertOSError(os_handle
);
807 ///////////////////////////////////////////////////////////////////////////////
808 // Configuration files
810 void PConfig::Construct(Source src
)
814 location
= "WIN.INI";
818 PFilePath appFile
= PProcess::Current()->GetFile();
819 location
= appFile
.GetDirectory() + appFile
.GetTitle() + ".INI";
827 void PConfig::Construct(const PFilePath
& filename
)
834 PStringList
PConfig::GetSections()
836 PStringList sections
;
838 if (source
!= Environment
) {
840 char * ptr
= buf
.GetPointer(10000);
841 GetPrivateProfileString(NULL
, NULL
, "", ptr
, 9999, location
);
842 while (*ptr
!= '\0') {
843 sections
.AppendString(ptr
);
844 ptr
+= strlen(ptr
)+1;
852 PStringList
PConfig::GetKeys(const PString
& section
) const
856 if (source
== Environment
) {
857 char ** ptr
= _environ
;
858 while (*ptr
!= NULL
) {
859 PString buf
= *ptr
++;
860 keys
.AppendString(buf
.Left(buf
.Find('=')));
865 char * ptr
= buf
.GetPointer(10000);
866 GetPrivateProfileString(section
, NULL
, "", ptr
, 9999, location
);
867 while (*ptr
!= '\0') {
868 keys
.AppendString(ptr
);
869 ptr
+= strlen(ptr
)+1;
877 void PConfig::DeleteSection(const PString
& section
)
879 if (source
== Environment
)
882 PAssert(!section
.IsEmpty(), PInvalidParameter
);
883 PAssertOS(WritePrivateProfileString(section
, NULL
, NULL
, location
));
887 void PConfig::DeleteKey(const PString
& section
, const PString
& key
)
889 PAssert(!key
.IsEmpty(), PInvalidParameter
);
891 if (source
== Environment
) {
893 PAssert(str
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
897 PAssert(!section
.IsEmpty(), PInvalidParameter
);
898 PAssertOS(WritePrivateProfileString(section
, key
, NULL
, location
));
903 PString
PConfig::GetString(const PString
& section
,
904 const PString
& key
, const PString
& dflt
)
908 PAssert(!key
.IsEmpty(), PInvalidParameter
);
910 if (source
== Environment
) {
911 PAssert(key
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
912 char * env
= getenv(key
);
919 PAssert(!section
.IsEmpty(), PInvalidParameter
);
920 GetPrivateProfileString(section
, key
, dflt
,
921 str
.GetPointer(1000), 999, location
);
922 str
.MakeMinimumSize();
929 void PConfig::SetString(const PString
& section
,
930 const PString
& key
, const PString
& value
)
932 PAssert(!key
.IsEmpty(), PInvalidParameter
);
934 if (source
== Environment
) {
936 PAssert(str
.Find('=') == P_MAX_INDEX
, PInvalidParameter
);
937 _putenv(str
+ "=" + value
);
940 PAssert(!section
.IsEmpty(), PInvalidParameter
);
941 PAssertOS(WritePrivateProfileString(section
, key
, value
, location
));
947 ///////////////////////////////////////////////////////////////////////////////
950 static char NEAR
* NEAR
* const StackBase
= (char NEAR
* NEAR
*)0xa;
951 static char NEAR
* NEAR
* const StackUsed
= (char NEAR
* NEAR
*)0xc;
952 static char NEAR
* NEAR
* const StackTop
= (char NEAR
* NEAR
*)0xe;
954 void PThread::SwitchContext(PThread
* from
)
956 if (from
== this) // Switching to itself, ie is only thread
959 if (setjmp(from
->context
) != 0) // Are being reactivated from previous yield
962 // Save some magic global variables in MS-Windows DGROUP segment
963 from
->stackBase
= *StackBase
;
964 from
->stackTop
= *StackTop
;
965 from
->stackUsed
= *StackTop
- *StackUsed
;
967 if (status
== Starting
) {
968 if (setjmp(context
) != 0)
970 context
[3] = (int)stackTop
-16; // Change the stack pointer in jmp_buf
973 // Restore those MS-Windows magic global for the next context
974 *StackBase
= stackBase
;
975 *StackTop
= stackTop
;
976 *StackUsed
= stackTop
- stackUsed
;
978 longjmp(context
, TRUE
);
979 PAssertAlways("longjmp failed"); // Should never get here
983 ///////////////////////////////////////////////////////////////////////////////
986 PDynaLink::PDynaLink()
992 PDynaLink::PDynaLink(const PString
& name
)
998 PDynaLink::~PDynaLink()
1004 BOOL
PDynaLink::Open(const PString
& name
)
1006 if ((_hDLL
= LoadLibrary(name
)) < HINSTANCE_ERROR
)
1008 return _hDLL
!= NULL
;
1012 void PDynaLink::Close()
1014 if (_hDLL
!= NULL
) {
1021 BOOL
PDynaLink::IsLoaded() const
1023 return _hDLL
!= NULL
;
1027 BOOL
PDynaLink::GetFunction(PINDEX index
, Function
& func
)
1032 FARPROC p
= GetProcAddress(_hDLL
, (LPSTR
)(DWORD
)LOWORD(index
));
1041 BOOL
PDynaLink::GetFunction(const PString
& name
, Function
& func
)
1046 FARPROC p
= GetProcAddress(_hDLL
, name
);
1056 // End Of File ///////////////////////////////////////////////////////////////