sysutils.pp 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by Florian Klaempfl
  4. member of the Free Pascal development team
  5. Sysutils unit for EMX
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit sysutils;
  13. interface
  14. {$MODE objfpc}
  15. {$MODESWITCH OUT}
  16. { force ansistrings }
  17. {$H+}
  18. uses
  19. Dos;
  20. {$DEFINE HAS_SLEEP}
  21. { Include platform independent interface part }
  22. {$i sysutilh.inc}
  23. implementation
  24. uses
  25. sysconst;
  26. {$DEFINE FPC_FEXPAND_UNC} (* UNC paths are supported *)
  27. {$DEFINE FPC_FEXPAND_DRIVES} (* Full paths begin with drive specification *)
  28. { used OS file system APIs use ansistring }
  29. {$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
  30. { Include platform independent implementation part }
  31. {$i sysutils.inc}
  32. {****************************************************************************
  33. System (imported) calls
  34. ****************************************************************************}
  35. (* "uses DosCalls" could not be used here due to type *)
  36. (* conflicts, so needed parts had to be redefined here). *)
  37. type
  38. TFileStatus = object
  39. end;
  40. PFileStatus = ^TFileStatus;
  41. TFileStatus3 = object (TFileStatus)
  42. DateCreation, {Date of file creation.}
  43. TimeCreation, {Time of file creation.}
  44. DateLastAccess, {Date of last access to file.}
  45. TimeLastAccess, {Time of last access to file.}
  46. DateLastWrite, {Date of last modification of file.}
  47. TimeLastWrite:word; {Time of last modification of file.}
  48. FileSize, {Size of file.}
  49. FileAlloc:cardinal; {Amount of space the file really
  50. occupies on disk.}
  51. AttrFile:cardinal; {Attributes of file.}
  52. end;
  53. PFileStatus3=^TFileStatus3;
  54. TFileStatus4=object(TFileStatus3)
  55. cbList:cardinal; {Length of entire EA set.}
  56. end;
  57. PFileStatus4=^TFileStatus4;
  58. TFileStatus3L = object (TFileStatus)
  59. DateCreation, {Date of file creation.}
  60. TimeCreation, {Time of file creation.}
  61. DateLastAccess, {Date of last access to file.}
  62. TimeLastAccess, {Time of last access to file.}
  63. DateLastWrite, {Date of last modification of file.}
  64. TimeLastWrite:word; {Time of last modification of file.}
  65. FileSize, {Size of file.}
  66. FileAlloc:int64; {Amount of space the file really
  67. occupies on disk.}
  68. AttrFile:cardinal; {Attributes of file.}
  69. end;
  70. PFileStatus3L=^TFileStatus3L;
  71. TFileStatus4L=object(TFileStatus3L)
  72. cbList:cardinal; {Length of entire EA set.}
  73. end;
  74. PFileStatus4L=^TFileStatus4L;
  75. TFileFindBuf3=object(TFileStatus)
  76. NextEntryOffset: cardinal; {Offset of next entry}
  77. DateCreation, {Date of file creation.}
  78. TimeCreation, {Time of file creation.}
  79. DateLastAccess, {Date of last access to file.}
  80. TimeLastAccess, {Time of last access to file.}
  81. DateLastWrite, {Date of last modification of file.}
  82. TimeLastWrite:word; {Time of last modification of file.}
  83. FileSize, {Size of file.}
  84. FileAlloc:cardinal; {Amount of space the file really
  85. occupies on disk.}
  86. AttrFile:cardinal; {Attributes of file.}
  87. Name:shortstring; {Also possible to use as ASCIIZ.
  88. The byte following the last string
  89. character is always zero.}
  90. end;
  91. PFileFindBuf3=^TFileFindBuf3;
  92. TFileFindBuf4=object(TFileStatus)
  93. NextEntryOffset: cardinal; {Offset of next entry}
  94. DateCreation, {Date of file creation.}
  95. TimeCreation, {Time of file creation.}
  96. DateLastAccess, {Date of last access to file.}
  97. TimeLastAccess, {Time of last access to file.}
  98. DateLastWrite, {Date of last modification of file.}
  99. TimeLastWrite:word; {Time of last modification of file.}
  100. FileSize, {Size of file.}
  101. FileAlloc:cardinal; {Amount of space the file really
  102. occupies on disk.}
  103. AttrFile:cardinal; {Attributes of file.}
  104. cbList:longint; {Size of the file's extended attributes.}
  105. Name:shortstring; {Also possible to use as ASCIIZ.
  106. The byte following the last string
  107. character is always zero.}
  108. end;
  109. PFileFindBuf4=^TFileFindBuf4;
  110. TFileFindBuf3L=object(TFileStatus)
  111. NextEntryOffset: cardinal; {Offset of next entry}
  112. DateCreation, {Date of file creation.}
  113. TimeCreation, {Time of file creation.}
  114. DateLastAccess, {Date of last access to file.}
  115. TimeLastAccess, {Time of last access to file.}
  116. DateLastWrite, {Date of last modification of file.}
  117. TimeLastWrite:word; {Time of last modification of file.}
  118. FileSize, {Size of file.}
  119. FileAlloc:int64; {Amount of space the file really
  120. occupies on disk.}
  121. AttrFile:cardinal; {Attributes of file.}
  122. Name:shortstring; {Also possible to use as ASCIIZ.
  123. The byte following the last string
  124. character is always zero.}
  125. end;
  126. PFileFindBuf3L=^TFileFindBuf3L;
  127. TFileFindBuf4L=object(TFileStatus)
  128. NextEntryOffset: cardinal; {Offset of next entry}
  129. DateCreation, {Date of file creation.}
  130. TimeCreation, {Time of file creation.}
  131. DateLastAccess, {Date of last access to file.}
  132. TimeLastAccess, {Time of last access to file.}
  133. DateLastWrite, {Date of last modification of file.}
  134. TimeLastWrite:word; {Time of last modification of file.}
  135. FileSize, {Size of file.}
  136. FileAlloc:int64; {Amount of space the file really
  137. occupies on disk.}
  138. AttrFile:cardinal; {Attributes of file.}
  139. cbList:cardinal; {Size of the file's extended attributes.}
  140. Name:shortstring; {Also possible to use as ASCIIZ.
  141. The byte following the last string
  142. character is always zero.}
  143. end;
  144. PFileFindBuf4L=^TFileFindBuf4L;
  145. TFSInfo = record
  146. case word of
  147. 1:
  148. (File_Sys_ID,
  149. Sectors_Per_Cluster,
  150. Total_Clusters,
  151. Free_Clusters: cardinal;
  152. Bytes_Per_Sector: word);
  153. 2: {For date/time description,
  154. see file searching realted
  155. routines.}
  156. (Label_Date, {Date when volume label was created.}
  157. Label_Time: word; {Time when volume label was created.}
  158. VolumeLabel: ShortString); {Volume label. Can also be used
  159. as ASCIIZ, because the byte
  160. following the last character of
  161. the string is always zero.}
  162. end;
  163. PFSInfo = ^TFSInfo;
  164. TCountryCode=record
  165. Country, {Country to query info about (0=current).}
  166. CodePage: cardinal; {Code page to query info about (0=current).}
  167. end;
  168. PCountryCode=^TCountryCode;
  169. TTimeFmt = (Clock12, Clock24);
  170. TCountryInfo=record
  171. Country, CodePage: cardinal; {Country and codepage requested.}
  172. case byte of
  173. 0:
  174. (DateFormat: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  175. CurrencyUnit: array [0..4] of char;
  176. ThousandSeparator: char; {Thousands separator.}
  177. Zero1: byte; {Always zero.}
  178. DecimalSeparator: char; {Decimals separator,}
  179. Zero2: byte;
  180. DateSeparator: char; {Date separator.}
  181. Zero3: byte;
  182. TimeSeparator: char; {Time separator.}
  183. Zero4: byte;
  184. CurrencyFormat, {Bit field:
  185. Bit 0: 0=indicator before value
  186. 1=indicator after value
  187. Bit 1: 1=insert space after
  188. indicator.
  189. Bit 2: 1=Ignore bit 0&1, replace
  190. decimal separator with
  191. indicator.}
  192. DecimalPlace: byte; {Number of decimal places used in
  193. currency indication.}
  194. TimeFormat: TTimeFmt; {12/24 hour.}
  195. Reserve1: array [0..1] of word;
  196. DataSeparator: char; {Data list separator}
  197. Zero5: byte;
  198. Reserve2: array [0..4] of word);
  199. 1:
  200. (fsDateFmt: cardinal; {1=ddmmyy 2=yymmdd 3=mmddyy}
  201. szCurrency: array [0..4] of char;
  202. {null terminated currency symbol}
  203. szThousandsSeparator: array [0..1] of char;
  204. {Thousands separator + #0}
  205. szDecimal: array [0..1] of char;
  206. {Decimals separator + #0}
  207. szDateSeparator: array [0..1] of char;
  208. {Date separator + #0}
  209. szTimeSeparator: array [0..1] of char;
  210. {Time separator + #0}
  211. fsCurrencyFmt, {Bit field:
  212. Bit 0: 0=indicator before value
  213. 1=indicator after value
  214. Bit 1: 1=insert space after
  215. indicator.
  216. Bit 2: 1=Ignore bit 0&1, replace
  217. decimal separator with
  218. indicator}
  219. cDecimalPlace: byte; {Number of decimal places used in
  220. currency indication}
  221. fsTimeFmt: byte; {0=12,1=24 hours}
  222. abReserved1: array [0..1] of word;
  223. szDataSeparator: array [0..1] of char;
  224. {Data list separator + #0}
  225. abReserved2: array [0..4] of word);
  226. end;
  227. PCountryInfo=^TCountryInfo;
  228. TRequestData=record
  229. PID, {ID of process that wrote element.}
  230. Data: cardinal; {Information from process writing the data.}
  231. end;
  232. PRequestData=^TRequestData;
  233. {Queue data structure for synchronously started sessions.}
  234. TChildInfo = record
  235. case boolean of
  236. false:
  237. (SessionID,
  238. Return: word); {Return code from the child process.}
  239. true:
  240. (usSessionID,
  241. usReturn: word); {Return code from the child process.}
  242. end;
  243. PChildInfo = ^TChildInfo;
  244. TStartData=record
  245. {Note: to omit some fields, use a length smaller than SizeOf(TStartData).}
  246. Length:word; {Length, in bytes, of datastructure
  247. (24/30/32/50/60).}
  248. Related:word; {Independent/child session (0/1).}
  249. FgBg:word; {Foreground/background (0/1).}
  250. TraceOpt:word; {No trace/trace this/trace all (0/1/2).}
  251. PgmTitle:PChar; {Program title.}
  252. PgmName:PChar; {Filename to program.}
  253. PgmInputs:PChar; {Command parameters (nil allowed).}
  254. TermQ:PChar; {System queue. (nil allowed).}
  255. Environment:PChar; {Environment to pass (nil allowed).}
  256. InheritOpt:word; {Inherit environment from shell/
  257. inherit environment from parent (0/1).}
  258. SessionType:word; {Auto/full screen/window/presentation
  259. manager/full screen Dos/windowed Dos
  260. (0/1/2/3/4/5/6/7).}
  261. Iconfile:PChar; {Icon file to use (nil allowed).}
  262. PgmHandle:cardinal; {0 or the program handle.}
  263. PgmControl:word; {Bitfield describing initial state
  264. of windowed sessions.}
  265. InitXPos,InitYPos:word; {Initial top coordinates.}
  266. InitXSize,InitYSize:word; {Initial size.}
  267. Reserved:word;
  268. ObjectBuffer:PChar; {If a module cannot be loaded, its
  269. name will be returned here.}
  270. ObjectBuffLen:cardinal; {Size of your buffer.}
  271. end;
  272. PStartData=^TStartData;
  273. const
  274. ilStandard = 1; (* Use TFileStatus3/TFindFileBuf3 *)
  275. ilQueryEASize = 2; (* Use TFileStatus4/TFindFileBuf4 *)
  276. ilQueryEAs = 3;
  277. ilQueryFullName = 5;
  278. ilStandardL = 11; (* Use TFileStatus3L/TFindFileBuf3L *)
  279. ilQueryEASizeL = 12; (* Use TFileStatus4L/TFindFileBuf4L *)
  280. ilQueryEAsL = 13;
  281. quFIFO = 0;
  282. quLIFO = 1;
  283. quPriority = 2;
  284. quNoConvert_Address = 0;
  285. quConvert_Address = 4;
  286. {Start the new session independent or as a child.}
  287. ssf_Related_Independent = 0; {Start new session independent
  288. of the calling session.}
  289. ssf_Related_Child = 1; {Start new session as a child
  290. session to the calling session.}
  291. {Start the new session in the foreground or in the background.}
  292. ssf_FgBg_Fore = 0; {Start new session in foreground.}
  293. ssf_FgBg_Back = 1; {Start new session in background.}
  294. {Should the program started in the new session
  295. be executed under conditions for tracing?}
  296. ssf_TraceOpt_None = 0; {No trace.}
  297. ssf_TraceOpt_Trace = 1; {Trace with no notification
  298. of descendants.}
  299. ssf_TraceOpt_TraceAll = 2; {Trace all descendant sessions.
  300. A termination queue must be
  301. supplied and Related must be
  302. ssf_Related_Child (=1).}
  303. {Will the new session inherit open file handles
  304. and environment from the calling process.}
  305. ssf_InhertOpt_Shell = 0; {Inherit from the shell.}
  306. ssf_InhertOpt_Parent = 1; {Inherit from the calling process.}
  307. {Specifies the type of session to start.}
  308. ssf_Type_Default = 0; {Use program's type.}
  309. ssf_Type_FullScreen = 1; {OS/2 full screen.}
  310. ssf_Type_WindowableVIO = 2; {OS/2 window.}
  311. ssf_Type_PM = 3; {Presentation Manager.}
  312. ssf_Type_VDM = 4; {DOS full screen.}
  313. ssf_Type_WindowedVDM = 7; {DOS window.}
  314. {Additional values for Windows programs}
  315. Prog_31_StdSeamlessVDM = 15; {Windows 3.1 program in its
  316. own windowed session.}
  317. Prog_31_StdSeamlessCommon = 16; {Windows 3.1 program in a
  318. common windowed session.}
  319. Prog_31_EnhSeamlessVDM = 17; {Windows 3.1 program in enhanced
  320. compatibility mode in its own
  321. windowed session.}
  322. Prog_31_EnhSeamlessCommon = 18; {Windows 3.1 program in enhanced
  323. compatibility mode in a common
  324. windowed session.}
  325. Prog_31_Enh = 19; {Windows 3.1 program in enhanced
  326. compatibility mode in a full
  327. screen session.}
  328. Prog_31_Std = 20; {Windows 3.1 program in a full
  329. screen session.}
  330. {Specifies the initial attributes for a OS/2 window or DOS window session.}
  331. ssf_Control_Visible = 0; {Window is visible.}
  332. ssf_Control_Invisible = 1; {Window is invisible.}
  333. ssf_Control_Maximize = 2; {Window is maximized.}
  334. ssf_Control_Minimize = 4; {Window is minimized.}
  335. ssf_Control_NoAutoClose = 8; {Window will not close after
  336. the program has ended.}
  337. ssf_Control_SetPos = 32768; {Use InitXPos, InitYPos,
  338. InitXSize, and InitYSize for
  339. the size and placement.}
  340. {This is the correct way to call external assembler procedures.}
  341. procedure syscall;external name '___SYSCALL';
  342. function DosSetFileInfo (Handle: THandle; InfoLevel: cardinal; AFileStatus: PFileStatus;
  343. FileStatusLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 218;
  344. function DosQueryFSInfo (DiskNum, InfoLevel: cardinal; var Buffer: TFSInfo;
  345. BufLen: cardinal): cardinal; cdecl; external 'DOSCALLS' index 278;
  346. function DosQueryFileInfo (Handle: THandle; InfoLevel: cardinal;
  347. AFileStatus: PFileStatus; FileStatusLen: cardinal): cardinal; cdecl;
  348. external 'DOSCALLS' index 279;
  349. function DosScanEnv (Name: PChar; var Value: PChar): cardinal; cdecl;
  350. external 'DOSCALLS' index 227;
  351. function DosFindFirst (FileMask: PChar; var Handle: THandle; Attrib: cardinal;
  352. AFileStatus: PFileStatus; FileStatusLen: cardinal;
  353. var Count: cardinal; InfoLevel: cardinal): cardinal; cdecl;
  354. external 'DOSCALLS' index 264;
  355. function DosFindNext (Handle: THandle; AFileStatus: PFileStatus;
  356. FileStatusLen: cardinal; var Count: cardinal): cardinal; cdecl;
  357. external 'DOSCALLS' index 265;
  358. function DosFindClose (Handle: THandle): cardinal; cdecl;
  359. external 'DOSCALLS' index 263;
  360. function DosQueryCtryInfo (Size: cardinal; var Country: TCountryCode;
  361. var Res: TCountryInfo; var ActualSize: cardinal): cardinal; cdecl;
  362. external 'NLS' index 5;
  363. function DosMapCase (Size: cardinal; var Country: TCountryCode;
  364. AString: PChar): cardinal; cdecl; external 'NLS' index 7;
  365. procedure DosSleep (MSec: cardinal); cdecl; external 'DOSCALLS' index 229;
  366. function DosCreateQueue (var Handle: THandle; Priority:longint;
  367. Name: PChar): cardinal; cdecl;
  368. external 'QUECALLS' index 16;
  369. function DosReadQueue (Handle: THandle; var ReqBuffer: TRequestData;
  370. var DataLen: cardinal; var DataPtr: pointer;
  371. Element, Wait: cardinal; var Priority: byte;
  372. ASem: THandle): cardinal; cdecl;
  373. external 'QUECALLS' index 9;
  374. function DosCloseQueue (Handle: THandle): cardinal; cdecl;
  375. external 'QUECALLS' index 11;
  376. function DosStartSession (var AStartData: TStartData;
  377. var SesID, PID: cardinal): cardinal; cdecl;
  378. external 'SESMGR' index 37;
  379. function DosFreeMem(P:pointer):cardinal; cdecl; external 'DOSCALLS' index 304;
  380. {****************************************************************************
  381. File Functions
  382. ****************************************************************************}
  383. const
  384. ofRead = $0000; {Open for reading}
  385. ofWrite = $0001; {Open for writing}
  386. ofReadWrite = $0002; {Open for reading/writing}
  387. doDenyRW = $0010; {DenyAll (no sharing)}
  388. faCreateNew = $00010000; {Create if file does not exist}
  389. faOpenReplace = $00040000; {Truncate if file exists}
  390. faCreate = $00050000; {Create if file does not exist, truncate otherwise}
  391. FindResvdMask = $00003737; {Allowed bits in attribute
  392. specification for DosFindFirst call.}
  393. {$ASMMODE INTEL}
  394. function FileOpen (const FileName: pointer; Mode: integer): longint; assembler;
  395. asm
  396. push ebx
  397. {$IFDEF REGCALL}
  398. mov ecx, edx
  399. mov edx, eax
  400. {$ELSE REGCALL}
  401. mov ecx, Mode
  402. mov edx, FileName
  403. {$ENDIF REGCALL}
  404. (* DenyNone if sharing not specified. *)
  405. mov eax, ecx
  406. xor eax, 112
  407. jz @FOpenDefSharing
  408. cmp eax, 64
  409. jbe FOpen1
  410. @FOpenDefSharing:
  411. or ecx, 64
  412. @FOpen1:
  413. mov eax, 7F2Bh
  414. call syscall
  415. (* syscall __open() returns -1 in case of error, i.e. exactly what we need *)
  416. pop ebx
  417. end {['eax', 'ebx', 'ecx', 'edx']};
  418. function FileOpen (const FileName: rawbytestring; Mode: integer): longint;
  419. var
  420. SystemFileName: RawByteString;
  421. begin
  422. SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
  423. FileOpen := FileOpen(pointer(SystemFileName),Mode);
  424. end;
  425. function FileCreate (const FileName: RawByteString): longint;
  426. begin
  427. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW, 777);
  428. (* Sharing to DenyAll *)
  429. end;
  430. function FileCreate (const FileName: RawByteString; Rights: integer): longint;
  431. begin
  432. FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW,
  433. Rights); (* Sharing to DenyAll *)
  434. end;
  435. function FileCreate (const FileName: Pointer; ShareMode: integer; Rights: integer): longint; assembler;
  436. asm
  437. push ebx
  438. {$IFDEF REGCALL}
  439. mov ecx, edx
  440. mov edx, eax
  441. {$ELSE REGCALL}
  442. mov ecx, ShareMode
  443. mov edx, FileName
  444. {$ENDIF REGCALL}
  445. and ecx, 112
  446. or ecx, ecx
  447. jz @FCDefSharing
  448. cmp ecx, 64
  449. jbe @FCSharingOK
  450. @FCDefSharing:
  451. mov ecx, doDenyRW (* Sharing to DenyAll *)
  452. @FCSharingOK:
  453. or ecx, ofReadWrite or faCreate
  454. mov eax, 7F2Bh
  455. call syscall
  456. pop ebx
  457. end {['eax', 'ebx', 'ecx', 'edx']};
  458. function FileCreate (const FileName: RawByteString; ShareMode: integer; Rights: integer): longint;
  459. var
  460. SystemFileName: RawByteString;
  461. begin
  462. SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
  463. FileOpen := FileCreate(pointer(SystemFileName),ShareMode,Rights);
  464. end;
  465. function FileRead (Handle: longint; Out Buffer; Count: longint): longint;
  466. assembler;
  467. asm
  468. push ebx
  469. {$IFDEF REGCALL}
  470. mov ebx, eax
  471. {$ELSE REGCALL}
  472. mov ebx, Handle
  473. mov ecx, Count
  474. mov edx, Buffer
  475. {$ENDIF REGCALL}
  476. mov eax, 3F00h
  477. call syscall
  478. jnc @FReadEnd
  479. mov eax, -1
  480. @FReadEnd:
  481. pop ebx
  482. end {['eax', 'ebx', 'ecx', 'edx']};
  483. function FileWrite (Handle: longint; const Buffer; Count: longint): longint;
  484. assembler;
  485. asm
  486. push ebx
  487. {$IFDEF REGCALL}
  488. mov ebx, eax
  489. {$ELSE REGCALL}
  490. mov ebx, Handle
  491. mov ecx, Count
  492. mov edx, Buffer
  493. {$ENDIF REGCALL}
  494. mov eax, 4000h
  495. call syscall
  496. jnc @FWriteEnd
  497. mov eax, -1
  498. @FWriteEnd:
  499. pop ebx
  500. end {['eax', 'ebx', 'ecx', 'edx']};
  501. function FileSeek (Handle, FOffset, Origin: longint): longint; assembler;
  502. asm
  503. push ebx
  504. {$IFDEF REGCALL}
  505. mov ebx, eax
  506. mov eax, ecx
  507. {$ELSE REGCALL}
  508. mov ebx, Handle
  509. mov eax, Origin
  510. mov edx, FOffset
  511. {$ENDIF REGCALL}
  512. mov ah, 42h
  513. call syscall
  514. jnc @FSeekEnd
  515. mov eax, -1
  516. @FSeekEnd:
  517. pop ebx
  518. end {['eax', 'ebx', 'edx']};
  519. function FileSeek (Handle: longint; FOffset: Int64; Origin: longint): Int64;
  520. begin
  521. {$warning need to add 64bit call }
  522. Result:=FileSeek(Handle,Longint(Foffset),Longint(Origin));
  523. end;
  524. procedure FileClose (Handle: longint);
  525. begin
  526. if (Handle > 4) or ((os_mode = osOS2) and (Handle > 2)) then
  527. asm
  528. push ebx
  529. mov eax, 3E00h
  530. mov ebx, Handle
  531. call syscall
  532. pop ebx
  533. end ['eax'];
  534. end;
  535. function FileTruncate (Handle: THandle; Size: Int64): boolean; assembler;
  536. asm
  537. push ebx
  538. {$IFDEF REGCALL}
  539. mov ebx, eax
  540. {$ELSE REGCALL}
  541. mov ebx, Handle
  542. {$ENDIF REGCALL}
  543. mov edx, dword ptr Size
  544. mov eax, dword ptr Size+4
  545. or eax, eax
  546. mov eax, 0
  547. jz @FTruncEnd (* file sizes > 4 GB not supported with EMX *)
  548. mov eax, 7F25h
  549. push ebx
  550. call syscall
  551. pop ebx
  552. jc @FTruncEnd
  553. mov eax, 4202h
  554. mov edx, 0
  555. call syscall
  556. mov eax, 0
  557. jnc @FTruncEnd
  558. dec eax
  559. @FTruncEnd:
  560. pop ebx
  561. end {['eax', 'ebx', 'ecx', 'edx']};
  562. function FileAge (const FileName: string): longint;
  563. var Handle: longint;
  564. begin
  565. Handle := FileOpen (FileName, 0);
  566. if Handle <> -1 then
  567. begin
  568. Result := FileGetDate (Handle);
  569. FileClose (Handle);
  570. end
  571. else
  572. Result := -1;
  573. end;
  574. function FileExists (const FileName: RawByteString): boolean;
  575. var
  576. L: longint;
  577. begin
  578. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  579. if FileName = '' then
  580. Result := false
  581. else
  582. begin
  583. L := FileGetAttr (FileName);
  584. Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
  585. (* Neither VolumeIDs nor directories are files. *)
  586. end;
  587. end;
  588. type
  589. TRec = record
  590. T, D: word;
  591. end;
  592. PSearchRec = ^SearchRec;
  593. function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
  594. var
  595. SR: PSearchRec;
  596. FStat: PFileFindBuf3L;
  597. Count: cardinal;
  598. Err: cardinal;
  599. begin
  600. if os_mode = osOS2 then
  601. begin
  602. New (FStat);
  603. Rslt.FindHandle := THandle ($FFFFFFFF);
  604. Count := 1;
  605. if FSApi64 then
  606. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  607. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
  608. else
  609. Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
  610. Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
  611. if (Err = 0) and (Count = 0) then
  612. Err := 18;
  613. FindFirst := -Err;
  614. if Err = 0 then
  615. begin
  616. Rslt.ExcludeAttr := 0;
  617. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  618. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  619. if FSApi64 then
  620. begin
  621. Rslt.Size := FStat^.FileSize;
  622. Rslt.Name := FStat^.Name;
  623. Rslt.Attr := FStat^.AttrFile;
  624. end
  625. else
  626. begin
  627. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  628. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  629. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  630. end;
  631. end
  632. else
  633. FindClose (Rslt);
  634. Dispose (FStat);
  635. end
  636. else
  637. begin
  638. Err := DOS.DosError;
  639. GetMem (SR, SizeOf (SearchRec));
  640. Rslt.FindHandle := longint(SR);
  641. DOS.FindFirst (Path, Attr, SR^);
  642. FindFirst := -DOS.DosError;
  643. if DosError = 0 then
  644. begin
  645. Rslt.Time := SR^.Time;
  646. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  647. Rslt.Size := cardinal (SR^.Size);
  648. Rslt.Attr := SR^.Attr;
  649. Rslt.ExcludeAttr := 0;
  650. Rslt.Name := SR^.Name;
  651. end;
  652. DOS.DosError := Err;
  653. end;
  654. end;
  655. function FindNext (var Rslt: TSearchRec): longint;
  656. var
  657. SR: PSearchRec;
  658. FStat: PFileFindBuf3L;
  659. Count: cardinal;
  660. Err: cardinal;
  661. begin
  662. if os_mode = osOS2 then
  663. begin
  664. New (FStat);
  665. Count := 1;
  666. Err := DosFindNext (Rslt.FindHandle, FStat, SizeOf (FStat^), Count);
  667. if (Err = 0) and (Count = 0) then
  668. Err := 18;
  669. FindNext := -Err;
  670. if Err = 0 then
  671. begin
  672. Rslt.ExcludeAttr := 0;
  673. TRec (Rslt.Time).T := FStat^.TimeLastWrite;
  674. TRec (Rslt.Time).D := FStat^.DateLastWrite;
  675. if FSApi64 then
  676. begin
  677. Rslt.Size := FStat^.FileSize;
  678. Rslt.Name := FStat^.Name;
  679. Rslt.Attr := FStat^.AttrFile;
  680. end
  681. else
  682. begin
  683. Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
  684. Rslt.Name := PFileFindBuf3 (FStat)^.Name;
  685. Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
  686. end;
  687. end;
  688. Dispose (FStat);
  689. end
  690. else
  691. begin
  692. SR := PSearchRec (Rslt.FindHandle);
  693. if SR <> nil then
  694. begin
  695. DOS.FindNext (SR^);
  696. FindNext := -DosError;
  697. if DosError = 0 then
  698. begin
  699. Rslt.Time := SR^.Time;
  700. (* Extend the supported file sizes from 2 GB to 4 GB at least. *)
  701. Rslt.Size := cardinal (SR^.Size);
  702. Rslt.Attr := SR^.Attr;
  703. Rslt.ExcludeAttr := 0;
  704. Rslt.Name := SR^.Name;
  705. end;
  706. end;
  707. end;
  708. end;
  709. procedure FindClose (var F: TSearchrec);
  710. var SR: PSearchRec;
  711. begin
  712. if os_mode = osOS2 then
  713. begin
  714. DosFindClose (F.FindHandle);
  715. end
  716. else
  717. begin
  718. SR := PSearchRec (F.FindHandle);
  719. DOS.FindClose (SR^);
  720. FreeMem (SR, SizeOf (SearchRec));
  721. end;
  722. F.FindHandle := 0;
  723. end;
  724. function FileGetDate (Handle: longint): longint; assembler;
  725. asm
  726. push ebx
  727. {$IFDEF REGCALL}
  728. mov ebx, eax
  729. {$ELSE REGCALL}
  730. mov ebx, Handle
  731. {$ENDIF REGCALL}
  732. mov ax, 5700h
  733. call syscall
  734. mov eax, -1
  735. jc @FGetDateEnd
  736. mov ax, dx
  737. shld eax, ecx, 16
  738. @FGetDateEnd:
  739. pop ebx
  740. end {['eax', 'ebx', 'ecx', 'edx']};
  741. function FileSetDate (Handle, Age: longint): longint;
  742. var FStat: PFileStatus3;
  743. RC: cardinal;
  744. begin
  745. if os_mode = osOS2 then
  746. begin
  747. New (FStat);
  748. RC := DosQueryFileInfo (Handle, ilStandard, FStat,
  749. SizeOf (FStat^));
  750. if RC <> 0 then
  751. FileSetDate := -1
  752. else
  753. begin
  754. FStat^.DateLastAccess := Hi (Age);
  755. FStat^.DateLastWrite := Hi (Age);
  756. FStat^.TimeLastAccess := Lo (Age);
  757. FStat^.TimeLastWrite := Lo (Age);
  758. RC := DosSetFileInfo (Handle, ilStandard, FStat,
  759. SizeOf (FStat^));
  760. if RC <> 0 then
  761. FileSetDate := -1
  762. else
  763. FileSetDate := 0;
  764. end;
  765. Dispose (FStat);
  766. end
  767. else
  768. asm
  769. push ebx
  770. mov ax, 5701h
  771. mov ebx, Handle
  772. mov cx, word ptr [Age]
  773. mov dx, word ptr [Age + 2]
  774. call syscall
  775. jnc @FSetDateEnd
  776. mov eax, -1
  777. @FSetDateEnd:
  778. mov Result, eax
  779. pop ebx
  780. end ['eax', 'ecx', 'edx'];
  781. end;
  782. function FileGetAttr (const FileName: string): longint; assembler;
  783. asm
  784. {$IFDEF REGCALL}
  785. mov edx, eax
  786. {$ELSE REGCALL}
  787. mov edx, FileName
  788. {$ENDIF REGCALL}
  789. mov ax, 4300h
  790. call syscall
  791. jnc @FGetAttrEnd
  792. mov eax, -1
  793. @FGetAttrEnd:
  794. end {['eax', 'edx']};
  795. function FileSetAttr (const Filename: RawByteString; Attr: longint): longint;
  796. var
  797. SystemFileName: RawByteString;
  798. begin
  799. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  800. asm
  801. mov ecx, Attr
  802. mov edx, SystemFileName
  803. mov ax, 4301h
  804. call syscall
  805. mov @result, 0
  806. jnc @FSetAttrEnd
  807. mov @result, -1
  808. @FSetAttrEnd:
  809. end ['eax', 'ecx', 'edx'];
  810. end;
  811. function DeleteFile (const FileName: string): boolean;
  812. var
  813. SystemFileName: RawByteString;
  814. begin
  815. SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
  816. asm
  817. mov edx, SystemFileName
  818. mov ax, 4100h
  819. call syscall
  820. mov @result, 0
  821. jc @FDeleteEnd
  822. moc @result, 1
  823. @FDeleteEnd:
  824. end ['eax', 'edx'];
  825. end;
  826. function RenameFile (const OldName, NewName: string): boolean;
  827. var
  828. OldSystemFileName, NewSystemFileName: RawByteString;
  829. Begin
  830. OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
  831. NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
  832. asm
  833. mov edx, OldSystemFileName
  834. mov edi, NewSystemFileName
  835. mov ax, 5600h
  836. call syscall
  837. mov @result, 0
  838. jc @FRenameEnd
  839. mov @result, 1
  840. @FRenameEnd:
  841. end ['eax', 'edx', 'edi'];
  842. end;
  843. {****************************************************************************
  844. Disk Functions
  845. ****************************************************************************}
  846. {$ASMMODE ATT}
  847. function DiskFree (Drive: byte): int64;
  848. var FI: TFSinfo;
  849. RC: cardinal;
  850. begin
  851. if (os_mode = osDOS) or (os_mode = osDPMI) then
  852. {Function 36 is not supported in OS/2.}
  853. asm
  854. pushl %ebx
  855. movb Drive,%dl
  856. movb $0x36,%ah
  857. call syscall
  858. cmpw $-1,%ax
  859. je .LDISKFREE1
  860. mulw %cx
  861. mulw %bx
  862. shll $16,%edx
  863. movw %ax,%dx
  864. movl $0,%eax
  865. xchgl %edx,%eax
  866. jmp .LDISKFREE2
  867. .LDISKFREE1:
  868. cltd
  869. .LDISKFREE2:
  870. popl %ebx
  871. leave
  872. ret
  873. end
  874. else
  875. {In OS/2, we use the filesystem information.}
  876. begin
  877. RC := DosQueryFSInfo (Drive, 1, FI, SizeOf (FI));
  878. if RC = 0 then
  879. DiskFree := int64 (FI.Free_Clusters) *
  880. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  881. else
  882. DiskFree := -1;
  883. end;
  884. end;
  885. function DiskSize (Drive: byte): int64;
  886. var FI: TFSinfo;
  887. RC: cardinal;
  888. begin
  889. if (os_mode = osDOS) or (os_mode = osDPMI) then
  890. {Function 36 is not supported in OS/2.}
  891. asm
  892. pushl %ebx
  893. movb Drive,%dl
  894. movb $0x36,%ah
  895. call syscall
  896. movw %dx,%bx
  897. cmpw $-1,%ax
  898. je .LDISKSIZE1
  899. mulw %cx
  900. mulw %bx
  901. shll $16,%edx
  902. movw %ax,%dx
  903. movl $0,%eax
  904. xchgl %edx,%eax
  905. jmp .LDISKSIZE2
  906. .LDISKSIZE1:
  907. cltd
  908. .LDISKSIZE2:
  909. popl %ebx
  910. leave
  911. ret
  912. end
  913. else
  914. {In OS/2, we use the filesystem information.}
  915. begin
  916. RC := DosQueryFSinfo (Drive, 1, FI, SizeOf (FI));
  917. if RC = 0 then
  918. DiskSize := int64 (FI.Total_Clusters) *
  919. int64 (FI.Sectors_Per_Cluster) * int64 (FI.Bytes_Per_Sector)
  920. else
  921. DiskSize := -1;
  922. end;
  923. end;
  924. function GetCurrentDir: string;
  925. begin
  926. GetDir (0, Result);
  927. end;
  928. function SetCurrentDir (const NewDir: string): boolean;
  929. begin
  930. {$I-}
  931. ChDir (NewDir);
  932. Result := (IOResult = 0);
  933. {$I+}
  934. end;
  935. function CreateDir (const NewDir: string): boolean;
  936. begin
  937. {$I-}
  938. MkDir (NewDir);
  939. Result := (IOResult = 0);
  940. {$I+}
  941. end;
  942. function RemoveDir (const Dir: string): boolean;
  943. begin
  944. {$I-}
  945. RmDir (Dir);
  946. Result := (IOResult = 0);
  947. {$I+}
  948. end;
  949. function DirectoryExists (const Directory: RawByteString): boolean;
  950. var
  951. L: longint;
  952. begin
  953. { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
  954. if Directory = '' then
  955. Result := false
  956. else
  957. begin
  958. if ((Length (Directory) = 2) or
  959. (Length (Directory) = 3) and
  960. (Directory [3] in AllowDirectorySeparators)) and
  961. (Directory [2] in AllowDriveSeparators) and
  962. (UpCase (Directory [1]) in ['A'..'Z']) then
  963. (* Checking attributes for 'x:' is not possible but for 'x:.' it is. *)
  964. L := FileGetAttr (Directory + '.')
  965. else if (Directory [Length (Directory)] in AllowDirectorySeparators) and
  966. (Length (Directory) > 1) and
  967. (* Do not remove '\' in '\\' (invalid path, possibly broken UNC path). *)
  968. not (Directory [Length (Directory) - 1] in AllowDirectorySeparators) then
  969. L := FileGetAttr (Copy (Directory, 1, Length (Directory) - 1))
  970. else
  971. L := FileGetAttr (Directory);
  972. Result := (L > 0) and (L and faDirectory = faDirectory);
  973. end;
  974. end;
  975. {****************************************************************************
  976. Time Functions
  977. ****************************************************************************}
  978. {$ASMMODE INTEL}
  979. procedure GetLocalTime (var SystemTime: TSystemTime); assembler;
  980. asm
  981. (* Expects the default record alignment (word)!!! *)
  982. push edi
  983. {$IFDEF REGCALL}
  984. push eax
  985. {$ENDIF REGCALL}
  986. mov ah, 2Ah
  987. call syscall
  988. {$IFDEF REGCALL}
  989. pop eax
  990. {$ELSE REGCALL}
  991. mov edi, SystemTime
  992. {$ENDIF REGCALL}
  993. mov ax, cx
  994. stosw
  995. xor eax, eax
  996. mov al, 10
  997. mul dl
  998. shl eax, 16
  999. mov al, dh
  1000. stosd
  1001. push edi
  1002. mov ah, 2Ch
  1003. call syscall
  1004. pop edi
  1005. xor eax, eax
  1006. mov al, cl
  1007. shl eax, 16
  1008. mov al, ch
  1009. stosd
  1010. mov al, dl
  1011. shl eax, 16
  1012. mov al, dh
  1013. stosd
  1014. pop edi
  1015. end {['eax', 'ecx', 'edx', 'edi']};
  1016. {$asmmode default}
  1017. {****************************************************************************
  1018. Misc Functions
  1019. ****************************************************************************}
  1020. procedure Beep;
  1021. begin
  1022. end;
  1023. {****************************************************************************
  1024. Locale Functions
  1025. ****************************************************************************}
  1026. procedure InitAnsi;
  1027. var I: byte;
  1028. Country: TCountryCode;
  1029. begin
  1030. for I := 0 to 255 do
  1031. UpperCaseTable [I] := Chr (I);
  1032. Move (UpperCaseTable, LowerCaseTable, SizeOf (UpperCaseTable));
  1033. if os_mode = osOS2 then
  1034. begin
  1035. FillChar (Country, SizeOf (Country), 0);
  1036. DosMapCase (SizeOf (UpperCaseTable), Country, @UpperCaseTable);
  1037. end
  1038. else
  1039. begin
  1040. (* !!! TODO: DOS/DPMI mode support!!! *)
  1041. end;
  1042. for I := 0 to 255 do
  1043. if UpperCaseTable [I] <> Chr (I) then
  1044. LowerCaseTable [Ord (UpperCaseTable [I])] := Chr (I);
  1045. end;
  1046. procedure InitInternational;
  1047. var Country: TCountryCode;
  1048. CtryInfo: TCountryInfo;
  1049. Size: cardinal;
  1050. RC: cardinal;
  1051. begin
  1052. Size := 0;
  1053. FillChar (Country, SizeOf (Country), 0);
  1054. FillChar (CtryInfo, SizeOf (CtryInfo), 0);
  1055. RC := DosQueryCtryInfo (SizeOf (CtryInfo), Country, CtryInfo, Size);
  1056. if RC = 0 then
  1057. begin
  1058. DateSeparator := CtryInfo.DateSeparator;
  1059. case CtryInfo.DateFormat of
  1060. 1: begin
  1061. ShortDateFormat := 'd/m/y';
  1062. LongDateFormat := 'dd" "mmmm" "yyyy';
  1063. end;
  1064. 2: begin
  1065. ShortDateFormat := 'y/m/d';
  1066. LongDateFormat := 'yyyy" "mmmm" "dd';
  1067. end;
  1068. 3: begin
  1069. ShortDateFormat := 'm/d/y';
  1070. LongDateFormat := 'mmmm" "dd" "yyyy';
  1071. end;
  1072. end;
  1073. TimeSeparator := CtryInfo.TimeSeparator;
  1074. DecimalSeparator := CtryInfo.DecimalSeparator;
  1075. ThousandSeparator := CtryInfo.ThousandSeparator;
  1076. CurrencyFormat := CtryInfo.CurrencyFormat;
  1077. CurrencyString := PChar (CtryInfo.CurrencyUnit);
  1078. end;
  1079. InitAnsi;
  1080. InitInternationalGeneric;
  1081. end;
  1082. function SysErrorMessage(ErrorCode: Integer): String;
  1083. begin
  1084. Result:=Format(SUnknownErrorCode,[ErrorCode]);
  1085. end;
  1086. {****************************************************************************
  1087. OS Utils
  1088. ****************************************************************************}
  1089. Function GetEnvironmentVariable(Const EnvVar : String) : String;
  1090. begin
  1091. GetEnvironmentVariable := GetEnvPChar (EnvVar);
  1092. end;
  1093. Function GetEnvironmentVariableCount : Integer;
  1094. begin
  1095. (* Result:=FPCCountEnvVar(EnvP); - the amount is already known... *)
  1096. GetEnvironmentVariableCount := EnvC;
  1097. end;
  1098. Function GetEnvironmentString(Index : Integer) : String;
  1099. begin
  1100. Result:=FPCGetEnvStrFromP (EnvP, Index);
  1101. end;
  1102. {$ASMMODE INTEL}
  1103. procedure Sleep (Milliseconds: cardinal);
  1104. begin
  1105. if os_mode = osOS2 then DosSleep (Milliseconds) else
  1106. asm
  1107. mov edx, Milliseconds
  1108. mov eax, 7F30h
  1109. call syscall
  1110. end ['eax', 'edx'];
  1111. end;
  1112. {$ASMMODE DEFAULT}
  1113. function ExecuteProcess (const Path: AnsiString; const ComLine: AnsiString;Flags:TExecuteFlags=[]):
  1114. integer;
  1115. var
  1116. HQ: THandle;
  1117. SPID, STID, QName: shortstring;
  1118. SD: TStartData;
  1119. SID, PID: cardinal;
  1120. RD: TRequestData;
  1121. PCI: PChildInfo;
  1122. CISize: cardinal;
  1123. Prio: byte;
  1124. E: EOSError;
  1125. CommandLine: ansistring;
  1126. begin
  1127. if os_Mode = osOS2 then
  1128. begin
  1129. FillChar (SD, SizeOf (SD), 0);
  1130. SD.Length := 24;
  1131. SD.Related := ssf_Related_Child;
  1132. SD.PgmName := PChar (Path);
  1133. SD.PgmInputs := PChar (ComLine);
  1134. Str (GetProcessID, SPID);
  1135. Str (ThreadID, STID);
  1136. QName := '\QUEUES\FPC_ExecuteProcess_p' + SPID + 't' + STID + '.QUE'#0;
  1137. SD.TermQ := @QName [1];
  1138. Result := DosCreateQueue (HQ, quFIFO or quConvert_Address, @QName [1]);
  1139. if Result = 0 then
  1140. begin
  1141. Result := DosStartSession (SD, SID, PID);
  1142. if (Result = 0) or (Result = 457) then
  1143. begin
  1144. Result := DosReadQueue (HQ, RD, CISize, PCI, 0, 0, Prio, 0);
  1145. if Result = 0 then
  1146. begin
  1147. Result := PCI^.Return;
  1148. DosCloseQueue (HQ);
  1149. DosFreeMem (PCI);
  1150. Exit;
  1151. end;
  1152. end;
  1153. DosCloseQueue (HQ);
  1154. end;
  1155. if ComLine = '' then
  1156. CommandLine := Path
  1157. else
  1158. CommandLine := Path + ' ' + ComLine;
  1159. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, Result]);
  1160. E.ErrorCode := Result;
  1161. raise E;
  1162. end else
  1163. begin
  1164. Dos.Exec (Path, ComLine);
  1165. if DosError <> 0 then
  1166. begin
  1167. if ComLine = '' then
  1168. CommandLine := Path
  1169. else
  1170. CommandLine := Path + ' ' + ComLine;
  1171. E := EOSError.CreateFmt (SExecuteProcessFailed, [CommandLine, DosError]);
  1172. E.ErrorCode := DosError;
  1173. raise E;
  1174. end;
  1175. ExecuteProcess := DosExitCode;
  1176. end;
  1177. end;
  1178. function ExecuteProcess (const Path: AnsiString;
  1179. const ComLine: array of AnsiString;Flags:TExecuteFlags=[]): integer;
  1180. var
  1181. CommandLine: AnsiString;
  1182. I: integer;
  1183. begin
  1184. Commandline := '';
  1185. for I := 0 to High (ComLine) do
  1186. if Pos (' ', ComLine [I]) <> 0 then
  1187. CommandLine := CommandLine + ' ' + '"' + ComLine [I] + '"'
  1188. else
  1189. CommandLine := CommandLine + ' ' + Comline [I];
  1190. ExecuteProcess := ExecuteProcess (Path, CommandLine);
  1191. end;
  1192. {****************************************************************************
  1193. Initialization code
  1194. ****************************************************************************}
  1195. Initialization
  1196. InitExceptions; { Initialize exceptions. OS independent }
  1197. InitInternational; { Initialize internationalization settings }
  1198. Finalization
  1199. DoneExceptions;
  1200. end.