home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / edmi3.zip / EDMI3.INF (.txt) < prev    next >
OS/2 Help File  |  1993-05-31  |  160KB  |  2,416 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Title Page ΓòÉΓòÉΓòÉ
  3.  
  4.           Welcome to EDM/2 - The Electronic OS/2 Developers' Magazine!.
  5.  
  6.                   Portions Copyright (C)1993 by Steve Luzynski.
  7.  
  8.                             Issue #3 - May/June 1993.
  9.  
  10.                            (Press 'Forward' to page.)
  11.  
  12.  
  13. ΓòÉΓòÉΓòÉ 2. Copyright Notice and other Legal Stuff ΓòÉΓòÉΓòÉ
  14.  
  15. EDM/2 Copyright (C)1993 by Steve Luzynski. This publication may be freely 
  16. distributed in electronic form provided that all parts are present in their 
  17. original unmodified form. A reasonable fee may be charged for the physical act 
  18. of distribution; no fee may be charged for the publication itself. 
  19.  
  20. All articles are copyrighted by their authors. No part of any article may be 
  21. reproduced without permission from the original author. 
  22.  
  23. Neither this publication nor Steve Luzynski is affiliated with International 
  24. Business Machines Corporation. 
  25.  
  26. OS/2 is a registered trademark of International Business Machines Corporation. 
  27. Other trademarks are property of their respective owners. Any mention of a 
  28. product in this publication does not constitute an endorsement or affiliation 
  29. unless specifically stated in the text. 
  30.  
  31.  
  32. ΓòÉΓòÉΓòÉ 3. From the Editor ΓòÉΓòÉΓòÉ
  33.  
  34.  Well, EDM/2 has finally made it to its third issue! You've probably noticed 
  35. that this issue says 'May/June' on it - that's because I ran out of time to do 
  36. separate issues for each month. I'm back on schedule now, though. 
  37.  
  38. This month, I happened upon an interesting little piece of software: 
  39.  
  40. The Microsoft Upgrade Advisor 
  41.  
  42. This is a free advertising tool MS has come up with to hype DOS 6.0 and 
  43. Windows. Oddly enough, you must have at least Windows 3.0 to run it.  No 
  44. problem - A double-click from the OS/2 drives object, and it started up. 
  45.  
  46. After a few screens worth of stuff, it noted that I have OS/2 2.0 on my system. 
  47. It recommended that I 'upgrade' my 32 bit multitasking OS with DOS 6 + Windows 
  48. 3.1. Obviously I'd want to drop back down to an 8 bit OS with a cute graphical 
  49. shell. 
  50.  
  51. My point in bringing this up was not to trash MS in any way (although that's 
  52. sometimes fun too). Instead, it got me thinking about what they're doing. While 
  53. IBM does have an OS/2 demo disk out, I would never have seen it had I not been 
  54. poking around on Internet. On the other hand, I have 3 MS Upgrade Advisors. 
  55.  
  56. Getting three free high-density disks wasn't bad, of course, but I am a bit 
  57. distressed to find that IBM isn't throwing their disk out in the quantities MS 
  58. is. Perhaps if IBM started pushing OS/2 as hard as MS pushes Windows, I might 
  59. be able to walk into a Babbage's or an Egghead and be able to pick DeScribe up 
  60. off of the shelf. 
  61.  
  62. In other news... 
  63.  
  64. Starting with the next issue, I hope to have a new column. The idea is this: 
  65. Each month, you, the readers, write up reivews of your favorite pieces of OS/2 
  66. development software. This can be any native OS/2 program, be it PM or text 
  67. mode. Originally, I was going to limit it to public domain tools, but I see no 
  68. reason to exclude commercial tools. After all, for upwards of 400 dollars in 
  69. most cases, I'd like to hear from someone else who has used a particular 
  70. program before I buy it. 
  71.  
  72. At any rate, Larry Salomon and I will go through your articles and select which 
  73. ones get in to EDM/2. (Chances are that almost all of them will.) Here's yet 
  74. another chance to get your name up in lights! 
  75.  
  76. Submissions can be in either .IPF format or plain ascii, and can be sent to 
  77. either os2man@panix.com (Larry) or sal8@po.cwru.edu (myself). I will be getting 
  78. back on schedule after this month, so for the July issue I'd like your 
  79. submissions no later than June 25th. 
  80.  
  81. Submissions 
  82.  
  83. Once again, I'd like to remind you all that I'm always in the market for 
  84. articles for EDM/2. No topic is too broad or too focused to not be of interest 
  85. to someone out there. 
  86.  
  87. I prefer submissions in .IPF format, but if you don't know how to create an 
  88. .IPF file, plain ASCII is fine as well. The rules go like this: 
  89.  
  90. For .IPF format submissions, your article should start at a heading level of 
  91. three. This is because the table of contents is at level one and the cover 
  92. panel (with the EDM/2 logo, article title, and author's name) is at level two. 
  93. This means that when you are writing your article, you'll need to include dummy 
  94. :h1 and :h2 panels. 
  95.  
  96. Beyond that, do what you want. You can either write an elaborate article with 
  97. hotlinks to glossary items and animated example windows, or just stick with a 
  98. straightforward series of panels. 
  99.  
  100. For ASCII format submissions, there are a few things that make my life a lot 
  101. simpler. First, since the .IPF tagging language uses colons to tell the 
  102. compiler that something is a command, colons should be represented as '&colon.' 
  103. rather than ':'. For the same reason, ampersands should be '&.' rather than 
  104. '&'. 
  105.  
  106. Next, each new paragraph should start with ':p.'. This indicates to the IPF 
  107. compiler that it should start a new line. Any place you would like to put 
  108. special emphasis on a word or phrase, place asterisks (*) around the text. You 
  109. should also indicate what kind of emphasis you want: bold, italics, 
  110. underlining, or a combination of the three. 
  111.  
  112. All submissions should come with a brief blurb describing the author. See the 
  113. 'Contributors' section for several examples of what it should look like. 
  114.  
  115. If you already have a piece you'd be willing to contribute, but don't want to 
  116. rework, contact me anyway and I'll arrange to convert your article for you. 
  117. Please note that: 1) I really hate doing it; and 2) I'll have to have your 
  118. article early so I have time to do the conversion. For example, converting 
  119. Andre's article on Installable File Systems in this issue from Word for Windows 
  120. format into what you see took me almost 3 hours! 
  121.  
  122. Anyway... 
  123.  
  124. In the future, I hope to include some how-to columns on using the help compiler 
  125. (.IPF files can compile to either .INF or .HLP files). For now, I'm including 
  126. in this issue's sample code both my editorial and the 'base' file for this 
  127. issue. While you won't be able to compile them directly without some reworking, 
  128. it should give you an idea of how to proceed. 
  129.  
  130. Steve Luzynski, Editor. 
  131.  
  132.  
  133. ΓòÉΓòÉΓòÉ 4. This Month's Features ΓòÉΓòÉΓòÉ
  134.  
  135. o Dos Development Tools Under OS/2 
  136.  
  137. o OS/2 Installable File Systems - Part 1 
  138.  
  139. o Programming the Container Control - Part 1 
  140.  
  141.  
  142. ΓòÉΓòÉΓòÉ 4.1. Dos Development Tools Under OS/2 ΓòÉΓòÉΓòÉ
  143.  
  144.                               DOS Development Tools
  145.                                       Under
  146.                                       OS/2
  147.  
  148.                                 Charles R. Oldham
  149.                             (cro@socrates.ed.asu.edu)
  150.  
  151.  
  152. ΓòÉΓòÉΓòÉ 4.1.1. Introduction ΓòÉΓòÉΓòÉ
  153.  
  154. In this new age of interoperability, OS/2 has been billed by the marketing 
  155. types as the Integrating Platform.  "Run your Windows, Dos, and OS/2 
  156. applications on one machine!  Preserve your existing investment in Dos and 
  157. Windows software--upgrade only when you are ready!" they cry.  Well, for a 
  158. change, the marketing people are on the right track.  OS/2 is indeed the 
  159. Integrating Platform, but there are far more advantages for the developer than 
  160. there are for the user. 
  161.  
  162. For the first time developers have the ability to write software for two 
  163. different operating systems and three different operating environments: Dos, 
  164. Windows, and OS/2 PM (four if you count OS/2 text mode programs).  And we can 
  165. do it all from one machine that hosts a multitasking, multithreaded, 
  166. protected-mode operating system.  Unlike systems that support cross-compilers, 
  167. we are also able to test these applications to a great extent, using the Dos 
  168. and WinOS /2 subsystems of OS/2 2.x. 
  169.  
  170. Developers are faced with a difficult question when a transition to a new 
  171. operating system is possible: 
  172.  
  173. o How can I get the work done that I did before, but still utilize the full 
  174.   potential of the Operating System? 
  175.  
  176. Frustration is a real possibility in a situation like this.  The developer may 
  177. discover after a few hours or days of programming that running a Borland IDE in 
  178. a Dos fullscreen session is still a lot like running Dos! 
  179.  
  180. Though we seem to have all of OS/2's power at our fingertips, having to use Dos 
  181. tools to develop Dos programs limits us somewhat.  Dos tools are not 
  182. multitasking or multithreaded; they do not understand filenames that are not in 
  183. the 8.3 format; interprocess communication is almost nonexistent, or at best 
  184. limited due to the fact that Dos understands only the single process. 
  185.  
  186. It is reasonable to conclude, therefore, that we would like to minimize our 
  187. contact with Dos tools, and maximize the number of OS/2 based tools that we 
  188. would use to get our work done.  Unfortunately, some tools, like compilers, in 
  189. tegrated development environments, and especially debuggers, are irreplaceable. 
  190.  
  191. The question then becomes 
  192.  
  193. o How can I minimize my contact with Dos while still utilizing my irreplaceable 
  194.   tools? 
  195.  
  196.  
  197. ΓòÉΓòÉΓòÉ 4.1.2. DPipeLn ΓòÉΓòÉΓòÉ
  198.  
  199. Origins, Usage, and Internal Structure 
  200.  
  201.  
  202. ΓòÉΓòÉΓòÉ 4.1.2.1. Origin ΓòÉΓòÉΓòÉ
  203.  
  204. The Origin of DPipeLn 
  205.  
  206. The utility called DPipeLn was created because when developing for Dos, I 
  207. tended to find myself using a Dos box all day.  This frustrated me because I 
  208. felt like I wasn't using the abilities of OS/2.  Also, though I like Borland's 
  209. Integrated Development Environments, I find them somewhat cumbersome for large 
  210. projects, and I wanted to be able to use the more advanced utilities like 
  211. NMake, Gnu Make, and the other Gnu programming utilities that are rapidly being 
  212. ported to OS/2.  I thought about my requirements and realized that it was 
  213. probably possible to write an OS/2 utility that would start a Dos session 
  214. transparently, run the appropriate command, and pipe the results back into the 
  215. OS/2 session. 
  216.  
  217. This I did, and DPipeLn is the result. 
  218.  
  219. dpipeln [-v] [-f] [-sdos_settings_filename] [-ttemp_dir_name] dos_command
  220.         -v: Start Dos session visible
  221.         -s: Specify file to get Dos Settings from
  222.         -f: Start Dos session in the foreground
  223.         -t: Specify location of temporary files
  224.  
  225. Now it is possible to call any Dos command-line based tool from an OS/2 prompt, 
  226. and to see the results as if it was executed as a native OS/2 command.  Dos 
  227. programs can become part of pipelines (though the program must be at the head 
  228. of the command line because input is not fed to the Dos program), they can be 
  229. called from OS/2 based Make utilities, even from IBM's WorkFrame/2! 
  230.  
  231. DPipeLn even passes return codes back from a terminated Dos program.  This is 
  232. essential to allow make utilities to operate correctly. 
  233.  
  234.  
  235. ΓòÉΓòÉΓòÉ 4.1.2.2. Internals ΓòÉΓòÉΓòÉ
  236.  
  237. DPipeLn Internals 
  238.  
  239. DPipeLn was developed with the excellent EMX/GCC development system by Eberhard 
  240. Mattes.  It is a standalone program; it contains none of the library calls that 
  241. require emx.dll or emxlibc.dll. 
  242.  
  243. The executable itself and the kit that contains the files needed to build 
  244. DPipeLn can be found in the Zips/ directory that accompanies this issue of 
  245. EDM/2. 
  246.  
  247.  
  248. ΓòÉΓòÉΓòÉ 4.1.2.3. Program Flow ΓòÉΓòÉΓòÉ
  249.  
  250. DPipeLn Program Flow 
  251.  
  252. Here is what happens when DPipeLn is executed: 
  253.  
  254.  1. Stdout is forced into binary mode. 
  255.  
  256.  2. The command line is processed.  Several variables that control program 
  257.     operation are set. 
  258.  
  259.  3. The named pipe used for transferring the stdout (and stderr when 4Dos is in 
  260.     use) is created. 
  261.  
  262.  4. The named pipe used for transferring the Dos program return code is 
  263.     created. 
  264.  
  265.  5. The StartData structure, which is used by DosStartSession() OS/2 API 
  266.     function, is populated with the proper data. 
  267.  
  268.  6. The auxiliary batch file is created.  DosStartSession actually calls the 
  269.     Dos command processor and instructs it to execute this batch file.  The 
  270.     contents will be explained when this function is reviewed. 
  271.  
  272.  7. DPipeLn executes the DosStartSession call.  The Dos program runs 
  273.     asynchronously. 
  274.  
  275.  8. A separate thread is initiated that waits for the return code from the Dos 
  276.     program. 
  277.  
  278.  9. DPipeLn connects to the Dos stdout pipe and prints out data that is fed by 
  279.     the Dos program through the pipe. 
  280.  
  281. 10. We wait for the return code thread to complete.  When it is complete, we 
  282.     know the Dos program is complete and we set DPipeLn's return code to be the 
  283.     same as the Dos return code. 
  284.  
  285. 11. Malloc'ed memory is freed and the named pipes are disconnected. 
  286.  
  287. 12. DPipeLn exits with the return code previously set. 
  288.  
  289.  
  290. ΓòÉΓòÉΓòÉ 4.1.2.4. DPipeLn.c ΓòÉΓòÉΓòÉ
  291.  
  292. This portion of the article is intended to be an introduction to the relevant 
  293. portions of the OS/2 API.  If you are already familiar with the Named Pipe API, 
  294. the Session API, and the Thread API, you will probably find it more worth your 
  295. while to examine DPipeLn's source code directly to learn about the internals. 
  296.  
  297.  
  298. ΓòÉΓòÉΓòÉ 4.1.2.5. #defines, #includes, and Global Variables ΓòÉΓòÉΓòÉ
  299.  
  300. DPipeLn.c 
  301.  
  302. #define INCL_DOSSESMGR    /* Session Manager values */
  303. #define INCL_DOS          /* DOS Calls (not MS-DOS) */
  304. #define INCL_DOSNMPIPES   /* Named Pipe Support */
  305. #define INCL_DOSPROCESS   /* Process IDs */
  306. #define INCL_DOSQUEUES    /* Queue support */
  307.  
  308. Since the OS/2 header files are so big, there are #ifdefs throughout them that 
  309. allow you to tell the compiler only which sections you would like included. 
  310. DPipeLn needs to use these sections. 
  311.  
  312. #define BUFSIZE 80        /* Pipe buffer size */
  313. #define SETSIZE 4096      /* Dos settings maximum size */
  314.  
  315. Like the comments say, make symbolic constants for the named pipe buffer size, 
  316. and the size of the Dos settings structure. 
  317.  
  318. #define new_string(x) ((char *)malloc((x) + 1))
  319. #define freemem(x) if ((x) != NULL) free((x))
  320.  
  321. Macros to make string creation and memory release a little easier. 
  322.  
  323. #define USING_4DOS
  324.  
  325. When compiling the software, #define this if you are using the 4Dos command 
  326. processor replacement.  The reason for this will be discussed later in the 
  327. article. 
  328.  
  329. #include <os2.h>
  330. #include <stdio.h>
  331. #include <string.h>
  332. #include <ctype.h>
  333. #include <stdlib.h>
  334.  
  335. #include the header files that we need. 
  336.  
  337. The following are the function prototypes for the program.  I'm including them 
  338. here with a description of what they all do because I won't show and describe 
  339. the internals of each function--only the interesting ones. 
  340.  
  341. PBYTE get_dos_settings(char *file);
  342.  
  343. Read in the Dos settings file.  The Dos settings file lets the user describe 
  344. the settings for the Dos session that the indicated program will be run in. 
  345. The format of the settings file is documented later in this article. 
  346.  
  347. char *get_basename();
  348.  
  349. Creates a base name for the named pipes and auxiliary batch file out of the PID 
  350. of the DPipeLn process.  The function allocates a string which is freed at the 
  351. termination of the program. 
  352.  
  353. char *make_npipename(char *PQbasename);
  354.  
  355. Takes the passed string and makes an appropriate name for the named pipe 
  356. through which the Dos session will communicate with the OS/2 session. 
  357.  
  358. char *make_batname(char *base, char *tempdir);
  359.  
  360. Makes the auxiliary batch file name.  The function returns a fully-qualified 
  361. path. 
  362.  
  363. int build_batchfile(char *Batname, char *Errpname, char *Command);
  364.  
  365. Builds the auxiliary batch file.  Returns FALSE if the build failed. 
  366.  
  367. void process_cmdline(int argc, char *argv[]);
  368.  
  369. Processes all the command line switches and sets appropriate global variables 
  370. that control the program flow. 
  371.  
  372. void usage();
  373.  
  374. Prints a usage message, calls cleanup(), then exits. 
  375.  
  376. void cleanup();
  377.  
  378. Frees allocated memory and disconnects named pipes. 
  379.  
  380. char *get_exename(char *arg);
  381.  
  382. Strips the path off of argv[0] to make an executable name out of it.  Returns a 
  383. character string containing just the name by which DPipeLn was executed.  The 
  384. string is used when reporting errors. 
  385.  
  386. void setup_startdata();
  387.  
  388. DPipeLn calls the OS/2 API function DosStartSession() to create the Dos session 
  389. in which the Dos command is run.  DosStartSession() takes a struct called 
  390. STARTDATA.  This function puts the proper data in the struct. 
  391.  
  392. void transfer_data(HPIPE *piphand);
  393.  
  394. This function reads the data from the named pipe that is connected to the Dos 
  395. programs stdout (and stderr if 4Dos is the command processor). 
  396.  
  397. void read_errpipe();
  398.  
  399. This function reads the data from the named pipe that is connected to the 
  400. "echo" command in the auxiliary batch file.  It runs in a separate thread and 
  401. collects the return code from the Dos program. 
  402.  
  403. char *make_rcdname(char *base);
  404.  
  405. We need a name for the named pipe that transfers the return code from the Dos 
  406. session.  make_rcdname creates a character string that contains the name. 
  407.  
  408. char *get_tempdir();
  409.  
  410. Scans the environment looking for a suitable temporary directory name.  This 
  411. directory will hold the auxiliary batch file.  get_tempdir() returns a 
  412. character string with the dirname in it. 
  413.  
  414. Now, global variables: 
  415.  
  416. PSZ    PgmTitle = NULL;    /* Title of window in which Dos program will execute */
  417. PSZ    PgmCmdLine = NULL;  /* Command line for Dos program */
  418. PSZ    PgmSettingsFile = NULL;    /* File containing DOS settings */
  419. PSZ    Exename = NULL;     /* DPipeLn Executable name */
  420. UCHAR  ObjBuf[100];        /* Object buffer.  Used by DosStartSession */
  421. PSZ    Command;            /* The actual DOS command to be executed */
  422. PSZ    Errpname;           /* Name of the pipe that contains the return code */
  423. HPIPE  Piphand, Rcdpipe;   /* Named Pipe handles */
  424. int    Opt_visible;        /* Run DOS session invisibly */
  425. int    Opt_settings;       /* DOS session has a settings file */
  426. int    Opt_foreground;     /* Run session in foreground */
  427. char   *PQbasename;        /* Unique name for the named pipe */
  428. char   *Pname;             /* Fully qualified path for named pipe */
  429. char   *Batname;           /* Unique name of the batch file */
  430. ULONG  OwningPID;          /* PID of dpipeln.exe */
  431. char   RCstring[BUFSIZE];  /* String to temporarily hold ret code from DOS program */
  432. char   *Tempdir = NULL;    /* temporary directory in which to put batch file */
  433.  
  434.  
  435. ΓòÉΓòÉΓòÉ 4.1.2.5.1. main() ΓòÉΓòÉΓòÉ
  436.  
  437. On to the main program.  I'll leave out the local variables and only mention 
  438. them when pertinent.  Also, I won't cover each and every statement.  Most are 
  439. documented thoroughly within the code if you are interested. 
  440.  
  441. USHORT main(int argc, char *argv[]) {
  442.  
  443. Standard stuff. 
  444.  
  445. if (_fsetmode(stdout, "b") == -1) {
  446.   fprintf(stderr, "Could not set stdout to binary mode.\n");
  447.   exit(-1);
  448. }
  449.  
  450. Set stdout to binary mode.  This is necessary because when stdout is in text 
  451. mode, EMX converts \n to \r\n on output.  This helps when porting applications 
  452. from Unix to OS/2, but is not desired behavior here. 
  453.  
  454. PQbasename = get_basename();
  455. Pname = make_npipename(PQbasename);
  456. Errpname = make_rcdname(PQbasename);
  457. Batname = make_batname(PQbasename, Tempdir);
  458.  
  459. Now we create unique names for the pipe through which the Dos program will send 
  460. it's output, the pipe that will transfer the return code from the Dos program, 
  461. and the auxiliary batch file.  All the variables will contain fully qualified 
  462. paths to the referenced resources. 
  463.  
  464. rc = DosCreateNPipe(Pname,
  465.       &Piphand,
  466.       NP_ACCESS_DUPLEX,
  467.        NP_WAIT ||
  468.        NP_TYPE_MESSAGE ||
  469.        NP_READMODE_BYTE ||
  470.        NP_UNLIMITED_INSTANCES,
  471.       outbuffer, inbuffer, timeout);
  472. rc = DosCreateNPipe(Errpname,
  473.       &Rcdpipe,
  474.       NP_ACCESS_DUPLEX,
  475.        NP_WAIT ||
  476.        NP_TYPE_MESSAGE ||
  477.        NP_READMODE_BYTE ||
  478.        NP_UNLIMITED_INSTANCES,
  479.       outbuffer, inbuffer, timeout);
  480.  
  481. Important part--create the named pipes.  The variables refer to the following: 
  482.  
  483. Pname, Errpname 
  484.           The names of the pipes. 
  485.  
  486. Piphand, Rcdpipe 
  487.           The OS/2 programming reference calls these "Pipe Handles".  These 
  488.           were defined in the global variable section, and the API takes 
  489.           addresses to them.  The API function then populates them with the 
  490.           proper data so they will refer to the named pipe. 
  491.  
  492. NP_ACCESS_DUPLEX 
  493.           These will be duplex (two-way) pipes.  For some reason, I was unable 
  494.           to get them to function as one-way pipes. 
  495.  
  496. NP_WAIT 
  497.           Open the pipe in blocking mode, i.e. DosRead and DosWrite block if 
  498.           there is no data available. 
  499.  
  500. NP_TYPE_MESSAGE 
  501.           Data is written to the pipe as a stream of messages, as opposed to a 
  502.           stream of bytes (NP_TYPE_BYTE). 
  503.  
  504. NP_READMODE_BYTE 
  505.           Data is read from the pipe as a stream of bytes. 
  506.  
  507. NP_UNLIMITED_INSTANCES 
  508.           There is no limit on the number of instances of this pipe.  This 
  509.           parameter doesn't really matter, as we know there will always be no 
  510.           more than one of each of these pipes (since the names are unique). 
  511.  
  512. outbuffer, inbuffer, timeout 
  513.           These local variables set the size of the output and input buffers 
  514.           for the pipes, and set the default amount of time DosWaitNPipe will 
  515.           wait for a pipe to become available. 
  516.  
  517. setup_startdata(&sd);
  518.  
  519. DosStartSession takes a special parameter--a pointer to what is called the 
  520. StartData structure.  It contains members that define the different 
  521. characteristics of the new session. 
  522.  
  523.  
  524. ΓòÉΓòÉΓòÉ 4.1.2.5.2. setup_startdata() ΓòÉΓòÉΓòÉ
  525.  
  526. Here is the definition of the StartData structure, taken from the EMX header 
  527. files: 
  528.  
  529. typedef struct {
  530.   USHORT Length;
  531.   USHORT Related;
  532.   USHORT FgBg;
  533.   USHORT TraceOpt;
  534.   PSZ    PgmTitle;
  535.   PSZ    PgmName;
  536.   PBYTE  PgmInputs;
  537.   PBYTE  TermQ;
  538.   PBYTE  Environment;
  539.   USHORT InheritOpt;
  540.   USHORT SessionType;
  541.   PSZ    IconFile;
  542.   ULONG  PgmHandle;
  543.   USHORT PgmControl;
  544.   USHORT InitXPos;
  545.   USHORT InitYPos;
  546.   USHORT InitXSize;
  547.   USHORT InitYSize;
  548.   USHORT Reserved;
  549.   PSZ    ObjectBuffer;
  550.   ULONG  ObjectBuffLen;
  551. } STARTDATA;
  552.  
  553. void setup_startdata(STARTDATA *SD) {
  554.  
  555. setup_startdata() takes one parameter--a pointer to a STARTDATA struct. 
  556.  
  557. SD->Length = sizeof(STARTDATA);
  558.  
  559. First we set the length of the structure.  Different values enable different 
  560. properties--specifically a length of 30 or 32 will cause DosStartSession to 
  561. leave the rest of the struct blank and allow the installation file to fill in 
  562. appropriate fields. We need all the functionality, so we will initialize 
  563. SD->Length to the actual size of the struct. 
  564.  
  565. SD->Related = SSF_RELATED_INDEPENDENT;
  566.  
  567. We want an independent session.  Originally I had this set as 
  568. SSF_RELATED_CHILD, because it seem to make sense that I would want DPipeLn to 
  569. spawn a child session to run the Dos program in.  Also, child sessions cause a 
  570. Termination Queue to be created, which, for Dos sessions, contains the Dos 
  571. program's exit code.  Obtaining the exit code is then merely a matter of 
  572. invoking the necessary functions from the queue API.  However, the Toolkit 
  573. reference says this about SSF_RELATED_CHILD: 
  574.  
  575. Once a process has issued DosStartSession specifying a value of 1 for Related, 
  576. no other process within that session can issue related DosStartSession 
  577. functions until all the dependent sessions have ended. 
  578.  
  579. And I found that that was true.  When running IBM's WorkFrame/2 from the 11/93 
  580. PDK CD-Rom and running a make that involved a Dos compiler and DPipeLn, I could 
  581. not start any other tool until the make was finished.  WorkFrame would complain 
  582. with error 452 "ERROR_SMG_NOT_PARENT".  Unfortunately, SSF_RELATED_INDEPENDENT 
  583. type sessions do not pass exit codes back to the parent.  To circumvent that, 
  584. DPipeLn creates a Dos batch file each time it is run.  The batch file contains 
  585. batch commands to run the Dos program, and then send the return code back 
  586. through the return code pipe to the OS/2 session.  This one of two reasons is 
  587. why DPipeLn works better with 4Dos than the stock command.com--4Dos includes 
  588. primitives for retrieving the return code from the previously run program.  The 
  589. batch file for command.com is several hundred lines of if statements.  The 
  590. second reason is that command.com makes no provision for redirecting stderr. 
  591. Thus, you get stderr from the Dos process only if you are running 4Dos. 
  592.  
  593. SD->FgBg = Opt_foreground ? SSF_FGBG_FORE : SSF_FGBG_BACK;
  594.  
  595. Opt_foreground is a global variable set while processing the command line.  It 
  596. is true if the user specified on the command line that the Dos session should 
  597. appear in the foreground.  FgBg is the element of STARTDATA that controls that 
  598. characteristic. 
  599.  
  600. SD->TraceOpt = SSF_TRACEOPT_NONE;
  601.  
  602. It is possible to start a session specifically for debugging--if so, TraceOpt 
  603. is set to SSF_TRACEOPT_TRACE or SSF_TRACEOPT_NOTIFY. 
  604.  
  605. SD->PgmTitle = PgmTitle;
  606.  
  607. PgmTitle contains the title of the session window. 
  608.  
  609. SD->TermQ = 0;
  610.  
  611. If the Dos session was a child session, we would set TermQ equal to the queue 
  612. handle. 0 indicates that there is no termination queue.  TermQ is ignored for 
  613. independent sessions anyway. 
  614.  
  615. SD->InheritOpt = SSF_INHERTOPT_PARENT;
  616.  
  617. This determines if the new session will inherit the parents environment or not. 
  618. In this case, we want to. 
  619.  
  620. SD->SessionType = SSF_TYPE_WINDOWEDVDM;
  621.  
  622. Though the default is for the session to be invisible, we still want to set its 
  623. type to a windowed VDM in case the user shows the window. 
  624.  
  625. SD->IconFile = 0;
  626.  
  627. There is no icon associated with this session. 
  628.  
  629. SD->PgmHandle = 0;
  630.  
  631. Do not use the installation file. I'm not sure what this means or how it works. 
  632. The CP reference is vague on this parameter. 
  633.  
  634. SD->PgmControl = Opt_visible ? SSF_CONTROL_VISIBLE : SSF_CONTROL_INVISIBLE;
  635.  
  636. Start the program as visible, or invisible depending on the command line 
  637. argument. 
  638.  
  639. SD->InitXPos = 30;
  640. SD->InitYPos = 40;
  641. SD->InitXSize = 200;
  642.  
  643. Here the initial window coordinates and size are set. 
  644.  
  645. SD->Reserved = 0;
  646.  
  647. This is a reserved parameter.  The CP reference says it must be 0. 
  648.  
  649. SD->ObjectBuffer = ObjBuf;
  650.  
  651. DosStartSession calls DosExecProgram to actually start the program.  If 
  652. DosExecPgm fails, the name of the object responsible is placed in this buffer. 
  653.  
  654. SD->ObjectBuffLen = 100;
  655.  
  656. This is just the size of the object buffer. 
  657.  
  658. SD->Environment = Opt_settings ? get_dos_settings(PgmSettingsFile) : 0;
  659.  
  660. DosStartSession allows Dos sessions to get their settings from a string of 
  661. null-terminated strings.  If the user specified a settings file on the command 
  662. line, then get_dos_settings() loads that file into memory and Environment is 
  663. assigned a pointer to the beginning of the set.  The settings cannot be any 
  664. larger than 4096 bytes.  This is not documented in the CP Reference, I learned 
  665. how to do it by examining the code from Norm Ross's StartD program.  Thus, 
  666. DPipeLn and StartD can use the same settings files. 
  667.  
  668. SD->PgmName = 0;
  669.  
  670. PgmName is the name of the executable that DosStartSession is running.  If this 
  671. is 0 (or NULL) the Session will invoke the a shell--either the one specified in 
  672. CONFIG.SYS or the one in the settings file. 
  673.  
  674. PgmCmdLine = new_string(strlen(Batname) + strlen("/c "));
  675. strcpy(PgmCmdLine, "/c ");
  676. strcat(PgmCmdLine, Batname);
  677. SD->PgmInputs = PgmCmdLine;
  678.  
  679. PgmInputs is the  last of the STARTDATA elements.  It points to the command 
  680. line for the program being invoked.  Since we are actually invoking a batch 
  681. file that runs the desired executable, we need to run it through the shell, 
  682. thus the /c. 
  683.  
  684.  
  685. ΓòÉΓòÉΓòÉ <hidden> StartD Reference ΓòÉΓòÉΓòÉ
  686.  
  687. StartD is a small OS/2 utility written by Norm P. Ross (npross@undergrad. 
  688. uwaterloo.ca) that starts a Dos session from an OS/2 command line.  It is a lot 
  689. like the built-in start /dos , except it allows a settings file to be 
  690. specified.  The settings file uses the same strings found in a standard Dos 
  691. settings box.  Here's the settings file I use when spawning Borland C/C++ for 
  692. Dos. 
  693.  
  694. EMS_MEMORY_LIMIT=128
  695. XMS_MEMORY_LIMIT=8192
  696. DPMI_DOS_API=ENABLED
  697. DPMI_MEMORY_LIMIT=8
  698. IDLE_SENSITIVITY=50
  699.  
  700. StartD can be found at ftp-os2.nmsu.edu in /pub/os2/2.x/sysutils/startd.zip. 
  701.  
  702.  
  703. ΓòÉΓòÉΓòÉ 4.1.2.5.3. main() continued ΓòÉΓòÉΓòÉ
  704.  
  705. Now that the STARTDATA struct is set up, we can create the batch file, and 
  706. start the new session.  The session is started asynchronously, so program flow 
  707. continues after the call. 
  708.  
  709. rc = build_batchfile(Batname, Errpname, Command);
  710. rc = DosStartSession(&sd, &sess_id, &s_pid);
  711.  
  712. DosStartSession() will return the new session's ID in sess_id, and the 
  713. appropriate process ID in s_pid. 
  714.  
  715. Because DPipeLn might still be busy transferring stdout from the Dos program 
  716. when the Dos program ends and sends its return code over the pipe, we need to 
  717. wait for that return code in a separate thread.  Starting new threads in OS/2 
  718. is easy--almost easier than under Unix: 
  719.  
  720. rc = DosCreateThread(&threadid, read_errpipe, targ, tflags, tstack);
  721.  
  722. DosCreateThread() needs the following 
  723.  
  724. read_errpipe 
  725.           The name of the function to execute in the thread. 
  726.  
  727. targ 
  728.           The address of a parameter block to pass to the function.  This 
  729.           allows any information to be passed into the thread in the form of a 
  730.           pointer to some storage. 
  731.  
  732. tflags 
  733.           If true, the thread starts right away.  If false, the program must 
  734.           call DosResumeThread() to start the thread. 
  735.  
  736. tstack 
  737.           Specifies the amount of stack to give to the thread.  The main 
  738.           program sets this at 4096 bytes. 
  739.  
  740. DosCreateThread() returns the thread ID in threadid. 
  741.  
  742. rc = DosConnectNPipe(Piphand);
  743.  
  744. After creating the pipe, we need to connect to it. 
  745.  
  746. transfer_data(&Piphand);
  747.  
  748. And now we transfer data from it.  transfer_data() loops until the Dos program 
  749. closes the pipe (by exiting).  The data is gathered out of the pipe by a 
  750. DosRead() call and printed to the stdout of the OS/2 session. 
  751.  
  752. rc = DosWaitThread(&threadid, DCWW_WAIT);
  753.  
  754. This waits for the read_errpipe() thread to complete.  When it is complete we 
  755. know that the Dos program (actually the batch file) has reported the exit code. 
  756. This is the easy way out--normally in a multithreaded program semaphores are 
  757. used to insure that global variables are accessed only when the data in them is 
  758. valid. 
  759.  
  760. sscanf(RCstring, "%d", &dosreturn);
  761.  
  762. Put the return code into the local dosreturn. The batch file transmits the code 
  763. as ASCII text, so the sscanf is necessary to convert it to an integer. 
  764.  
  765. DosWaitChild(DCWA_PROCESS,
  766.       DCWW_WAIT,
  767.       &wp_results,
  768.       &the_pid,
  769.       s_pid);
  770.  
  771. This call may not be absolutely necessary, since the Dos program is started as 
  772. an independent session.  It blocks until the Dos session is complete. 
  773.  
  774. cleanup();
  775.  
  776. cleanup() frees allocated storage and closes the named pipes. 
  777.  
  778. return (USHORT)dosreturn;
  779.  
  780. Lastly, return the Dos exit code to the calling process. 
  781.  
  782.  
  783. ΓòÉΓòÉΓòÉ 4.1.2.6. DPipeLn Examples ΓòÉΓòÉΓòÉ
  784.  
  785. Now that you understand how DPipeLn works, let's look at a couple of ways to 
  786. use it. 
  787.  
  788.  
  789. ΓòÉΓòÉΓòÉ 4.1.2.6.1. Make and DPipeLn ΓòÉΓòÉΓòÉ
  790.  
  791. Here is a makefile I use that utilizes DPipeLn.  Note that GnuMake supports 
  792. parallel makes, and since OS/2 never loads code more than once, parallel makes 
  793. can be a real win even with Dos compilers. 
  794.  
  795. SHELL=c:/4os2/4os2.exe
  796.  
  797. # Makefile for the School Improvement Program.
  798.  
  799. OBJS=fileio.obj filewins.obj prutils.obj si_chk0.obj si_chk1.obj si_chk2.obj \
  800. si_chk3.obj si_chk4.obj si_chk5.obj si_chk6.obj si_chk7.obj si_chk8.obj \
  801. si_chk9.obj si_chka.obj si_chkb.obj si_chkc.obj si_chkd.obj si_chke.obj \
  802. si_chkf.obj si_chkg.obj si_chkh.obj si_pg0.obj  si_pg1.obj si_pg2.obj \
  803.  
  804. OBJS2=d:\dosapps\borlandc\lib\c0l.obj
  805.  
  806. CFLAGS=-ml -c -If:\tcxl55\inc
  807.  
  808. DEBUGLINK= /m /v
  809.  
  810. DEBUG=-v
  811. %.obj : %.c
  812.     echos $< ^ >> sources.rsp
  813.  
  814. sip.exe: preclean objects $(OBJS) sip.rsp
  815.     dpipeln.exe -sbcc.ini tlink.exe $(DEBUGLINK) /c @sip.rsp,sip,sip,tcxlbcl cl
  816.  
  817. objects: $(OBJS)
  818.     dpipeln.exe -sbcc.ini bcc.exe $(DEBUG) $(CFLAGS) @sources.rsp
  819.  
  820. sip.rsp: makefile
  821.     echo $(OBJS2) + > sip.rsp
  822.     echo $(OBJS) >> sip.rsp
  823.  
  824. preclean:
  825.     copy nul sources.rsp
  826.  
  827. clean:
  828.     erase /q sip.exe sources.rsp sip.rsp $(OBJS)
  829.  
  830. The makefile builds a list of targets in the file sources.rsp, and then passes 
  831. that to BCC as a response file.  BCC only loads itself once, but you could 
  832. speed up processing by splitting the object files up into two targets and 
  833. compiling them in parallel. 
  834.  
  835.  
  836. ΓòÉΓòÉΓòÉ 4.1.2.7. WF/2 and DPipeLn ΓòÉΓòÉΓòÉ
  837.  
  838. If you have IBM's WorkFrame/2 and have read its README file, you may remember 
  839. that it says that you can use Dos hosted tools, but you cannot see their 
  840. output. With DPipeLn, you can!  Dos command-line tools become just like OS/2 
  841. tools under WF/2. 
  842.  
  843. Under Language Profile Management, simply specify x:\path\dpipeln.exe as the 
  844. compiler executable name. Then, under Compiler Options, type the acual name of 
  845. the compiler, along with any command-line options, in the options dialog. 
  846. Here's an example using Turbo Pascal 6.0 for Dos. 
  847.  
  848. And in the Compiler Options dialog box: 
  849.  
  850. ... 
  851.  
  852.  
  853. ΓòÉΓòÉΓòÉ 4.1.3. Conclusion ΓòÉΓòÉΓòÉ
  854.  
  855. DPipeLn has been a very useful tool for helping to seamlessly integrate my Dos 
  856. development utilities with OS/2 hosted utilities such as GnuMake, IBM WF/2, and 
  857. others.  Source and executable is available, as mentioned at the beginning of 
  858. this article. 
  859.  
  860. Comments, questions, and suggestions are encouraged.  I may be reached at the 
  861. address found at the end of this document. 
  862.  
  863. Happy Hacking! 
  864.  
  865.  
  866. ΓòÉΓòÉΓòÉ 4.2. OS/2 Installable File Systems - Part 1 ΓòÉΓòÉΓòÉ
  867.  
  868.                                 OS/2 Installable
  869.                                   File Systems
  870.  
  871.                               Part 1 - Introduction
  872.  
  873.                                   Andre Asselin
  874.                                 (assela@rpi.edu)
  875.  
  876.  
  877. ΓòÉΓòÉΓòÉ 4.2.1. Introduction ΓòÉΓòÉΓòÉ
  878.  
  879. One of the most useful but obscure features of OS/2 is it's support for 
  880. installable file systems (IFSs). This API allows you to extend OS/2 to do two 
  881. things: access files stored on disk in formats other than FAT and HPFS,  and 
  882. access files that are stored on a network file server.  For example, under many 
  883. versions of UNIX, files are stored in the Berkeley fast file system format, 
  884. which isn't compatible with FAT or HPFS.  If you have both UNIX and OS/2 
  885. installed on the same computer with partitions setup for each, you could write 
  886. an IFS to read and write the UNIX files while OS/2 is running and give all the 
  887. programs running under OS/2 (including DOS and Windows programs) access to 
  888. those files. 
  889.  
  890. The other variety of IFS is called a remote file system or redirector, and 
  891. allows file sharing over LANs.  In this case, when a program calls for a file, 
  892. the IFS acts as a client and sends the request over a network to a file server. 
  893. The file server handles the request and sends the data back to the client. 
  894. Examples of this type of IFS include Novell's Netware requester and the 
  895. requester part of LAN Server.  Sometimes, in addition to just sending the 
  896. requests to the server, this type of IFS also has to translate between OS/2 
  897. file conventions and file conventions that the server understands.  For 
  898. example, the NFS (Network File System) protocol is completely UNIX oriented, so 
  899. the NFS client (which is an IFS) has to handle UNIX conventions like case 
  900. sensitive filenames and UNIX file attributes. 
  901.  
  902. Up until now, there hasn't been much written on how to develop an IFS. It also 
  903. doesn't help that the documentation on the IFS API has been available only by 
  904. special request from IBM.  This series is going to explore the IFS API in depth 
  905. with working examples in order to take the mystery out of writing them.  This 
  906. first article is a brief overview of the IFS concept to give a feel for what's 
  907. involved in writing one.  In the coming months, I'm going to explore the IFS 
  908. architecture in depth and build up a toolkit that can be used as a skeleton for 
  909. writing an IFS. 
  910.  
  911.  
  912. ΓòÉΓòÉΓòÉ 4.2.2. IFS Structure and How It Fits In ΓòÉΓòÉΓòÉ
  913.  
  914. An IFS (which is also known as an FSD for File System Driver) can  be thought 
  915. of as a specialized kind of physical device driver (PDD), although it is 
  916. structured very differently.  Instead of having only two entry points and being 
  917. based on request packets, it is structured as an ordinary 16-bit DLL with a 
  918. series of predefined entry points, broken up into four groups,  that are 
  919. exported to the system (see Table 1). The first group consists of the primary 
  920. entry points that all IFSs are required to export.  This group does basic file 
  921. manipulation, such as opening and closing, and reading and writing files.  Most 
  922. of these entry points correspond pretty closely in name and function to related 
  923. DosXxx calls. The other three groups of calls provide support for the swapper, 
  924. file locking, and UNC (Universal Naming Convention). For each of these groups, 
  925. if your IFS doesn't support that particular feature, you don't have to export 
  926. any of the functions in that group of entry points. Note that exports should be 
  927. made on a group-by-group basis; don't export only some of the entry points from 
  928. a group. 
  929.  
  930. Figure 1 (below) shows where an IFS fits into the OS/2 system.  The two shaded 
  931. components are what make up an IFS.  The piece that runs in ring 0 (called 
  932. MY.IFS in the figure) is the main component.  It is called by the OS/2 kernel 
  933. through one of its FS_XXX entry points whenever something needs to be done on a 
  934. drive that the IFS is managing.  The IFS performs the function and returns the 
  935. requested data or an error code.  Typically, it will interact with a PDD to do 
  936. its I/O.  Like any ordinary DLL, an IFS doesn't have a process or threads of 
  937. its own.  Instead, it operates in the context of the caller's process and on 
  938. the caller's thread (in the case of an IFS, the caller's thread and process are 
  939. the thread and process of the application making the Doscall). In this sense, 
  940. an IFS can be thought of as a passive library that's not activated until a 
  941. program calls it. 
  942.  
  943. Since an IFS has to be available to every application in the system, it is 
  944. loaded into global system memory (using GDT selectors).  Any memory it 
  945. allocates (such as for buffers) should also come from global system memory so 
  946. that no matter which process its entered from, it'll still have access to the 
  947. memory. 
  948.  
  949. The piece that runs in ring 3 (UMY.DLL in the figure) is a utility library. 
  950. There is one utility DLL for each IFS; the naming convention is a 'U' followed 
  951. by the IFS name with an extension of .DLL.  It has four entry points; one each 
  952. for FORMAT, RECOVER, SYS, and CHKDSK.  When a user runs any of those programs 
  953. and it detects that it is being run against a drive being managed by an IFS, it 
  954. will call the appropriate entry point in the IFS's utility DLL.  The DLL is 
  955. then completely responsible for carrying out the command. 
  956.  
  957.  
  958. ΓòÉΓòÉΓòÉ 4.2.3. How a Doscall Gets Processed ΓòÉΓòÉΓòÉ
  959.  
  960. A typical Doscall (such as DosOpen, DosRead, or DosWrite) is processed mainly 
  961. by the IFS with some help from the OS/2 kernel (see Figure 2).  When an 
  962. application issues a Doscall, such as DosOpen (1), a component of the OS/2 
  963. kernel called the file system router does some preliminary validation of the 
  964. parameters.  If everything's OK, it decides which IFS the call should be sent 
  965. to and calls the IFS at the appropriate entry point, which in the case of 
  966. DosOpen is FS_OPENCREATE (2).  The IFS then looks at the parameters that were 
  967. passed and decides on a course of action to service the call.  In some cases, 
  968. it may not support the function (for example, trying to open a remote drive for 
  969. direct, sector-by-sector access), in which case it immediately returns an error 
  970. code.  If it does support the function, it might first check its cache to see 
  971. if it already has the requested data, in which case it can just return it.  If 
  972. it doesn't have the data in its cache, it will probably have to do some I/O to 
  973. get it. 
  974.  
  975. In the this case, it calls one of OS/2's file system helpers, FSH_DOVOLIO (3), 
  976. which acts as an intermediary between the IFS and the device driver. 
  977. FSH_DOVOLIO generates a request packet and calls the strategy entry point of 
  978. the appropriate device driver (4).  The device driver performs the I/O (5), and 
  979. eventually returns to FSH_DOVOLIO, which returns back to the IFS. The IFS can 
  980. then examine the return code for errors and take appropriate action.  If it 
  981. needs to, the IFS can the device driver multiple times until it has all the 
  982. requested data.  It then returns back to the OS/2 kernel, which in turn returns 
  983. back to the application.  The application can then examine the return code to 
  984. see if the operation was successful. 
  985.  
  986.  
  987. ΓòÉΓòÉΓòÉ 4.2.4. Ring 0 Issues ΓòÉΓòÉΓòÉ
  988.  
  989. The type of IFS described above runs completely in ring 0 and can be thought of 
  990. as a 'traditional' IFS.  Unfortunately, it can be difficult to develop because 
  991. of the restrictions placed on code that runs at ring 0 (PDDs and VDDs suffer 
  992. from these restrictions as well).  There are three main restrictions: 
  993.  
  994. No preemptive multitasking - When an IFS or any other ring 0 code is entered, 
  995. preemptive multitasking is temporarily disabled.  The IFS can still yield to 
  996. other threads (i.e. cooperative multitasking), but it will never be suspended 
  997. unless it specifically asks for it.  This has the benefit of eliminating some 
  998. synchronization issues, but it also means that periodic yields have to be 
  999. sprinkled throughout lengthy operations. 
  1000.  
  1001. No Doscalls; only file system helpers and DevHlps - None of the ring 3 API's 
  1002. (such as the Doscalls) are available to ring 0 code (except at initialization, 
  1003. which is special).  If you use any functions from the C library, you have to 
  1004. make sure that they don't in turn use any of the Doscalls (i.e. malloc and free 
  1005. don't work at ring 0 because they call DosAllocMem).  As a partial replacement, 
  1006. there are a series of file system helper (FSH) calls available for IFS's (see 
  1007. Table 2) as well as the standard DevHlp calls available to all device drivers. 
  1008. These APIs perform common tasks such as allocating memory and handling 
  1009. semaphores, but they are more primitive and thus more difficult to use than the 
  1010. Doscalls. 
  1011.  
  1012. Debugging is a pain - If you thought debugging PM applications was tricky, wait 
  1013. until you try an IFS! First, you won't be able to use your favorite debugger-- 
  1014. you have to use a ring 0 debugger, such as the OS/2 kernel debugger or ASDT32. 
  1015. Neither of these can do source level debugging, so you have to know assembler, 
  1016. and they also have limited support for labels.  There is also no such thing as 
  1017. a printf in ring 0, so you have to use a hex dump to look at variables.  As if 
  1018. that weren't bad enough, OS/2's crash protection doesn't apply to ring 0 code; 
  1019. if your code has a bug and traps, it will bring down the system with an IPE 
  1020. (Internal Processing Error). This is where you get the blue screen, lots of 
  1021. register information, a suggestion to call IBM, etc.  Frequent reboots tend to 
  1022. be the way of life. 
  1023.  
  1024.  
  1025. ΓòÉΓòÉΓòÉ 4.2.5. The Split IFS / Control Program Approach ΓòÉΓòÉΓòÉ
  1026.  
  1027. Because of these restrictions, a popular approach to developing an IFS is to 
  1028. split it between ring 0 and ring 3.  The ring 0 piece (the IFS proper) contains 
  1029. only stub routines and passes all the calls up to a ring 3 control program. 
  1030. The control program handles the calls and then passes the results back to the 
  1031. ring 0 piece.  The advantages of doing it this way are that developing the bulk 
  1032. of the IFS is easier (because it runs at ring 3, you don't have to worry about 
  1033. those restrictions mentioned above), and you have access to all the normal ring 
  1034. 3 APIs.  This approach also allows you to layer an IFS on top of an already 
  1035. existing IFS; for example, DCF/2 and Stacker for OS/2 probably take this 
  1036. approach to use FAT or HPFS to store their compressed data files.  This way 
  1037. they don't have to worry about totally rewriting the FAT or HPFS code-- all 
  1038. they have to be concerned with is compressing the data on the fly and then 
  1039. using the already existing IFSs to actually store it on the disk. 
  1040.  
  1041. This type of IFS is usually implemented using captive threads.  Figure 3 traces 
  1042. a call as it winds its way between an application, the IFS, and its control 
  1043. program.  When the control program initializes, it creates one or more threads 
  1044. that call into the IFS (1 and 2).  The IFS makes these threads block until some 
  1045. application calls the IFS with work to do (3 and 4).  The IFS then sets up a 
  1046. parameter area, blocks the application's thread and unblocks the control 
  1047. program's thread.  The IFS returns back to the control program (5 and 6), where 
  1048. it executes the request.  The control program then puts the results back in the 
  1049. parameter block and calls the IFS again (7 and 8).  The IFS then unblocks the 
  1050. application's thread and has it return with the results (9 and 10) while the 
  1051. control program's thread is again blocked waiting for a new request. 
  1052.  
  1053.  
  1054. ΓòÉΓòÉΓòÉ 4.2.6. What's Ahead ΓòÉΓòÉΓòÉ
  1055.  
  1056. Well, that's a high level overview of what's involved in writing an installable 
  1057. file system.  In the next issue, I'm going to start developing the framework to 
  1058. implement a split ring 0 / ring 3 IFS.  To illustrate how to use it, I'm going 
  1059. to write an IFS that supports file versions (like VMS). 
  1060.  
  1061. While you're waiting for the next issue, you may want to start gathering the 
  1062. tools necessary to write an IFS.  The first thing you'll need, of course, is 
  1063. the documentation on the IFS API and the libraries and header files that go 
  1064. along with it.  To get it, you need to send a note on CompuServe requesting the 
  1065. IFS documentation to Mike Abrams (72420,216) in the OS2DF1 forum section 11 
  1066. (Device Driver Development) with your name and address.  If you don't have an 
  1067. account on CompuServe, you can send him a note using the Internet; address it 
  1068. to 72420.216@compuserve.com (note the period instead of the comma in the 
  1069. number). 
  1070.  
  1071. You'll also need two C compilers.  For the ring 0 piece, you'll need a 16-bit C 
  1072. compiler.  Most IFS developers use Microsoft C 6.0, but I'm going to 
  1073. investigate the possibility of using Borland C++ instead.  If I can make it 
  1074. work, that's what I'm going to use, but the code should be compatible with both 
  1075. compilers.  For the ring 3 piece, you'll need a 32-bit compiler, such as IBM's 
  1076. C Set++ or Borland C++ for OS/2.  Finally, you probably won't need it right 
  1077. away, but you should also get a hold of either the kernel debugger or ASDT32, 
  1078. which is available through IBM's EWS program. 
  1079.  
  1080. If this series is interesting to you, please drop me a note telling me a little 
  1081. bit about yourself and your background so that I have a better idea who my 
  1082. audience is (it'll also help my motivation if I know that more than Steve and I 
  1083. are reading this series).  While you're at it, if you have any feedback or 
  1084. ideas on what you'd like to see covered in future articles, I'd love to hear 
  1085. it.  See you next month. 
  1086.  
  1087.  
  1088. ΓòÉΓòÉΓòÉ 4.2.7. Table 1 - FSD Entry Points ΓòÉΓòÉΓòÉ
  1089.  
  1090. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1091. ΓöéPrimary Entry Points                                                              Γöé
  1092. Γöé                                                                                  Γöé
  1093. ΓöéFile Management                                                                   Γöé
  1094. Γöé                                                                                  Γöé
  1095. Γöé                     FS_OPENCREATE             Open or create a file              Γöé
  1096. Γöé                                                                                  Γöé
  1097. Γöé                     FS_CLOSE                  Close a file                       Γöé
  1098. Γöé                                                                                  Γöé
  1099. Γöé                     FS_READ                   Read data from a file              Γöé
  1100. Γöé                                                                                  Γöé
  1101. Γöé                     FS_WRITE                  Write data to a file               Γöé
  1102. Γöé                                                                                  Γöé
  1103. Γöé                     FS_CHGFILEPTR             Change the current position in a   Γöé
  1104. Γöé                                               file                               Γöé
  1105. Γöé                                                                                  Γöé
  1106. Γöé                     FS_COMMIT                 Write all cached data for a file toΓöé
  1107. Γöé                                               disk                               Γöé
  1108. Γöé                                                                                  Γöé
  1109. Γöé                     FS_DELETE                 Delete a file                      Γöé
  1110. Γöé                                                                                  Γöé
  1111. Γöé                     FS_NEWSIZE                Change the size of a file          Γöé
  1112. Γöé                                                                                  Γöé
  1113. Γöé                     FS_MOVE                   Move or rename a file              Γöé
  1114. Γöé                                                                                  Γöé
  1115. Γöé                     FS_COPY                   Copy a file                        Γöé
  1116. Γöé                                                                                  Γöé
  1117. Γöé                     FS_FILEATTRIBUTE          Set or return the standard (DOS)   Γöé
  1118. Γöé                                               attributes                         Γöé
  1119. Γöé                                                                                  Γöé
  1120. Γöé                     FS_FILEIO                 Perform an atomic read/write/lock  Γöé
  1121. Γöé                                               operation                          Γöé
  1122. Γöé                                                                                  Γöé
  1123. Γöé                     FS_FILEINFO               Set or return information on an    Γöé
  1124. Γöé                                               open file                          Γöé
  1125. Γöé                                                                                  Γöé
  1126. Γöé                     FS_PATHINFO               Set or return information on a fileΓöé
  1127. Γöé                                                                                  Γöé
  1128. ΓöéVolume Management                                                                 Γöé
  1129. Γöé                                                                                  Γöé
  1130. Γöé                     FS_ATTACH                 Associate or disassociate a drive  Γöé
  1131. Γöé                                               letter with an FSD                 Γöé
  1132. Γöé                                                                                  Γöé
  1133. Γöé                     FS_MOUNT                  Examine a volume to determine if   Γöé
  1134. Γöé                                               the FSD knows its format           Γöé
  1135. Γöé                                                                                  Γöé
  1136. Γöé                     FS_FSINFO                 Get/Set file system information    Γöé
  1137. Γöé                                                                                  Γöé
  1138. Γöé                     FS_FLUSHBUF               Write all cached data for a volume Γöé
  1139. Γöé                                               to disk                            Γöé
  1140. Γöé                                                                                  Γöé
  1141. ΓöéDirectory Management                                                              Γöé
  1142. Γöé                                                                                  Γöé
  1143. Γöé                     FS_CHDIR                  Change directory                   Γöé
  1144. Γöé                                                                                  Γöé
  1145. Γöé                     FS_MKDIR                  Make a new directory               Γöé
  1146. Γöé                                                                                  Γöé
  1147. Γöé                     FS_RMDIR                  Remove a directory                 Γöé
  1148. Γöé                                                                                  Γöé
  1149. ΓöéDirectory Search                                                                  Γöé
  1150. Γöé                                                                                  Γöé
  1151. Γöé                     FS_FINDCLOSE              End a search in progress           Γöé
  1152. Γöé                                                                                  Γöé
  1153. Γöé                     FS_FINDFIRST              Begin a new search                 Γöé
  1154. Γöé                                                                                  Γöé
  1155. Γöé                     FS_FINDFROMNAME           Restart a search from a particular Γöé
  1156. Γöé                                               point                              Γöé
  1157. Γöé                                                                                  Γöé
  1158. Γöé                     FS_FINDNEXT               Return next file name              Γöé
  1159. Γöé                                                                                  Γöé
  1160. Γöé                     FS_FINDNOTIFYCLOSE        Stop monitoring a directory for    Γöé
  1161. Γöé                                               changes                            Γöé
  1162. Γöé                                                                                  Γöé
  1163. Γöé                     FS_FINDNOTIFYFIRST        Start monitoring a directory file  Γöé
  1164. Γöé                                               changes                            Γöé
  1165. Γöé                                                                                  Γöé
  1166. Γöé                     FS_FINDNOTIFYNEXT         Return the next set of changes     Γöé
  1167. Γöé                                                                                  Γöé
  1168. ΓöéFSD Extended                                                                      Γöé
  1169. ΓöéInterface                                                                         Γöé
  1170. Γöé                                                                                  Γöé
  1171. Γöé                     FS_FSCTL                  Extended interface to an FSD       Γöé
  1172. Γöé                                                                                  Γöé
  1173. Γöé                     FS_IOCTL                  I/O control for devices            Γöé
  1174. Γöé                                                                                  Γöé
  1175. ΓöéMiscellaneous                                                                     Γöé
  1176. Γöé                                                                                  Γöé
  1177. Γöé                     FS_NMPIPE                 Support named pipe operations      Γöé
  1178. Γöé                                                                                  Γöé
  1179. Γöé                     FS_PROCESSNAME            Allow an FSD to canonicalize a fileΓöé
  1180. Γöé                                               name to its own particular         Γöé
  1181. Γöé                                               conventions                        Γöé
  1182. Γöé                                                                                  Γöé
  1183. Γöé                     FS_SETSWAP                Designate a partition as the swap  Γöé
  1184. Γöé                                               partition                          Γöé
  1185. Γöé                                                                                  Γöé
  1186. Γöé                     FS_INIT                   Initialize the FSD                 Γöé
  1187. Γöé                                                                                  Γöé
  1188. Γöé                     FS_SHUTDOWN               Notify the FSD that the system is  Γöé
  1189. Γöé                                               shutting down                      Γöé
  1190. Γöé                                                                                  Γöé
  1191. Γöé                     FS_EXIT                   Notify the FSD that a process is   Γöé
  1192. Γöé                                               ending                             Γöé
  1193. Γöé                                                                                  Γöé
  1194. ΓöéSwapper Entry Points                                                              Γöé
  1195. Γöé                                                                                  Γöé
  1196. Γöé                     FS_ALLOCATEPAGESPACE      Allocate space in the swapper file Γöé
  1197. Γöé                                                                                  Γöé
  1198. Γöé                     FS_DOPAGEIO               Read or write page(s) to the       Γöé
  1199. Γöé                                               swapper file                       Γöé
  1200. Γöé                                                                                  Γöé
  1201. Γöé                     FS_OPENPAGEFILE           Open the swapper file              Γöé
  1202. Γöé                                                                                  Γöé
  1203. ΓöéFile Locking Entry                                                                Γöé
  1204. ΓöéPoints                                                                            Γöé
  1205. Γöé                                                                                  Γöé
  1206. Γöé                     FS_CANCELLOCKREQUEST      Cancels a lock request             Γöé
  1207. Γöé                                                                                  Γöé
  1208. Γöé                     FS_FILELOCKS              Lock or unlock a region of a file  Γöé
  1209. Γöé                                                                                  Γöé
  1210. ΓöéUNC Entry Point                                                                   Γöé
  1211. Γöé                                                                                  Γöé
  1212. Γöé                     FS_VERIFYUNCNAME          Determine if FSD provides access toΓöé
  1213. Γöé                                               a specific UNC server              Γöé
  1214. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1215.  
  1216.  
  1217. ΓòÉΓòÉΓòÉ 4.2.8. Table 2 - File System Helpers ΓòÉΓòÉΓòÉ
  1218.  
  1219. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1220. ΓöéFSH_ADDSHARE                        Add a name to the sharing set      Γöé
  1221. Γöé                                                                       Γöé
  1222. ΓöéFSH_CALLDRIVER                      Call a PDD's extended strategy     Γöé
  1223. Γöé                                    entry point                        Γöé
  1224. Γöé                                                                       Γöé
  1225. ΓöéFSH_CANONICALIZE                    Convert a filename to canonical    Γöé
  1226. Γöé                                    form                               Γöé
  1227. Γöé                                                                       Γöé
  1228. ΓöéFSH_CHECKEANAME                     Verify correctness of an EA name   Γöé
  1229. Γöé                                                                       Γöé
  1230. ΓöéFSH_CRITERROR                       Signal a hard error                Γöé
  1231. Γöé                                                                       Γöé
  1232. ΓöéFSH_DEVIOCTL                        Send a PDD an IOCTL request        Γöé
  1233. Γöé                                                                       Γöé
  1234. ΓöéFSH_DOVOLIO                         Call a PDD to transfer sectors     Γöé
  1235. Γöé                                                                       Γöé
  1236. ΓöéFSH_FINDCHAR                        Find first occurrence of a         Γöé
  1237. Γöé                                    character in a string              Γöé
  1238. Γöé                                                                       Γöé
  1239. ΓöéFSH_FINDDUPHVPB                     Locates equivalent hVPBs           Γöé
  1240. Γöé                                                                       Γöé
  1241. ΓöéFSH_FORCENOSWAP                     Forces a segment permanently into  Γöé
  1242. Γöé                                    memory                             Γöé
  1243. Γöé                                                                       Γöé
  1244. ΓöéFSH_GETPRIORITY                     Get current thread's priority      Γöé
  1245. Γöé                                                                       Γöé
  1246. ΓöéFSH_GETVOLPARM                      Get data for current volume        Γöé
  1247. Γöé                                                                       Γöé
  1248. ΓöéFSH_INTERR                          Signal an Internal Processing ErrorΓöé
  1249. Γöé                                                                       Γöé
  1250. ΓöéFSH_IOBOOST                         Give the current thread an I/O     Γöé
  1251. Γöé                                    boost                              Γöé
  1252. Γöé                                                                       Γöé
  1253. ΓöéFSH_IOSEMCLEAR                      Clear an I/O event semaphore       Γöé
  1254. Γöé                                                                       Γöé
  1255. ΓöéFSH_ISCURDIRPREFIX                  Check if current directory is a    Γöé
  1256. Γöé                                    prefix of a file name              Γöé
  1257. Γöé                                                                       Γöé
  1258. ΓöéFSH_LOADCHAR                        Load character from a string (NLS) Γöé
  1259. Γöé                                                                       Γöé
  1260. ΓöéFSH_NAMEFROMSFN                     Retrieve a file's name from its    Γöé
  1261. Γöé                                    file handle number                 Γöé
  1262. Γöé                                                                       Γöé
  1263. ΓöéFSH_PREVCHAR                        Move one character backwards in a  Γöé
  1264. Γöé                                    string (NLS)                       Γöé
  1265. Γöé                                                                       Γöé
  1266. ΓöéFSH_PROBEBUF                        Verify a region of memory for      Γöé
  1267. Γöé                                    accessibility                      Γöé
  1268. Γöé                                                                       Γöé
  1269. ΓöéFSH_QSYSINFO                        Retrieve system information        Γöé
  1270. Γöé                                                                       Γöé
  1271. ΓöéFSH_REGISTERPERFCTRS                Register the IFS with PERFVIEW     Γöé
  1272. Γöé                                                                       Γöé
  1273. ΓöéFSH_REMOVESHARE                     Remove a name from the sharing set Γöé
  1274. Γöé                                                                       Γöé
  1275. ΓöéFSH_SEGALLOC                        Allocate a segment                 Γöé
  1276. Γöé                                                                       Γöé
  1277. ΓöéFSH_SEGFREE                         Deallocate a segment               Γöé
  1278. Γöé                                                                       Γöé
  1279. ΓöéFSH_SEGREALLOC                      Reallocate a segment               Γöé
  1280. Γöé                                                                       Γöé
  1281. ΓöéFSH_SEMCLEAR                        Clear a semaphore                  Γöé
  1282. Γöé                                                                       Γöé
  1283. ΓöéFSH_SEMREQUEST                      Request a semaphore                Γöé
  1284. Γöé                                                                       Γöé
  1285. ΓöéFSH_SEMSET                          Set a semaphore                    Γöé
  1286. Γöé                                                                       Γöé
  1287. ΓöéFSH_SEMSETWAIT                      Set a semaphore and wait on it     Γöé
  1288. Γöé                                                                       Γöé
  1289. ΓöéFSH_SEMWAIT                         Wait on a semaphore                Γöé
  1290. Γöé                                                                       Γöé
  1291. ΓöéFSH_SETVOLUME                       Force a volume to be mounted on a  Γöé
  1292. Γöé                                    drive                              Γöé
  1293. Γöé                                                                       Γöé
  1294. ΓöéFSH_STORECHAR                       Store a character in a string (NLS)Γöé
  1295. Γöé                                                                       Γöé
  1296. ΓöéFSH_UPPERCASE                       Uppercase a string (NLS)           Γöé
  1297. Γöé                                                                       Γöé
  1298. ΓöéFSH_WILDMATCH                       Match a filename using wildcards   Γöé
  1299. Γöé                                                                       Γöé
  1300. ΓöéFSH_YIELD                           Yield the CPU to higher priority   Γöé
  1301. Γöé                                    threads                            Γöé
  1302. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1303.  
  1304.  
  1305. ΓòÉΓòÉΓòÉ 4.3. Programming the Container Control - Part 1 ΓòÉΓòÉΓòÉ
  1306.  
  1307.                                  Programming the
  1308.                                 Container Control
  1309.  
  1310.                                Larry Salomon, Jr.
  1311.                                (os2man@panix.com)
  1312.  
  1313.  
  1314. ΓòÉΓòÉΓòÉ 4.3.1. Introduction ΓòÉΓòÉΓòÉ
  1315.  
  1316. The release of OS/2 2.0 was special in many ways; not the least was the 
  1317. inclusion of four new standard PM controls:  the container, the notebook, the 
  1318. slider, and the value set.  Without question, the most difficult of these to 
  1319. utilize fully is the container control.  It's flexible design allowed for it to 
  1320. be used in a variety of fashions (which is no surprise when you look at its 
  1321. real-world counterpart) and provided a CUA 91 compliant interface without much 
  1322. additional work by the programmer.  Unfortunately, the initial work that has to 
  1323. be done is significant and has daunted many developers. 
  1324.  
  1325. This article begins a multi-part series on how to program the container and 
  1326. will describe the container control from a developer's perspective as well as 
  1327. introduce some of the basic programming concepts that can be used in you 
  1328. applications.  For additional information, it is highly recommended that you 
  1329. acquire a copy of the Winter and Spring 1993 issues of the OS/2 Developer 
  1330. magazine (produced by IBM Corp. and published by Miller Freeman Inc.).  These 
  1331. two issues contain a single article each by the container control developers on 
  1332. how to use it and are both very informative. 
  1333.  
  1334.  
  1335. ΓòÉΓòÉΓòÉ 4.3.2. A Bird's-Eye View ΓòÉΓòÉΓòÉ
  1336.  
  1337. In "real-life" a container is something that you see everyday. Most people 
  1338. store foodstuffs in Tupperware containers.  On many office desks, pens and 
  1339. pencils are stored in containers.  In a filing cabinet, documents are stored in 
  1340. another container, although it is more widely known as a folder. Everywhere you 
  1341. look, there are containers being used; because of this, the CUA designers 
  1342. decided that the ability to store objects in a container was a very good thing; 
  1343. not only was it a familiar concept, but it was also already being used on 
  1344. another computer platform (the MacIntosh) with extremely good results. 
  1345.  
  1346. The container is exactly what you think it is.  It allows an application to 
  1347. place "things" inside of it and these things can be viewed in one of five 
  1348. different ways.  The term "thing" is used because the container does not 
  1349. restrict the application in the type of items stored.  The five different views 
  1350. supported by the container are listed below: 
  1351.  
  1352. View                Description 
  1353. Icon                Each object is represented as an icon with a descriptive 
  1354.                     string below it. 
  1355. Name                Each object is represented as an icon with a descriptive 
  1356.                     string to the right. 
  1357. Text                Each object is represented solely as a descriptive string. 
  1358. Tree                Each object is represented as a hierarchical diagram of 
  1359.                     icons and/or descriptive strings. 
  1360. Detail              Each object is represented as a detailed description of the 
  1361.                     object.  The information displayed is defined by the 
  1362.                     application. 
  1363.  
  1364. This month, we will only employ the icon view for simplicity.  The other views 
  1365. will be covered in subsequent months. 
  1366.  
  1367. Each object is described to the container using a base data type - this can be 
  1368. either the RECORDCORE or the MINIRECORDCORE structure, depending on the CCS_ 
  1369. style used when creating the control. (For the purposes of our discussion, the 
  1370. MINIRECORDCORE structure will be referenced although either could be used.) 
  1371. When objects are allocated, additional memory at the end of the MINIRECORDCORE 
  1372. structure can be requested, for the storage of any object-specific data. Thus, 
  1373. you would have to define a structure to contain both the base data and the 
  1374. additional fields needed: 
  1375.  
  1376. typedef struct _MYCNRREC {
  1377.    MINIRECORDCORE mrcCore;
  1378.    CHAR achText[256];
  1379.    ULONG ulNumSold;
  1380.    float fGrossIncome;
  1381.    float fNetIncome;
  1382.    float fTotalCost;
  1383.    float fNetProfit;
  1384. } MYCNRREC, *PMYCNRREC;
  1385.  
  1386. Since the container, when returning pointers to the object records, always 
  1387. returns a PRECORDCORE type, you will need to typecast this to your 
  1388. application-defined type (here, PMYCNRREC). 
  1389.  
  1390.  
  1391. ΓòÉΓòÉΓòÉ 4.3.3. Basic Record Operations ΓòÉΓòÉΓòÉ
  1392.  
  1393. Inserting and Removing Records 
  1394.  
  1395. The container makes a distinction between allocation and insertion of records; 
  1396. likewise, a similar distinction is made between removing a record and freeing 
  1397. the memory consumed by the record.  Allocation is accomplished by sending the 
  1398. control a CM_ALLOCRECORD message, while insertion is done by sending a 
  1399. CM_INSERTRECORD message. 
  1400.  
  1401. The CM_ALLOCRECORD requires the number of additional bytes needed in mpParm1 
  1402. and the number of records to allocate in mpParm2.  If more than one record is 
  1403. allocated, a linked list of the records is returned (with the linked being the 
  1404. preccNextRecord field in the MINIRECORDCORE structure); otherwise, a pointer to 
  1405. the record is returned.  The container will initialize the entire structure to 
  1406. "nothing" (meaning no icon, no text, etc.).  It is your responsibility to 
  1407. "fill-in-the-blanks" so that something meaningful will appear in the control; 
  1408. for the icon view, these fields are the hptrIcon and pszIcon fields of the 
  1409. MINIRECORDCORE structure.  You should set them to the handle of the icon and to 
  1410. the pointer to the descriptive text to be displayed, respectively.  Using our 
  1411. MYCNRREC structure again as an example: 
  1412.  
  1413. ULONG ulExtra;
  1414. PMYCNRREC pmcrRecord;
  1415.  
  1416. ulExtra=sizeof(MYCNRREC)-sizeof(MINIRECORDCORE);
  1417.  
  1418. pmcrRecord=(PMYCNRREC)PVOIDFROMMR(WinSendMsg(hwndCnr,
  1419.                                              CM_ALLOCRECORD,
  1420.                                              MPFROMLONG(ulExtra),
  1421.                                              MPFROMSHORT(1)));
  1422. if (pmcrRecord!=NULL) {
  1423.    pmcrRecord->mrcCore.hptrIcon=WinLoadPointer(HWND_DESKTOP,
  1424.                                                NULLHANDLE,
  1425.                                                HPTR_PRODUCT);
  1426.    pmcrRecord->mcrCore.pszIcon=pmcrRecord->achText;
  1427.    strcpy(pmcrRecord->achText,"Thing-A-Ma-Jig");
  1428. } /* endif */
  1429.  
  1430. Once you have allocated, initialized, and are ready to insert your records, you 
  1431. need to describe the placement of the records to the container (via the 
  1432. RECORDINSERT structure) to the container.  An item of interest is that the 
  1433. container has two notions of order:  z-order and item-order. The former should 
  1434. be familiar because PM windows all have this concept.  The latter, however, is 
  1435. useful when you wish to enumerate the records in an order other than the 
  1436. z-order placement without affecting the appearance of the records in the 
  1437. container.  Continuing our example above: 
  1438.  
  1439. RECORDINSERT riInsert;
  1440.  
  1441. riInsert.cb=sizeof(RECORDINSERT);
  1442. riInsert.pRecordOrder=CMA_FIRST;    /* Insert at the head of the list */
  1443. riInsert.pRecordParent=NULL;        /* No parent record */
  1444. riInsert.fInvalidateRecord=TRUE;    /* Automatic invalidation of records */
  1445. riInsert.zOrder=CMA_TOP;            /* Place on top of siblings */
  1446. riInsert.cRecordsInsert=1;
  1447.  
  1448. WinSendMsg(hwndCnr,
  1449.            CM_INSERTRECORD,
  1450.            MPFROMP(pmcrRecord),
  1451.            MPFROMP(&riInsert));
  1452.  
  1453. A couple of important things should be noted here: 
  1454.  
  1455. o It is very inefficient to allocate and insert records one at a time.  If at 
  1456.   all possible, allocate many records and insert them all at once. 
  1457. o You can specify FALSE for the fInvalidateRecord field to cause the container 
  1458.   not to invalidate the records once they are inserted.  Doing this allows you 
  1459.   to reflow - or arrange - the records in the container before displaying them 
  1460.   ( using the CM_ARRANGE) message.  If you choose to do this, you must send a 
  1461.   CM_INVALIDATERECORD message specifying CMA_REPOSITION and CMA_ERASE to redraw 
  1462.   the container. 
  1463.  
  1464. To remove a record from the list, you use the CM_REMOVERECORD message.  If you 
  1465. choose not to have the container free the memory (using the CMA_FREE flag), you 
  1466. must also send a CM_FREERECORD message to return the memory to the system.  A 
  1467. "gotcha" here is that the first parameter of the two messages is a pointer to 
  1468. an array of pointers. Thus, if you are only removing one record, you need to 
  1469. specify a pointer to the record pointer: 
  1470.  
  1471. PMYCNRREC pmcrRecord;
  1472.  
  1473. /* Query the first record in the container */
  1474. pmcrRecord=(PMYCNRREC)PVOIDFROMMR(WinSendMsg(hwndCnr,
  1475.                                              CM_QUERYRECORD,
  1476.                                              MPFROMP(NULL),
  1477.                                              MPFROM2SHORT(CMA_FIRST,
  1478.                                                           CMA_ITEMORDER)));
  1479.  
  1480. /* Remove it and free the memory */
  1481. WinSendMsg(hwndCnr,
  1482.            CM_REMOVERECORD,
  1483.            MPFROMP(&pmcrRecord),
  1484.            MPFROMSHORT(CMA_FREE));
  1485.  
  1486. /* We now need to invalidate the container */
  1487. WinSendMsg(hwndCnr,
  1488.            CM_INVALIDATERECORD,
  1489.            MPFROMP(NULL),
  1490.            MPFROM2SHORT(0,CMA_REPOSITION|CMA_ERASE));
  1491.  
  1492. Arranging the Records 
  1493.  
  1494. Arranging the records is as simple as sending a CM_ARRANGE message.  This 
  1495. message takes no parameters. the record pointer: 
  1496.  
  1497. WinSendMsg(hwndCnr,
  1498.            CM_ARRANGE,
  1499.            0,
  1500.            0);
  1501.  
  1502.  
  1503. ΓòÉΓòÉΓòÉ 4.3.4. Using the CM_SETCNRINFO Message ΓòÉΓòÉΓòÉ
  1504.  
  1505. To change the value any of a multitude of attributes belonging to the 
  1506. container, you can use the CM_SETCNRINFO message.  This controls everything 
  1507. about the container including the current view type, which is probably its most 
  1508. widely used feature.  The way this message works is that you define a variable 
  1509. of type CNRINFO, set the appropriate fields, and send the message.  In the 
  1510. second parameter, you specify one or more flags which tells the container which 
  1511. fields to examine.  Thus, you do not have to initialize the entire structure 
  1512. for one field. the record pointer: 
  1513.  
  1514. CNRINFO ciInfo;
  1515.  
  1516. /* Change the view to icon view */
  1517. ciInfo.flWindowAttr=CV_ICON;
  1518.  
  1519. WinSendMsg(hwndCnr,
  1520.            CM_SETCNRINFO,
  1521.            MPFROMP(&ciInfo),
  1522.            MPFROMLONG(CMA_FLWINDOWATTR));
  1523.  
  1524. This provides a very limited example of the CM_SETCNRINFO message.  For more 
  1525. information about the CNRINFO structure see the Technical Reference, available 
  1526. with the Programming Toolkit. 
  1527.  
  1528.  
  1529. ΓòÉΓòÉΓòÉ 4.3.5. Basic Notifications ΓòÉΓòÉΓòÉ
  1530.  
  1531. The container will notify its owner via the WM_CONTROL message whenever any of 
  1532. a multitude of events occur.  Five of the more basic notifications are listed: 
  1533.  
  1534. Code                Meaning 
  1535. CN_ENTER            The user pressed ENTER or double clicked the mouse while 
  1536.                     the container had the focus. 
  1537. CN_HELP             The user pressed F1 while the container had the focus. 
  1538. CN_CONTEXTMENU      The user pressed the context menu key combination as 
  1539.                     defined on the System settings.  The default for the system 
  1540.                     is Ctrl+F10. 
  1541. CN_SETFOCUS         The container has received the focus. 
  1542. CN_KILLFOCUS        The container is losing the focus. 
  1543.  
  1544. Next month we'll briefly describe a few others and their meanings. 
  1545.  
  1546.  
  1547. ΓòÉΓòÉΓòÉ 4.3.6. Next Month ΓòÉΓòÉΓòÉ
  1548.  
  1549. Next month, we will look at the tree view as well as look at a few other 
  1550. notifications.  Also, we will build our first sample application using the 
  1551. concepts described here and in next month's article. 
  1552.  
  1553.  
  1554. ΓòÉΓòÉΓòÉ <hidden> Example Container Object Record ΓòÉΓòÉΓòÉ
  1555.  
  1556. Used as the object record type throughout this article, the definition is 
  1557. below: 
  1558.  
  1559. typedef struct _MYCNRREC {
  1560.    MINIRECORDCORE mrcCore;
  1561.    CHAR achText[256];
  1562.    ULONG ulNumSold;
  1563.    float fGrossIncome;
  1564.    float fNetIncome;
  1565.    float fTotalCost;
  1566.    float fNetProfit;
  1567. } MYCNRREC, *PMYCNRREC;
  1568.  
  1569.  
  1570. ΓòÉΓòÉΓòÉ 5. Columns ΓòÉΓòÉΓòÉ
  1571.  
  1572. o Questions and Answers 
  1573.  
  1574. o Introduction to PM 
  1575.  
  1576.  
  1577. ΓòÉΓòÉΓòÉ 5.1. Questions and Answers ΓòÉΓòÉΓòÉ
  1578.  
  1579. Welcome to this month's "Questions and Answers"!  Each month, I collect various 
  1580. questions sent to me via email and try to answer each directly; the ones that I 
  1581. feel contribute the most to developers, whether in terms of information or as a 
  1582. nifty trick to tuck into your cap, get published in this column. 
  1583.  
  1584. To submit a question, send mail to my email address - os2man@panix.com - and be 
  1585. sure to grant permission to publish your question (those that forget will not 
  1586. be considered for publication). 
  1587.  
  1588. This month's deluge of questions covered the following topics: 
  1589.  
  1590. o Using Presentation Parameters 
  1591. o Context-specific Dialogs 
  1592. o Adjusting the Priority of a Non-related Process 
  1593. o Hooking the Kernel APIs 
  1594. o Using MMPM/2 to Record and Playback Audio Samples 
  1595.  
  1596.  
  1597. ΓòÉΓòÉΓòÉ 5.1.1. Using Presentation Parameters ΓòÉΓòÉΓòÉ
  1598.  
  1599. Les Chan (chan@holo.ps.iit.nrc.ca) writes: 
  1600.  
  1601. How do I create buttons (and other standard classes) with custom fonts? I think 
  1602. the way to do this is with the last parameter in WinCreateWindow, which is 
  1603. PVOID pPresParams.  But I can't figure out how to use it. 
  1604.  
  1605. Also, once the window is created, one should be able to change the font with 
  1606. WinSetPresParams.  And I can't get this to work consistently (the window is 
  1607. created with pPresParams=NULL). 
  1608.  
  1609. So, what is the correct way to create and manipulate presentation parameters? 
  1610.  
  1611. To answer your second question first, the most common problem with using 
  1612. WinSetPresParam is not passing the correct values for the parameters; this 
  1613. often manifests itself when attempting to change the font of a control.  What 
  1614. most developers do not know, when using a string for the value of the 
  1615. presentation parameter, is that you must add one to the length for the `\0' 
  1616. byte at the end. 
  1617.  
  1618. WinSetPresParam(hwndButton,
  1619.                 PP_FONTNAMESIZE,
  1620.                 strlen("12.Helv"),
  1621.                 "12.Helv");
  1622.  
  1623. WinSetPresParam(hwndButton,
  1624.                 PP_FONTNAMESIZE,
  1625.                 strlen("12.Helv")+1,
  1626.                 "12.Helv");
  1627.  
  1628. Thus, the first example is incorrect and will yield indeterminable results, 
  1629. while the second will work as expected.  Using WinSetPresParam will work 
  1630. regardless of the value of pPresParam on the WinCreateWindow call. 
  1631.  
  1632. Your first question is a bit more complex, due to the fact that the online and 
  1633. hardcopy documentation for 1.x and 2.0 are incorrect.  Piecing together the 
  1634. information from all sources reaps the solution, however.  In the 
  1635. WinCreateWindow call, the last parameter is defined to be of type PVOID when in 
  1636. reality it is of type PPRESPARAMS.  This type is a variable length structure 
  1637. which contains one or more presentation parameters to be passed to the window 
  1638. (I won't review the structure definition, since you can do that on your own). 
  1639. By initializing this structure properly, you can set the appropriate 
  1640. characteristics on the call to WinCreateWindow as in the example below: 
  1641.  
  1642. ULONG ulSzFont;
  1643. BYTE abBuf[sizeof(PRESPARAMS)+256];
  1644. PPRESPARAMS pppParm;
  1645.  
  1646. ulSzFont=strlen("18.Helv")+1;
  1647.  
  1648. pppParm=(PPRESPARAMS)abBuf;
  1649. pppParm->cb=sizeof(PARAM)+ulSzFont-1;
  1650. pppParm->aparam[0].id=PP_FONTNAMESIZE;
  1651. pppParm->aparam[0].cb=ulSzFont;
  1652. strcpy(pppParm->aparam[0].ab,"18.Helv");
  1653.  
  1654. if (WinCreateWindow(hwndWnd,
  1655.                     WC_BUTTON,
  1656.                     "Test",
  1657.                     WS_VISIBLE|BS_PUSHBUTTON,
  1658.                     100,
  1659.                     100,
  1660.                     200,
  1661.                     100,
  1662.                     hwndWnd,
  1663.                     HWND_TOP,
  1664.                     1,
  1665.                     NULL,
  1666.                     pppParm)==NULLHANDLE) {
  1667.    WinAlarm(HWND_DESKTOP,WA_ERROR);
  1668.    return MRFROMSHORT(FALSE);
  1669. } /* endif */
  1670.  
  1671. An interesting note here is that, when testing this, this code did not result 
  1672. in an error, yet no button was displayed when I placed this in the WM_CREATE 
  1673. processing. 
  1674.  
  1675.  
  1676. ΓòÉΓòÉΓòÉ 5.1.2. Context-specific Dialogs ΓòÉΓòÉΓòÉ
  1677.  
  1678. A user who wishes to remain anonymous writes: 
  1679.  
  1680. I'm writing a program that is essentially a dialog.  I know how to do that. 
  1681. But I want to have a portion be dependant on another part, but don't know how 
  1682. to make that happen.  For example, when you click on an radio button in the top 
  1683. half, the bottom half changes so you can change settings for it. 
  1684.  
  1685. If you have any experience using the notebook, you can design your main dialog 
  1686. in a related fashion.  For each radio button in the top half, call WinLoadDlg 
  1687. to load an auxilliary dialog specific to the item that radio button represents. 
  1688. Then, when you receive the WM_CONTROL/ BN_CLICKED notification message, call 
  1689. WinShowWindow both to hide the currently displayed dialog and to display the 
  1690. dialog corresponding to the button selected. 
  1691.  
  1692. As a caveat, define the auxilliary dialogs as having no border and not having 
  1693. any frame controls (FCF_ flags).  You will also need to call WinSetWindowPos 
  1694. after loading them to set their position to be the lower half of the main 
  1695. dialog. 
  1696.  
  1697.  
  1698. ΓòÉΓòÉΓòÉ 5.1.3. Adjusting the Priority of a Non-related Process ΓòÉΓòÉΓòÉ
  1699.  
  1700. Roman Stangl (86505339awiwuw11.wu-wien.ac.at) writes: 
  1701.  
  1702. How can the priority of any running process be adjusted, without these 
  1703. processes being child processes of the program that wants to adjust the 
  1704. priority. 
  1705.  
  1706. The answer is that you can't, at least as far as I am aware.  If you have the 
  1707. source to the child processes, you can modify them to accept a command line 
  1708. parameter specifying the desired priority class and value and then have them 
  1709. call DosSetPriority. 
  1710.  
  1711.  
  1712. ΓòÉΓòÉΓòÉ 5.1.4. Hooking the Kernel APIs ΓòÉΓòÉΓòÉ
  1713.  
  1714. Roman Stangl (86505339awiwuw11.wu-wien.ac.at) again writes: 
  1715.  
  1716. How can the OS/2 API DosOpen() be hooked to trace write accesses to files, 
  1717. similar to a DOS TSR that hooks into INT21? 
  1718.  
  1719. The only way I know of to accomplish what your second question is asking is by 
  1720. writing your own IFS (installable file system).  You might be able to also do 
  1721. this using device monitors, but I cannot be sure. My apologies for the lack of 
  1722. a concrete answer to this. 
  1723.  
  1724.  
  1725. ΓòÉΓòÉΓòÉ 5.1.5. Using MMPM/2 to Record and Playback Audio Samples ΓòÉΓòÉΓòÉ
  1726.  
  1727. Marc Van-Woerkom (Marc_Van-Woerkom@ac3.maus.de) writes: 
  1728.  
  1729. I own a Soundblaster card and want to use it under OS/2! 
  1730.  
  1731. It's FM synthesizers generate some nice sounds but I think the best effects are 
  1732. produced by it's digital channel. For this I need a driver/routines that allow 
  1733. me to record and play a sample. 
  1734.  
  1735. A solution already exists (sbos2 package) but that's only an intermediate 
  1736. solution -- with OS/2 2.1 MMPM/2 will become the standard to deal with. 
  1737.  
  1738. So is there a MMPM/2 API which allows me to record/play samples? 
  1739.  
  1740. In the Summer 1992 issue of the OS/2 Developer magazine, there is an article 
  1741. entitled "Listen to the Sounds: The MMPM/2 Audio Subsystem" starting on page 
  1742. 98.  In this article, the author discusses how both audio samples and MIDI 
  1743. sequences are used in the MMPM/2 system.  Since I personally have no experience 
  1744. using MMPM/2, I will not try to explain the article in order to avoid confusing 
  1745. anyone, but will consider the reference as an affirmative answer to your 
  1746. question. 
  1747.  
  1748. Now that the magazine is published by Miller Freeman, I am unsure if back 
  1749. issues can be ordered.  If so, the IBM Mechanicsburg number is G362-0001; if 
  1750. not, you can try contacting the magazine via the Internet at the address 
  1751. os2mag@vnet.ibm.com for the possibility of article reprints. 
  1752.  
  1753.  
  1754. ΓòÉΓòÉΓòÉ 5.2. Introduction to PM Programming - Part III ΓòÉΓòÉΓòÉ
  1755.  
  1756.                     Introduction to PM Programming - Part III
  1757.  
  1758.                                    Gavin Baker
  1759.                           (demogrb@lust.latrobe.edu.au)
  1760.  
  1761.  
  1762. ΓòÉΓòÉΓòÉ 5.2.1. Introduction ΓòÉΓòÉΓòÉ
  1763.  
  1764.   Introduction 
  1765.  
  1766. Menus, dialog boxes and icons are all examples of Resources in OS/2.  Resources 
  1767. are stored in their own read-only segment within the executable file (or DLL), 
  1768. can be shared between multiple instances of a program, and are normally loaded 
  1769. only when required at runtime rather than at the load time of the application. 
  1770.  
  1771. The most commonly used resource types along with their definition are shown 
  1772. below: 
  1773.  
  1774. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1775. ΓöéType                ΓöéDescription                   Γöé
  1776. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1777. ΓöéACCELTABLE          ΓöéKeyboard Accelerator table    Γöé
  1778. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1779. ΓöéBITMAP              ΓöéBitmap                        Γöé
  1780. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1781. ΓöéDIALOG              ΓöéDialog box template           Γöé
  1782. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1783. ΓöéFONT                ΓöéFont                          Γöé
  1784. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1785. ΓöéMENU                ΓöéMenu definition               Γöé
  1786. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1787. ΓöéMESSAGETABLE        ΓöéApplication Message Strings   Γöé
  1788. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1789. ΓöéPOINTER             ΓöéIcon or mouse pointer         Γöé
  1790. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1791. ΓöéRCDATA*             ΓöéCustom-defined resource       Γöé
  1792. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1793. ΓöéSTRINGTABLE         ΓöéStrings                       Γöé
  1794. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1795.  
  1796. Resources are created in two ways (depending on the type of resource).  They 
  1797. are either text or binary. The binary resources are POINTER, BITMAP, and FONT. 
  1798. All the other resources are textual. The RCDATA type is special, as it allows 
  1799. the programmer to define a custom structure for a resource. 
  1800.  
  1801. The RC.EXE program is called the Resource Compiler, and it takes the your 
  1802. source file and compiles it into a binary form (.RES).  It also binds the .RES 
  1803. file with your executable. 
  1804.  
  1805. We will examine the general syntax of resources and the structure of the RC 
  1806. file, and then examine each type in detail. 
  1807.  
  1808.  
  1809. ΓòÉΓòÉΓòÉ 5.2.2. Scope ΓòÉΓòÉΓòÉ
  1810.  
  1811.   Scope 
  1812.  
  1813. I am assuming that you are a competent C programmer, and have a working 
  1814. knowledge of OS/2 from a user's perspective. The sample code here was produced 
  1815. with Borland's Resource Workshop for PM and tested with the OS/2 Resource 
  1816. Compiler (RC). 
  1817.  
  1818.  
  1819. ΓòÉΓòÉΓòÉ 5.2.3. Syntax and the RC File ΓòÉΓòÉΓòÉ
  1820.  
  1821.   Syntax and the RC File 
  1822.  
  1823. Resources are defined in a text file with the .RC extension. There are a number 
  1824. of keywords for the different resource types, and each keyword defines one 
  1825. resource.  Resources are referenced by an identifier, which takes the form of a 
  1826. C #define.  Since the Resource Compiler (RC.EXE) supports C-like #includes and 
  1827. #defines, it is convenient to have all the symbols defined in one header file 
  1828. for the resources and their IDs. (Obviously they must have unique numbers). 
  1829. Resources are usually named according a certain convention - ID followed by a 
  1830. single letter denoting the resource type, an underscore and then a descriptive 
  1831. name.  Here are some examples: 
  1832.  
  1833. #define  IDM_FILE    10         /* the ID of the FILE Menu      */
  1834. #define  IDS_ERROR   300        /* the ID of the ERROR String   */
  1835. #define  IDD_OPTIONS 436        /* the ID of the OPTIONS Dialog */
  1836.  
  1837. Generally speaking, a resource statement consists of the following: 
  1838.  
  1839. TYPE ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ RESOURCE DEFINITION ΓöÇΓöÇΓöÇΓöÇΓöñ
  1840.                        Γöé           Γöé
  1841.                        Γöé  MEMORY   Γöé
  1842.                        ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  1843.  
  1844. Due to the differing nature of resources, it is easier to show the syntax for 
  1845. each type's definition rather than to generalize here. 
  1846.  
  1847. The options refer to the Memory Options, which specify how OS/2 treats the 
  1848. memory occupied by the resource.  The memory options are as follows: 
  1849.  
  1850. ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1851. ΓöéOption              ΓöéMeaning                                                     Γöé
  1852. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1853. ΓöéFIXED or            ΓöéResource remains at a fixed point in memory                 Γöé
  1854. ΓöéMOVEABLE*           ΓöéResource can be moved by the system in memory               Γöé
  1855. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1856. ΓöéPRELOAD or          ΓöéResource is loaded at load-time                             Γöé
  1857. ΓöéLOADONCALL*         ΓöéResource is loaded when first referenced (run-time)         Γöé
  1858. Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöñ
  1859. ΓöéDISCARDABLE         ΓöéResource can be discarded if not needed                     Γöé
  1860. ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÿ
  1861.  
  1862. Note that the default options are marked with an asterisk.  These options apply 
  1863. to all of the resource types. 
  1864.  
  1865.  
  1866. ΓòÉΓòÉΓòÉ 5.2.4. Resources ΓòÉΓòÉΓòÉ
  1867.  
  1868.   Resources 
  1869.  
  1870. In the following sections we will see each type of resource (at least the most 
  1871. common ones) and some examples, along with how to use them in your programs. 
  1872.  
  1873. The syntax diagrams follow those conventions used in the Command Reference, but 
  1874. also note that keywords are underlined. 
  1875.  
  1876.  
  1877. ΓòÉΓòÉΓòÉ 5.2.4.1. String Table ΓòÉΓòÉΓòÉ
  1878.  
  1879.   String Table 
  1880.  
  1881.   Syntax 
  1882.  
  1883. STRINGTABLE ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ
  1884.                               Γöé           Γöé
  1885.                               Γöé  MEMORY   Γöé
  1886.                               ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  1887.  
  1888.          ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1889.          Γöé                             Γöé
  1890.                                       Γöé
  1891.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓöÇΓöÇΓöÇ STRING ΓöÇΓöÇΓö┤ΓöÇΓöÇ
  1892.  
  1893.  
  1894. ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇΓöñ
  1895.  
  1896.   Notes 
  1897.  
  1898. String tables are used to keep all of the static text which is used in a 
  1899. program in one place, thus making it easier to manage, and also to maintain 
  1900. versions in multiple languages.  Ideally the program source code should be free 
  1901. of static or literal text, and instead use a STRINGTABLE to manage the text. 
  1902. Strings are loaded by using the WinLoadString call, and once loaded, are used 
  1903. exactly the same way as a normal string. 
  1904.  
  1905.  Example 
  1906.  
  1907. STRINGTABLE ID_ERRORS FIXED
  1908. BEGIN
  1909.     IDS_FILENOTFOUND       "Sorry - I can't find that file anywhere!"
  1910.     IDS_NOGAMES            "Games are not allowed during office hours."
  1911.     IDS_BYEBYE             "Are you sure you really truly want to go?"
  1912. END
  1913.  
  1914.   Output 
  1915.  
  1916. There is no output as such from this resource - you would use it in your 
  1917. program like this: 
  1918.  
  1919. WinLoadString(hab, NULLHANDLE, IDS_BADCMD, MAXERRORLEN, pszError);
  1920. WinMessageBox(HWND_DESKTOP,HWND_DESKTOP,pszError,"Error!",0,
  1921.               MB_CUACRITICAL | MB_OK);
  1922.  
  1923. This will load an error message from the executable file and display an error 
  1924. message in a box. 
  1925.  
  1926.  
  1927. ΓòÉΓòÉΓòÉ 5.2.4.2. Message Table ΓòÉΓòÉΓòÉ
  1928.  
  1929.   Message Table 
  1930.  
  1931.   Syntax 
  1932.  
  1933. MESSAGETABLE ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ
  1934.                                Γöé           Γöé
  1935.                                Γöé  MEMORY   Γöé
  1936.                                ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  1937.  
  1938.          ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1939.          Γöé                             Γöé
  1940.                                       Γöé
  1941.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓöÇΓöÇΓöÇ STRING ΓöÇΓöÇΓö┤ΓöÇΓöÇ
  1942.  
  1943.  
  1944. ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇΓöñ
  1945.  
  1946.   Notes 
  1947.  
  1948. A Message table works just the same way as a STRINGTABLE. Most applications use 
  1949. a STRINGTABLE, or use the MKMSGF (the Make MeSsaGe File utility, documented in 
  1950. the Toolkit Tools Reference). 
  1951.  
  1952.  Example 
  1953.  
  1954. MESSAGETABLE ID_ERRORS
  1955. BEGIN
  1956.     IDM_PRINTEDOK     "The file has been successfully printed."
  1957.     IDM_SYNTAX        "A syntax error was found on line %1."
  1958. END
  1959.  
  1960.  
  1961. ΓòÉΓòÉΓòÉ 5.2.4.3. Menu ΓòÉΓòÉΓòÉ
  1962.  
  1963.   Menu 
  1964.  
  1965.   Syntax 
  1966.  
  1967. MENU ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ
  1968.                        Γöé           Γöé
  1969.                        Γöé  MEMORY   Γöé
  1970.                        ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  1971.  
  1972.       ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  1973.       Γöé                                                                                 Γöé
  1974.                                                                                        Γöé
  1975.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ SUBMENU ΓöÇΓöÇΓöÇΓöÇ TEXT ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓöÇΓöÇΓöÇ STYLE ΓöÇΓöÇΓöÇΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ          Γöé
  1976.                                                                                         Γöé
  1977.          ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ   Γöé
  1978.          Γöé                                                                          Γöé   Γöé
  1979.                                                                                    Γöé   Γöé
  1980.       ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ MENUITEM ΓöÇΓöÇΓöÇΓöÇ TEXT ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓöÇΓöÇΓöÇ STYLE ΓöÇΓöÇΓöÇΓöÇ ATTRIBUTES ΓöÇΓöÇΓö┤ΓöÇ Γöé
  1981.                                                                                         Γöé
  1982.                                                                                         Γöé
  1983.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö┤ΓöÇΓöÇΓöÇ
  1984.  
  1985.  
  1986. ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇΓöñ
  1987.  
  1988.   Notes 
  1989.  
  1990. I hope this diagram isn't too confusing - if you examine it, all it means is 
  1991. that a MENU consists of one or more SUBMENUs, which consist of one or more 
  1992. MENUITEMs.  You can leave off the style and attributes if you don't want to 
  1993. specify any (see the example).  Put a tilde ~ character in to specify that the 
  1994. following letter will be the underlined shortcut key. 
  1995.  
  1996. Note:  If you make the ID of the menu the same as your main window that you 
  1997.        create with WinCreateStdWindow and use the FCF_MENU style when you 
  1998.        create it, PM will automatically load the menu and assign it to the 
  1999.        window. 
  2000.  
  2001.  Example 
  2002.  
  2003. MENU ID_MAIN
  2004. BEGIN
  2005.     SUBMENU "~File", IDM_FILE
  2006.     BEGIN
  2007.         MENUITEM "~New",       IDM_FILENEW
  2008.         MENUITEM "~Open...",   IDM_FILEOPEN
  2009.         MENUITEM "~Save",      IDM_FILESAVE
  2010.         MENUITEM "Save ~As...",IDM_FILESAVEAS
  2011.     END
  2012.     SUBMENU "Fon~t", IDM_FONT
  2013.     BEGIN
  2014.         MENUITEM "~Small",     IDM_FONTSMALL
  2015.         MENUITEM "~Medium",    IDM_FONTMED,    MIS_TEXT, MIA_CHECKED
  2016.         MENUITEM "~Large",     IDM_FONTLARGE
  2017.         MENUITEM SEPARATOR
  2018.         MENUITEM "~Options...",IDM_FONTOPTIONS
  2019.     END
  2020. END
  2021.  
  2022.   Output 
  2023.  
  2024.  
  2025. ΓòÉΓòÉΓòÉ 5.2.4.4. Dialog ΓòÉΓòÉΓòÉ
  2026.  
  2027.   Dialog 
  2028.  
  2029.   Syntax  The dialog template itself: 
  2030.  
  2031. DLGTEMPLATE ΓöÇΓöÇΓöÇΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ
  2032.                               Γöé           Γöé
  2033.                               Γöé  MEMORY   Γöé
  2034.                               ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  2035.  
  2036.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ DIALOG ΓöÇΓöÇΓöÇΓöÇ TITLE, ID, X, Y, WIDTH, HEIGHT ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ BEGIN ΓöÇΓöÇΓöÇΓöÇ
  2037.                                                           Γöé          Γöé
  2038.                                                           ΓööΓöÇ STYLES ΓöÇΓöÿ
  2039.  
  2040.             ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
  2041.             Γöé                       Γöé
  2042.                                    Γöé
  2043.       ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ CONTROL DEFINITION ΓöÇΓö┤ΓöÇΓöÇ
  2044.  
  2045.  
  2046.    ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇ
  2047.  
  2048.  
  2049. ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ END ΓöÇΓöÇΓöÇΓöÇΓöñ
  2050.  
  2051. The Control Definition: 
  2052.  
  2053. CONTROL ΓöÇΓöÇΓöÇΓöÇ TEXT, ΓöÇΓöÇΓöÇΓöÇ ID, ΓöÇΓöÇΓöÇΓöÇ X, ΓöÇΓöÇΓöÇΓöÇ Y, ΓöÇΓöÇΓöÇΓöÇ
  2054.  
  2055.  
  2056. ΓöÇ ΓöÇ ΓöÇΓöÇΓöÇΓöÇ WIDTH, ΓöÇΓöÇΓöÇΓöÇ HEIGHT, ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇΓöñ
  2057.                                 Γöé          Γöé
  2058.                                 ΓööΓöÇ STYLES ΓöÇΓöÿ
  2059.  
  2060.   Notes 
  2061.  
  2062. A dialog template is used to define a dialog, which contains many controls. The 
  2063. control can be a custom control, or one of the following: 
  2064.  
  2065. Γûá  AUTOCHECKBOX 
  2066.  
  2067. Γûá  AUTORADIOBUTTON 
  2068.  
  2069. Γûá  CHECKBOX 
  2070.  
  2071. Γûá  DEFPUSHBUTTON 
  2072.  
  2073. Γûá  GROUPBOX 
  2074.  
  2075. Γûá  PUSHBUTTON 
  2076.  
  2077. Γûá  RADIOBUTTON 
  2078.  
  2079. Γûá  ENTRYFIELD 
  2080.  
  2081. to name a few.  Consult the Toolkit documentation for a complete description of 
  2082. all the different controls.  Once you know how to use one, the others work 
  2083. basically the same. 
  2084.  
  2085.  Example 
  2086.  
  2087. This example was produced with Borland's Resource Workshop for PM (part of 
  2088. Borland C++ for OS/2), which makes it easy to visually design dialogs and other 
  2089. resources. The IBM Toolkit also includes a Dialog Editor. 
  2090.  
  2091. As you can see, a reasonably simple dialog can get fairly complex.  If you were 
  2092. to write this by hand it would take hours to figure out the X and Y positions, 
  2093. flags, etc.  This is not practical for anything but the simplest of dialogs, so 
  2094. a dialog editor (such as the two mentioned above) is invaluable. 
  2095.  
  2096. This may seem complicated, but it is fairly straightforward.  Everything except 
  2097. the buttons is defined as a CONTROL (a generic way of specifying a control). 
  2098. The type of control is given in the flags, for example the comment edit field 
  2099. is defined as a WC_ENTRYFIELD, and has its own specific flags (ES_LEFT and the 
  2100. others).  There are lots of flags specified (more than if you had done it by 
  2101. hand) but most have reasonable defaults. 
  2102.  
  2103. Three things to note: 
  2104.  
  2105. Γûá  The order is important - it is the order the user tabs through in. 
  2106.  
  2107. Γûá  The WS_TABSTOP flag must be specified if you want the user to be able to tab 
  2108. to the control under keyboard control. 
  2109.  
  2110. Γûá  Groups (WS_GROUP) are mainly used to group together automatic radio buttons, 
  2111. so they turn each other off and on. 
  2112.  
  2113. DLGTEMPLATE 1
  2114. BEGIN
  2115.   DIALOG "Sample Dialog", 100, 30, 90, 300, 150, WS_VISIBLE, FCF_SYSMENU | FCF_TITLEBAR
  2116.   BEGIN
  2117.     CONTROL "", 109, 44, 104, 72, 35, WC_COMBOBOX, CBS_DROPDOWN | ES_ANY | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2118.     CONTROL "", 112, 156, 128, 133, 9, WC_ENTRYFIELD, ES_LEFT | ES_AUTOSCROLL | ES_MARGIN | ES_ANY | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2119.     CONTROL "~Preload", 102, 20, 96, 50, 10, WC_BUTTON, BS_AUTORADIOBUTTON | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2120.     CONTROL "~Load on Call", 103, 20, 80, 72, 10, WC_BUTTON, BS_AUTORADIOBUTTON | WS_VISIBLE | WS_TABSTOP
  2121.     CONTROL "~Fixed", 104, 104, 96, 50, 10, WC_BUTTON, BS_AUTORADIOBUTTON | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2122.     CONTROL "~Moveable", 105, 104, 80, 50, 10, WC_BUTTON, BS_AUTORADIOBUTTON | WS_VISIBLE | WS_TABSTOP
  2123.     CONTROL "~Discardable", 106, 20, 56, 68, 10, WC_BUTTON, BS_AUTOCHECKBOX | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2124.     CONTROL "", 107, 172, 84, 48, 12, WC_SPINBUTTON, SPBS_MASTER | SPBS_ALLCHARACTERS | SPBS_JUSTLEFT | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2125.     CONTROL "", 108, 236, 84, 48, 12, WC_SPINBUTTON, SPBS_MASTER | SPBS_ALLCHARACTERS | SPBS_JUSTLEFT | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2126.     CONTROL "", 113, 172, 56, 48, 12, WC_SPINBUTTON, SPBS_MASTER | SPBS_ALLCHARACTERS | SPBS_JUSTLEFT | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2127.     CONTROL "", 114, 236, 56, 48, 12, WC_SPINBUTTON, SPBS_MASTER | SPBS_ALLCHARACTERS | SPBS_JUSTLEFT | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2128.     CONTROL "", 121, 16, 26, 268, 12, WC_ENTRYFIELD, ES_LEFT | ES_AUTOSCROLL | ES_MARGIN | ES_ANY | WS_VISIBLE | WS_GROUP | WS_TABSTOP
  2129.     CONTROL "~Memory Options", 101, 10, 48, 150, 72, WC_STATIC, SS_GROUPBOX | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE | WS_GROUP
  2130.     CONTROL "T~ype", 110, 8, 128, 27, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE | WS_GROUP
  2131.     CONTROL "~Text", 111, 130, 128, 24, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE | WS_GROUP
  2132.     CONTROL "X", 115, 172, 96, 32, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE
  2133.     CONTROL "Size & Position", 116, 163, 48, 129, 72, WC_STATIC, SS_GROUPBOX | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE | WS_GROUP
  2134.     CONTROL "Y", 117, 238, 96, 32, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE
  2135.     CONTROL "Width", 118, 172, 72, 45, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE
  2136.     CONTROL "Height", 119, 236, 72, 45, 8, WC_STATIC, SS_TEXT | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE
  2137.     CONTROL "Comment", 120, 10, 20, 282, 28, WC_STATIC, SS_GROUPBOX | DT_LEFT | DT_TOP | DT_MNEMONIC | WS_VISIBLE | WS_GROUP
  2138.     DEFPUSHBUTTON "OK", DID_OK, 6, 4, 51, 14
  2139.     PUSHBUTTON "Cancel", DID_CANCEL, 60, 4, 51, 14
  2140.     PUSHBUTTON "Help", 998, 114, 4, 51, 14, BS_HELP
  2141.   END
  2142. END
  2143.  
  2144.   Output 
  2145.  
  2146.  
  2147. ΓòÉΓòÉΓòÉ 5.2.4.5. Fonts, Icons, Pointers, and Bitmaps ΓòÉΓòÉΓòÉ
  2148.  
  2149.   Fonts, Icons, Pointers, and Bitmaps 
  2150.  
  2151.   Syntax 
  2152.  
  2153. ΓöÇΓö¼ΓöÇ FONT    ΓöÇΓö¼ΓöÇ IDENTIFIER ΓöÇΓö¼ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö¼ΓöÇ FILENAME ΓöÇΓöÇΓöÇΓöÇΓöñ
  2154.  Γöé  BITMAP   Γöé               Γöé  MEMORY   Γöé
  2155.  ΓööΓöÇ POINTER ΓöÇΓöÿ               ΓööΓöÇ OPTIONS ΓöÇΓöÿ
  2156.  
  2157.   Notes 
  2158.  
  2159. Fonts, icons, pointers and bitmaps are all treated in the same way. (In fact 
  2160. icons and pointers are more or less identical). They are all defined externally 
  2161. in their own binary file, and are bound in when the resources are compiled. 
  2162.  
  2163. There are editors available to design your own binary resources. An Icon Editor 
  2164. (also used for pointers and small bitmaps) is included in base OS/2, and there 
  2165. is a Font Editor in the Toolkit. 
  2166.  
  2167.  Example 
  2168.  
  2169. BITMAP IDB_SMILEY  Smiley.Bmp
  2170. ICON   IDI_MYPROG  Whiz.Ico
  2171. FONT   IDF_BIGFONT Large.Fnt
  2172.  
  2173.   Output 
  2174.  
  2175. <Insert your favourite graphic here> 
  2176.  
  2177.  
  2178. ΓòÉΓòÉΓòÉ 5.2.5. Roundup ΓòÉΓòÉΓòÉ
  2179.  
  2180.   Roundup 
  2181.  
  2182. Well, there you have Resources in a nutshell.  You will find that tools such as 
  2183. Borland's Resource Workshop and those included with IBM's Toolkit can save you 
  2184. from ever having to understand all that we have just discussed, as you can 
  2185. point and click and the work is done for you. 
  2186.  
  2187. However, it is very useful to know just how resources are created as it gives 
  2188. you a better understanding of just what you are doing. 
  2189.  
  2190. Now for those of you who have eagerly gone to consult your manuals (or the 
  2191. header files for that matter), you will have noticed that I left out a few 
  2192. resource types.  I did this to save both time and space, and also because they 
  2193. are infrequently used.  I won't dare say that it is left as an excercise for 
  2194. the reader, but if there is enough demand I will cover the remaining types in a 
  2195. later article. 
  2196.  
  2197.  
  2198. ΓòÉΓòÉΓòÉ 5.2.6. What Next? ΓòÉΓòÉΓòÉ
  2199.  
  2200.   What Next? 
  2201.  
  2202. Next we look at the Graphics Programming Interface (GPI). 
  2203.  
  2204. I would love to hear from you about what you thought, how useful it was, 
  2205. whether or not there was too much or not enough information, if it was too 
  2206. wordy or too simple - in short any and all comments are most welcome. Also, if 
  2207. there is something specific you would like to see covered, drop me a line too. 
  2208.  
  2209.  
  2210. ΓòÉΓòÉΓòÉ 5.2.7. Bibliography ΓòÉΓòÉΓòÉ
  2211.  
  2212.   Bibliography 
  2213.  
  2214. The following references were used in the preparation of this article: 
  2215.  
  2216. Γûá  OS/2 Version 2.0 - The Redbooks 
  2217.  
  2218. Γûá  OS/2 Version 2.0 Technical Library 
  2219.  
  2220. The following products were mentioned: 
  2221.  
  2222. Γûá  IBM OS/2 Toolkit Version 2.0 
  2223.  
  2224. Γûá  Borland C++ for OS/2 Version 1.0 
  2225.  
  2226.  
  2227. ΓòÉΓòÉΓòÉ 6. Future Attractions ΓòÉΓòÉΓòÉ
  2228.  
  2229. Coming up in the future, we have: 
  2230.  
  2231. o Introduction to PM Part 4 
  2232.  
  2233. o Writing Installable File Systems 
  2234.  
  2235. o Getting Started with IPF 
  2236.  
  2237. o And much more! 
  2238.  
  2239.  
  2240. ΓòÉΓòÉΓòÉ 7. Contributors to this issue ΓòÉΓòÉΓòÉ
  2241.  
  2242. o Andre Asselin 
  2243.  
  2244. o Gavin R Baker 
  2245.  
  2246. o Steve Luzynski 
  2247.  
  2248. o Charles Oldham 
  2249.  
  2250. o Larry Salomon 
  2251.  
  2252.  
  2253. ΓòÉΓòÉΓòÉ 7.1. Andre Asselin ΓòÉΓòÉΓòÉ
  2254.  
  2255. Andre Asselin recently graduated Cum Laude from Rensselaer Polytechnic 
  2256. Institute with a Bachelor of Science degree in Computer Science.  He has worked 
  2257. with OS/2 since version 1.3, including several beta copies of version 2.0, and 
  2258. also has extensive experience with MS-DOS and Microsoft Windows.  He has 
  2259. co-oped twice in IBM's TCP/IP Development Department in Raleigh NC, where his 
  2260. responsibilities included the NFS client and server components of TCP/IP for 
  2261. OS/2.  In August, he will be rejoining the group full time. 
  2262.  
  2263. Andre is also a member of Alpha Sigma Phi Fraternity, and enjoys hockey, the 
  2264. beach, and a good science fiction novel.  He can be reached via email at 
  2265. assela@rpi.edu or on CompuServe at 73765,673. 
  2266.  
  2267.  
  2268. ΓòÉΓòÉΓòÉ 7.2. Gavin R Baker ΓòÉΓòÉΓòÉ
  2269.  
  2270.   Gavin R Baker 
  2271.  
  2272. Gavin R Baker is the man behind  ThinkSoft, a consulting firm based in 
  2273. Melbourne Australia which specialises in developing custom software. He is an 
  2274. active member of Team OS/2, and is the Editor for the Victorian Independent 
  2275. OS/2 Developer's Group (VioDevGrp). When he isn't programming, he is also a 
  2276. musician, an actor, and wastes lots of time reading Net News. He can be 
  2277. contacted thusly: 
  2278.  
  2279. net: demogrb@lust.latrobe.edu.au
  2280. cis: 100026,270
  2281.  
  2282.  
  2283. ΓòÉΓòÉΓòÉ 7.3. Steve Luzynski ΓòÉΓòÉΓòÉ
  2284.  
  2285. Steve Luzynski is the editor and creator of this magazine. He is currently a 
  2286. Computer Engineering student at University of Missouri at Columbia, after 
  2287. leaving Case Western Reserve University in Cleveland, OH, where it was just too 
  2288. cold. Steve has released several small programs for IBM's TCP/IP using Pat 
  2289. Mueller's rxSock library for REXX. He is currently working on the ultimate file 
  2290. manager, designed in conjuction with several hard-core DOS file manager users. 
  2291. It should see release as soon as Steve figures out how exactly to do all of 
  2292. this cool C++ 'object' stuff in OS/2 PM. Did you know you can't export a member 
  2293. function of a class? <sigh> 
  2294.  
  2295. Steve can by reached via e-mail at: 
  2296.  
  2297. Internet  - sal8@po.cwru.edu
  2298.        sluzynski@delphi.com
  2299.        72677.2140@compuserve.com
  2300.        Steve.Luzynski@f304.n280.z1.fidonet.org
  2301. Delphi   - sluzynski
  2302. Compuserve - 72677,2140
  2303. FidoNet   - Steve Luzynski @ 1:280/304 (Multitasking Systems, K.C., MO)
  2304.  
  2305. The old fashioned kind of mail can currently find Steve home for the summer at: 
  2306.  
  2307. Steve Luzynski
  2308. 3604 S. 10th ST CT
  2309. Blue Springs, MO 64015-6238
  2310.  
  2311.  
  2312. ΓòÉΓòÉΓòÉ 7.4. Charles Oldham ΓòÉΓòÉΓòÉ
  2313.  
  2314. Charles R. (C. R.) Oldham resides in Mesa, Arizona with his wife Amy.  He is 
  2315. currently working as the systems analyst for the North Central Association, a 
  2316. non-profit organization that accredits schools in the 20 state region roughly 
  2317. in the central United States.  C. R. is an experienced Dos, Macintosh, and Unix 
  2318. programmer who is eagerly moving into the area of OS/2 applications development 
  2319. and is trying to take as many people with him as he can. 
  2320.  
  2321. C. R. can be reached via Internet email or snail mail at the following 
  2322. addresses: 
  2323.  
  2324. Internet Email:  cro@socrates.ed.asu.edu
  2325.  
  2326. U. S. Mail:      C. R. Oldham
  2327.                  North Central Association
  2328.                  Arizona State University
  2329.                  Tempe, AZ  85287-3011
  2330.  
  2331.  
  2332. ΓòÉΓòÉΓòÉ 7.5. Larry Salomon ΓòÉΓòÉΓòÉ
  2333.  
  2334. Larry Salomon wrote his first Presentation Manager application for OS/2 version 
  2335. 1.1 in 1989.  Since that time, he has written numerous VIO and PM applications, 
  2336. including the Scramble applet included with OS/2 and the I-Brow/Magnify/Screen 
  2337. Capture trio included with the IBM Professional Developers Kit CD-ROM currently 
  2338. being distributed by IBM.  Currently, he works for International Masters 
  2339. Publishers in Stamford, Connecticut and resides in Bellerose, New York with his 
  2340. wife Lisa. 
  2341.  
  2342.  
  2343. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2344.  
  2345. EMX/GCC can be retrieved from the official OS/2 anonymous FTP site, ftp-os2. 
  2346. nmsu.edu, in the directory /pub/os2/2.x/unix/gnu/emx-0.8f.  An installation 
  2347. guide for the system can be found in the first issue of EDM/2. 
  2348.  
  2349.  
  2350. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2351.  
  2352. DevHlps - A set of calls available to IFSs and device drivers to perform common 
  2353. functions, such as allocating memory. 
  2354.  
  2355.  
  2356. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2357.  
  2358. Doscalls - Any of the DosXxx calls available in OS/2, such as DosOpen, DosRead, 
  2359. etc. 
  2360.  
  2361.  
  2362. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2363.  
  2364. FSD (File System Driver) - A system extension that allows OS/2 to access files 
  2365. stored in different disk formats or across a network.  Also called an IFS. 
  2366.  
  2367.  
  2368. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2369.  
  2370. FSH (File System Helpers) - A set of calls available to IFSs that perform 
  2371. common functions, such as allocating memory and managing semaphores. 
  2372.  
  2373.  
  2374. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2375.  
  2376. GDT (Global Descriptor Table) - The table of selectors that are valid across 
  2377. all processes. 
  2378.  
  2379.  
  2380. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2381.  
  2382. IFS (Installable File System) - A system extension that allows OS/2 to access 
  2383. files stored in different disk formats or across a network.  Also called an 
  2384. FSD. 
  2385.  
  2386.  
  2387. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2388.  
  2389. IPE (Internal Processing Error) - An unrecoverable system halt caused by buggy 
  2390. ring 0 code. 
  2391.  
  2392.  
  2393. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2394.  
  2395. LDT (Local Descriptor Table) - The table of selectors that is allocated on a 
  2396. per process basis.  Every process has its own LDT.  A particular LDT selector 
  2397. is valid only in its own process. 
  2398.  
  2399.  
  2400. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2401.  
  2402. NFS (Network File System) - A protocol developed by Sun Microsystems to allow 
  2403. UNIX machines to share files across a network. 
  2404.  
  2405.  
  2406. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2407.  
  2408. UNC (Universal Naming Convention) - The '\\server\path\file' naming convention, 
  2409. where 'server' refers to the server the file is on. 
  2410.  
  2411.  
  2412. ΓòÉΓòÉΓòÉ <hidden>  ΓòÉΓòÉΓòÉ
  2413.  
  2414. VMS - DEC's proprietary operating system for its VAX series of computers. One 
  2415. of the nice features it supports is version levels for files (sort of an 
  2416. automatic backup).