throbber
Microsoft® Programming Series
`_
`ir
`
`
`=
`
`Included
`
`Powered by ce

`

`rogramming
`
`
`Includes
`Windows CE >
`Platform
`SDKs
`
`“DOUG’S CODE
`DEMONSTRATES
`A PERFECT GRASP
`OF WINDOWS CE—
`CRAFTY AND ELEGANT.”
`—Charles Petzold, author,
`Programming Windows
`
`Microsoft Corp. Exhibit 1058
`
`The
`definitive
`guide to
`programming
`the Windows CE
`API
`
`Douglas Boling
`
`|
`
`Microsoft Corp. Exhibit 1058
`
`

`

`PROGRAMMING
`MICROSOFT:
`Winpows’ CE
`
`Douglas Boling
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`
`
`PUBLISHED BY
`Microsoft Press
`A Division of Microsoft Corporation
`One Microsoft Way
`Redmond, Washington 98052-6399
`
`Copyright © 1998 by Douglas McConnaughey Boling
`
`All rights reserved. No part of the contents of this book may be reproduced or
`transmitted in any form or by any means without the written permission of the publisher.
`
`Library of Congress Cataloging-in-Publication Data
`Boling, Douglas McConnaughey, 1960-
`Programming Microsoft Windows CE / Douglas McConnaughey Boling.
`p.
`cm.
`Includes index.
`ISBN 1-57231-856-2
`1. Microsoft Windows (Computer file)
`(Computers)
`I. Title.
`QA76.76.063B623
`1998
`005.4'469--dc21
`
`2. Operating Systems
`
`98-39279
`CIP
`
`Printed and bound in the United States of America.
`
`123456789 QMOM 321098
`
`Distributed in Canada by ITP Nelson, a division of Thomson Canada Limited.
`
`A CIP catalogue record for this book is available from the British Library.
`
`Microsoft Press books are available through booksellers and distributors worldwide. For further
`information about international editions, contact your local Microsoft Corporation office. Or
`contact Microsoft Press International directly at fax (425) 936-7329. Visit our Website at
`mspress.microsoft.com.
`
`Active Desktop, Developer Studio, Microsoft, Microsoft Press, MS-DOS, Visual C++, Win32, Win-
`dows, the Windows CE logo, and Windows NTare either registered trademarks or trademarks of
`Microsoft Corporation in the United States and/or other countries. Other product and company
`names mentioned herein may be the trademarks of their respective owners.
`
`Acquisitions Editor: Eric Stroo
`Project Editor: Kathleen Atkins
`Technical Editor: Jim Fuchs
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8
`
`Processes
`and Threads
`
`Like Windows NT, WindowsCEis a fully multitasking and multithreaded operating
`system. What does that mean? In this chapter I'll present a few definitions and then
`some explanations to answer that question.
`A processis a single instance of an application.If two copies of Microsoft Pocket
`Word are running, two unique processes are running. Every process has its own,
`protected, 32-MB address space as described in Chapter 6. Windows CE enforces a
`limit of 32 separate processes that can run at any time.
`Each process hasat least one thread. A thread executes code within a process. A
`process can have multiple threads running “at the sametime.” I put the phrase at the
`same time in quotes because, in fact, only one thread executes at any instant in time.
`The operating system simulates the concurrent execution ofthreads by rapidly switch-
`ing between the threads, alternatively stopping one thread and switching to another.
`
`PROCESSES
`
`WindowsCEtreats processes differently than does Windows 98 or WindowsNT.First
`and foremost, Windows CE has the aforementioned system limit of 32 processes being
`run at any one time. Whenthe system starts, at least four processes are created: NK.EXE,
`which provides the kernel services; FILESYS.EXE, which providesfile system services;
`GWES.EXE, which provides the GUI support; and DEVICE.EXE, which loads and
`maintains the device drivers for the system. On most systems, other processes are
`
`493
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Partll Windows CE Basics
`
`also started, such as the shell, EXPLORER.EXE, and, if the system is connected to a
`PC, REPLLOG.EXE and RAPISRV.EXE, which service the link between the PC and the
`WindowsCE system. This leaves room for about 24 processesthat the user or other
`applications that are running can start. While this soundslike a harsh limit, most sys-
`tems don’t need that many processes. A typical H/PCthat’s being used heavily might
`have 15 processes running at any one time.
`Windows CE diverges from its desktop counterparts in other ways. Compared
`with processes under Windows 98 or Windows NT, Windows CE processes contain
`muchless state information. Since Windows CE supports neither drives nor the con-
`cept of a current directory, the individual processes don’t needto store that informa-
`tion, WindowsCEalso doesn’t maintain a set of environmentvariables, so processes
`don’t need to keep an environment block. Windows CE doesn’t support handle in-
`heritance, so there’s no need totell a process to enable handle inheritance. Because
`of all this, the parameter-heavy CreateProcess function is passed mainly NULLs and
`zeros, with just a few parameters actually used by Windows CE.
`Manyof the process and thread-related functions are simply not supported by
`Windows CE because the system doesn’t support certain features supported by Win-
`dows 98 or Windows NT. Since Windows CE doesn’t support an environment,all the
`Win32 functions dealing with the environment don’t exist in Windows CE. While
`Windows CE supports threads, it doesn’t supportfibers, a lightweight version of a
`thread supported by WindowsNT.So, the fiber API doesn’t exist under WindowsCE.
`Somefunctions aren’t supported because there’s an easy way to work aroundthe lack
`of the function. For example, GetCommandLine doesn’t exist in WindowsCE, so an
`application needsto save a pointer to the commandline passed to WinMain if it needs
`to accessit later. Finally, ExitProcess doesn’t exist under WindowsCE. But, as you
`might expect, there’s a workaroundthatallows a processto close.
`Enough of what Windows CE doesn’t do; let’s look at what you can do with
`Windows CE.
`
`Creating a Process
`The function for creating another processis
`
`BOOL CreateProcess (LPCTSTR 1lpApplicationName,
`LPTSTR 1pCommandLine,
`LPSECURITY_ATTRIBUTES 1pProcessAttributes,
`LPSECURITY_ATTRIBUTES IpThreadAttributes,
`BOOL bInheritHandles, DWORD dwCreationFlags,
`LPVOID 1pEnvironment,
`LPCTSTR 1pCurrentDirectory,
`LPSTARTUPINFO IpStartupInfo,
`LPPROCESS_INFORMATION 1pProcessInformation);
`
`While the list of parameters looks daunting, most of the parameters mustbe set to
`NULL or 0 because Windows CE doesn’t support security or current directories,
`
`494
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`nor doesit handle inheritance. This results in a function prototype that looks more
`like this:
`
`BOOL CreateProcess (LPCTSTR IpApplicationName,
`LPTSTR IpCommandLine,
`NULL, NULL, FALSE,
`DWORD dwCreationFlags, NULL, NULL, NULL,
`LPPROCESS_INFORMATION 1lpProcessInformation);
`
`The parameters that remain start with a pointer to the nameof the application to launch.
`WindowsCE looks for the application in the following directories, in this order:
`
`1. The path, if any, specified in the jpApplicationName.
`
`2.
`
`For Windows CE 2.1 orlater, the path specified in the SystemPath value in
`[HKEY_LOCAL_MACHINE] \Loader. For earlier versions, the root of any
`external storage devices, such as PC Cards.
`
`The windowsdirectory, (\Windows).
`
`The root directory in the object store, (\).
`
`This action is different from Windows NT, where CreateProcess searches for the
`executable only if pApplicationNameis set to NULL andthe executable nameis passed
`through the IpCcommnadLine parameter. In the case of Windows CE, the applica-
`tion name must be passed in the pApplicaitonName parameter because Windows CE
`doesn’t support the technique of passing a NULL in /pApplicationNamewith the ap-
`plication nameasthefirst token in the p>CommandLine parameter.
`The IpCommandLine parameter specifies the commandline that will be passed
`to the new process. The only difference between Windows CE and Windows NT in
`this parameter is that under Windows CE the command line is always passed as a
`Unicodestring. And, as I mentioned previously, you can’t pass the name of the exe-
`cutable as the first token in lpCommandLine.
`The dwCreationFlags parameter specifies the initial state of the processafterit
`has been loaded. Windows CElimits the allowable flags to the following:
`
`M
`
`M
`
`M
`
`M
`
`O Creates a standard process.
`
`CREATE_SUSPENDED Creates the process, then suspends the primary
`thread.
`
`DEBUG_PROCESS Theprocess being created is treated as a process being
`debugged by the caller. The calling process receives debug information
`from the process being launched.
`
`DEBUG_ONLY_THIS_PROCESS When combined with DEBUG_PROCESS,
`debugs a process but doesn’t debug any child processes that are launched
`by the process being debugged.
`
`495
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Part Il
`
`WindowsCE Basics
`
`a
`
`CREATE_NEW_CONSOLE Forces a new console to be created. This is
`supported only in Windows CE 2.1 andlater.
`
`The only other parameter of CreateProcess used by Windows CEis /pProcess-
`Information. This parameter can be set to NULL, or it can point to a PROCESS_
`INFORMATIONstructurethat’s filled by CreateProcess with information about the new
`process. The PROCESS_INFORMATIONstructure is defined this way:
`
`typedef struct _PROCESS_INFORMATION {
`HANDLE hProcess;
`HANDLE hThread;
`DWORD dwProcesslId;
`DWORD dwThreadId;
`} PROCESS_INFORMATION;
`
`Thefirst two fields in this structure are filled with the handles of the new process and
`the handle of the primary thread of the new process. These handles are useful for
`monitoring the newly created process, but with them comes someresponsibility. When
`the system copies the handles for use in the PROCESS_INFORMATIONstructure, it
`increments the use countfor the handles. This meansthat, if you don’t have any use
`for the handles, the calling process must close them. Ideally, they should be closed
`immediately following a successful call to CreateProcess. V'll describe some good uses
`for these handles later in this chapter in the section, “Synchronization.”
`The other two fields in the PROCESS_INFORMATIONstructure are filled with
`the process ID and primary thread ID of the new process. These ID values aren't
`handles but simply unique identifiers that can be passed to Windowsfunctionsto iden-
`tify the target of the function. Be careful when using these IDs. If the new process
`terminates and another new oneis created, the system can reuse the old ID values.
`You must take measuresto assure that ID values for other processesare still identify-
`ing the process you're interested in before using them. For example, you can, by us-
`ing synchronization objects, be notified when a process terminates. When the process
`terminated, you would then know notto use the ID values for that process.
`Using the create process is simple, as you can see in the following code
`fragment:
`
`TCHAR szFileName[MAX_PATH];
`TCHAR szCmdLine[64];
`DWORD dwCreationFlags;
`PROCESS_INFORMATION pi;
`INT re;
`
`Tstrcepy (szFileName, TEXT ("calc"));
`Istrepy (szCmdLine, TEXT (""));
`dwCreationFlags = Q;
`
`496
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`re = CreateProcess (szFileName, szCmdLine, NULL, NULL, FALSE,
`dwCreationFlags, NULL, NULL, NULL, &pi);
`
`if (rc) {
`CloseHandle (pi.hThread);
`CloseHandle (pi.hProcess);
`
`} T
`
`his code launchesthe standard Calculator applet found on Handheld PCs and Palm-
`size PCs. Since the file name doesn’t specify a path, CreateProcess will, using the stan-
`dard Windows CEsearch path, find calc.exe in the \Windowsdirectory. Because I
`didn’t pass a commandline to Calc, I could have simply passed a NULL value in
`the /pCmdLine parameter. But I passed a null string in szCmdLineto differentiate the
`IpCmdLine parameter from the many other parameters in CreateProcess that aren't
`used. I used the same technique for dwCreationFlags. If the call to CreateProcessis
`successful, it returns a nonzero value. The code above checksfor this, andif the call
`was successful, closes the process and thread handles returned in the PROCESS_
`INFORMATIONstructure. Remember that this must be done by all Win32 applica-
`tions to prevent memory leaks.
`
`Terminating a Process
`
`A process can terminate itself by simply returning from the WinMain procedure. For
`console applications, a simple return from main suffices. Windows CE doesn’t sup-
`port the ExitProcess function found in Windows 98 and WindowsNT.Instead, you
`can have the primary thread of the process call ExitTbread. Under WindowsCE, if
`the primary thread terminates, the process is terminated as well, regardless of what other
`threads are currently active in the process. The exit code of the process will be the exit
`code provided by ExitThread. You can determine the exit code of a process by calling
`
`BOOL GetExitCodeProcess (HANDLE hProcess, LPDWORD 1pExitCode);
`
`The parameters are the handle to the process and a pointer to a DWORD thatreceives
`the exit code that was returned by the terminating process. If the processis still run-
`ning, the return code is the constant STILL_ACTIVE.
`You can terminate another process. But while it’s possible to do that, you
`shouldn’t be in the business of closing other processes. The user might not be ex-
`pecting that process to be closed without his or her consent. If you need to terminate
`a process (or close a process, which is the same thing but much nicer a word), the
`following methods can be used.
`If the process to be closed is one that you created, you can use somesort of
`interprocess communication to tell the process to terminate itself. This is the most
`advisable method because you’ve designed the target process to be closed by an-
`other party. Another method of closing a process is to send the main window of the
`process a WM_CLOSEmessage.This is especially effective on the Palm-size PC, where
`
`497
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Patil Windows CE Basics
`
`applications are designed to respond to WM_CLOSEmessages by quietly saving their
`state and closing. Finally, if all else fails and you absolutely must close another pro-
`cess, you can use TerminateProcess.
`TerminateProcess is prototyped as
`
`BOOL TerminateProcess (HANDLE hProcess, DWORD uExitCode);
`
`The two parameters are the handle of the process to terminate and the exit code the
`terminating process will return.
`
`Other Processes
`
`Of course, to terminate another process, you've got to know the handle to that pro-
`cess. You might want to know the handle for a process for other reasons, as well. For
`example, you might want to know when the process terminates. Windows CE sup-
`ports two additional functions that come in handy here (both of which are seldom
`discussed). Thefirst function is OpenProcess, which returns the.handle of an already
`running process. OpenProcess is prototyped as
`
`HANDLE OpenProcess (DWORD dwDesiredAccess, BOOL bInheritHandle,
`DWORD dwProcessId);
`
`Under Windows CE, the first parameter isn’t used and should be set to 0. The
`bInheritHandle parameter must be set to FALSE because Windows CE doesn’t sup-
`port handle inheritance. The final parameter is the process ID value of the process
`you want to open.
`The other function useful in this circumstanceis
`
`DWORD GetWindowThreadProcessId (HWND hWnd, LPDWORD IpdwProcessIld);
`
`This function takes a handle to a window and returns the process ID for the
`processthat created the window.So, using these two functions, you can trace a win-
`dow backto the process that createdit.
`Two other functions allow you to directly read from and write to the memory
`space of another process. These functions are
`
`BOOL ReadProcessMemory (HANDLE hProcess, LPCVOID lpBaseAddress,.
`LPVOID lpBuffer, DWORD nSize,
`LPDWORD 1pNumberOfBytesRead);
`
`and
`
`BOOL WriteProcessMemory (HANDLE hProcess, LPVOID IpBaseAddress,
`LPVOID lpBuffer, DWORD nSize,
`LPDWORD 1pNumberOfBytesWritten);
`The parameters for these functionsare fairly self-explanatory. The first parameter is
`the handle of the remote process. The second parameter is the base address in the
`other process’s address space of the area to be read or written. The third and fourth
`parameters specify the name andthe size of the local buffer in which the data is to
`
`498
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`be read from or written to. Finally, the last parameter specifies the bytes actually read
`or written. Both functions require that the entire area being read to or written from
`must be accessible. Typically, you use these functions for debugging but there’s no
`requirement that this be their only use.
`
`THREADS
`
`A thread is, fundamentally, a unit of execution. Thatis, it has a stack and a processor
`context, which is a set of values in the CPU internal registers. When a thread is sus-
`pended, the registers are pushed onto the thread's stack, the active stack is changed
`to the next thread to be run, that thread’s CPU state is pulled off its stack, and the
`new thread starts executing instructions.
`Threads under WindowsCEare similar to threads under Windows NT or Win-
`dows 98. Each process has a primary thread. Using the functions that I describe be-
`low, a process can create any numberof additional threads within the process. The
`only limit to the numberof threads in a Windows CE process is the memory and process
`address space available for the thread’s stack.
`Threads within a process share the address space of the process. Memory allo-
`cated by one thread is accessible to all threads in the process. Threads share the same
`access rights for handles whether they be file handles, memory objects handles, or
`handles to synchronization objects.
`Before WindowsCE 2.1, the size of all thread stacks was set at around 58 KB.
`Starting with WindowsCE 2.1, the stack size of all threads created within a processis
`set by the linker. (The linker switch for setting the stack size in Microsoft Visual C++
`is /stack.) Secondary threads under Windows CE 2.1 are created with the same stack
`size as the primary thread.
`
`The System Scheduler
`
`Windows CE schedules threads in a preemptive manner. Threads run for a quantum
`or time slice, which is usually 25 milliseconds on H/PCs and Palm-size PCs. (OEMs
`developing custom hardware can specify a different quantum.) After that time,if the
`thread hasn’t already relinquished its time slice and if the thread isn’t a time-critical
`thread, it’s suspended and another thread is scheduled to run. Windows CE chooses
`which thread to run based on a priority scheme. Threadsof a higherpriority are sched-
`uled before threads of lowerpriority.
`The rules for how Windows CEallocates time among the threads are quite dif-
`ferent from Windows NT and from Windows 98. Unlike Windows NT, Windows CE
`processes don’t have a priority class. Under WindowsNT, a process is created with a
`priority class. Threads derive their priority based on the priority class of their parent
`processes. A process with a higher-priority class has threads that run at a higher pri-
`ority than threads in a lower-priority class process. Threads within a process can then
`refine their priority within that process by setting their relative thread priority.
`
`499
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Part! Windows CE Basics
`
`Because WindowsCE hasnopriority classes, all processes are treated as peers.
`Individual threads can have different priorities, but the process that the thread runs
`within doesn’t influence those priorities. Also, unlike Windows NT, the foreground
`thread in Windows CE doesn’t get a boost in priority.
`In WindowsCE, a thread can have oneof eight priority levels. Those priorities
`are listed below:
`
`™
`
`MM
`
`iE
`
`HM
`
`ial
`
`™@
`
`i
`
`THREAD_PRIORITY_TIME_CRITICAL Indicates 3 points above normal
`priority. Threads of this priority aren’t preempted.
`THREAD_PRIORITY_HIGHEST Indicates 2 points above normalpriority.
`
`THREAD_PRIORITY_ABOVE_NORMAL Indicates 1 point above normal
`priority.
` THREAD_PRIORITY_NORMAL Indicates normal priority. All threads are
`created with this priority.
`
`THREAD_PRIORITY_BELOW_NORMAL Indicates 1 point below normal
`priority.
`
`THREAD_PRIORITY_LOWEST Indicates 2 points below normal priority.
`
`THREAD_PRIORITY_ABOVE_IDLE Indicates 3 points below normal
`priority.
`
`MM
`
`THREAD_PRIORITY_IDLE Indicates 4 points below normalpriority.
`
`All higher-priority threads run before lower-priority threads. This means that
`before a threadset to run at particular priority can be scheduled,all threads that have
`a higher priority must be blocked. A blocked thread is one that’s waiting on some
`system resource or synchronization object before it can continue. Threads of equal
`priority are scheduled in a round-robin fashion. Once a thread has voluntarily given
`up its time slice, is blocked, or has completed its timeslice, all other threads of the
`samepriority are allowed to run beforetheoriginal thread is allowed to continue.If
`a thread of higher priority is unblocked and a thread of lower priority is currently
`running, the lower-priority thread is immediately suspended and the higher-priority
`thread is scheduled. Lower-priority threads can never preempt a higher-priority thread.
`There are two exceptions to the rules I just stated. If a thread has a priority
`of THREAD_PRIORITY_TIME_CRITICAL, it’s never preempted, even by another
`THREAD_PRIORITY_TIME_CRITICALthread. As you can see, a THREAD_PRIORITY_
`TIME_CRITICALthread can and will starve everyone else in the system unless writ-
`ten carefully. This priority is reserved by convention for interrupt service threads in
`device drivers, which are written so that each thread quickly performsits task and
`releases its time slice.
`
`500
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`The other exception to the scheduling rules happensif a low-priority thread owns
`a resource that a higher-priority thread is waiting on. In this case, the low-priority thread
`is temporarily given the higher-priority thread’s priority in a scheme knownas prior-
`ity inversion, so that it can quickly accomplish its task and free the needed resource.
`While it might seem that lower-priority threads never get a chance to run in
`this scheme,it works out that threads are almost always blocked, waiting on something
`to free up before they can be scheduled. Threads are always created at THREAD_
`PRIORITY_NORMAL,so, unless they proactively changetheir priority level, a thread
`is usually at an equal priority to most of the other threads in the system. Even at the
`normalpriority level, threads are almost always blocked. For example, an application’s
`primary thread is typically blocked waiting on messages. Other threads should be
`designed to block on one of the many synchronization objects available to a Win-
`dows CE application.
`
`Never Do This!
`
`What’s not supported by the arrangementI just described, or by any other thread-
`based scheme, is code like the following:
`
`{
`while (bFlag == FALSE)
`// Do nothing, and spin
`
`} /
`
`/ Now do something.
`
`This kind of code isn’t just bad manners, since it wastes CPU power,it’s a death sen-
`tence to a battery-powered Windows CE device. To understand whythis is impor-
`tant, I need to digress into a quick lesson on Windows CE power management.
`WindowsCE is designed so that whenall threads are blocked, which happens
`over 90 percent ofthe time, it calls down to the OEM Abstraction Layer (the equiva-
`lent to the BIOS on an MS-DOS machine) to enter a low-power waiting state. Typi-
`cally, this low-power state means that the CPU is halted; thatis, it simply stops
`executing instructions. Because the CPU isn’t executing any instructions, no power-
`consuming reads and writes of memory are performed by the CPU.Atthis point, the
`only powernecessary for the system is to maintain the contents of the RAM andlight
`the display. This low-power mode can reduce power consumption by up to 99 per-
`cent of what is required when a thread is running in a well-designed system.
`Doing a quick back-of-the-envelope calculation, say a Palm-size PC is designed
`to run for 15 hours on a couple of AAA batteries. Given that the system turnsitself off
`after a few minutes of non-use, this 15 hours translates into a month or two of battery
`life in the device for the user. (I’m basing this calculation on the assumption that the
`system indeed spends 90 percent or moreofits time in its low-poweridle state.) Say
`a poorly written application thread spins on a variable instead of blocking. While this
`application is running, the system will never enter its low-powerstate. So, instead of
`
`501
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Patil Windows CE Basics
`
`900 minutes of battery time (15 hours x 60 minutes/hour), the system spends 100 per-
`cent ofits time at full power, resulting in a battery life of slightly over 98 minutes, or
`right at 1.5 hours. So, as you can see,it’s good to have the system in its low-power
`state.
`
`Fortunately, since Windowsapplications usually spend their time blocked in a
`call to GeiMessage, the system power managementworks by default. However,if you
`plan on using multiple threads in your application, you must use synchronization
`objects to block threads while they’re waiting. First, let’s look at how to create a thread,
`and then I’ll dive into the synchronization tools available to Windows CE programs.
`
`Creating a Thread
`
`You create a thread by calling this function:
`
`HANDLE CreateThread (LPSECURITY_ATTRIBUTES 1pThreadAttributes,
`DWORD dwStackSize,
`LPTHREAD_START_ROUTINE 1IpStartAddress,
`LPVOID 1pParameter, DWORD dwCreationFlags,
`LPDWORD 1pThreadId);
`
`As with CreateProcess, Windows CE doesn’t support a numberof the parameters in
`CreateTbread, and so they are set to NULL or 0 as appropriate. For CreateTbread,
`the [pThreadAttributes, and dwStackSize parameters aren’t supported. The parameter
`lpThreadAttributes must be set to NULL and dwStackSize is ignored by the system
`and should beset to 0. The third parameter, /pStartAddress, must point to thestart of
`the thread routine. The /pParameter parameter in CreateThreadis an application-
`defined value that’s passed to the thread function as its one and only parameter.
`The dwCreationFlags parameter can be set to either 0 or CREATE_SUSPENDED. If
`CREATE_SUSPENDEDis passed, the thread is created in a suspended state and must
`be resumedwitha call to ResumeThread.Thefinal parameteris a pointer toa DWORD
`that receives the newly created thread’s ID value.
`The thread routine should be prototyped this way:
`
`DWORD WINAPI ThreadFunc (LPVOID 1pArg);
`
`The only parameter is the /pParameter value, passed unaltered from the call to
`CreateThread. The parameter can be an integer or a pointer. Make sure, however,
`that you don’t pass a pointer to a stack-basedstructure that will disappear when the
`routine that called CreateThread returns.
`If CreateThreadis successful, it creates the thread and returns the handle to the
`newly created thread. As with CreateProcess, the handle returned should be closed
`when you no longer need the handle. Following is a short code fragment that con-
`tains a call to start a thread and the thread routine.
`
`502
`
`a:
`.
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`[forests 27 Ons SET aS Le Pe a oa SARE Ree oes Ss
`//
`if
`HANDLE hThread1;
`DWORD dwThread1ID = Q;
`INT nParameter = 5;
`
`hThreadl = CreateThread (NULL, @, Thread2, nParameter, @,
`&dwThread1ID);
`
`CloseHandle (hThread1);
`
`[fs esnsens se se se oo Sr Ss oO ere en tn te eee men ie ie
`// Second thread routine
`//
`
`DWORD WINAPI Thread2 (PVOID pArg)
`
`f{
`
`INT nParam = (INT) pArg;
`
`//
`// Do something here.
`//.
`//.
`//.
`return Q@x15;
`
`In this code, the second thread is started with a call to CreateThread. The
`nParametervalue is passed to the secondthread as the single parameterto the thread
`routine. The second thread executes until it terminates, in this case simply by return-
`ing from the routine.
`A thread can also terminate itself by calling this function:
`
`VOID ExitThread (DWORD dwExitCode);
`
`The only parameteris the exit code that’s set for the thread. That thread exit code
`can be queried by another thread using this function:
`
`BOOL GetExitCodeThread (HANDLE hThread, LPDWORD 1pExitCode);
`
`The function takes the handle to the thread (not the thread ID) andreturns the exit
`codeofthe thread.If the thread is still running, the exit code is STILL_ACTIVE,a con-
`stant defined as 0x0103. The exit codeis set by a thread using ExitTbreador the value
`returned by the thread procedure. In the preceding code, the thread sets its exit code
`to 0x15 whenit returns.
`All threads within a process are terminated when the process terminates. As I
`said earlier, a process is terminated whenits primary thread terminates.
`
`503
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Patil Windows CE Basics
`
`Setting and querying thread priority
`Threads are always created at a priority level of THREAD_PRIORITY_NORMAL. The
`thread priority can be changed either by the threaditself or by another thread calling
`this function:
`
`BOOL SetThreadPriority (HANDLE hThread,
`
`int nPriority);
`
`The two parameters are the thread handle and the new priority level. The level passed
`can be oneof the constants described previously, ranging from THREAD_PRIORITY_
`IDLE up to THREAD_PRIORITY_TIME_CRITICAL. You must be extremely careful when
`you're changing a thread’s priority. Rememberthat threads of a lowerpriority almost
`never preempt threads of higher priority. So, a simple bumping up of a thread one
`notch above normal can harm the responsivenessofthe rest of the system unless that
`thread is carefully written.
`To query the priority level of a thread, call this function:
`
`int GetThreadPriority (HANDLE hThread);
`
`This function returnsthe priority level of the thread. You shouldn’t use the hard-coded
`priority levels. Instead, use constants, such as THREAD_PRIORITY_NORMAL,defined
`by the system. This ensures that any changeto the priority scheme in future versions
`of Windows CE doesn’t affect your program.
`
`Suspending and resuming a thread
`You can suspend a thread at any time by calling this function:
`
`DWORD SuspendThread (HANDLE hThread);
`
`The only parameter is the handle to the thread to suspend. The value returned is the
`suspend count for the thread. Windows maintains a suspend count for each thread.
`Any thread with a suspend countgreater than 0 is suspended. Since SuspendThread
`increments the suspend count, multiple calls to SuspendThread must be matched with
`an equal numberofcalls to ResuumeThbread before a thread is actually scheduled to
`run. ResumeCount is prototyped as
`
`DWORD ResumeThread (HANDLE hThread);
`
`Here again, the parameter is the handle to the thread and the return value is
`the previous suspend count. So, if ResumeThread returns 1, the thread is no longer
`suspended.
`At times, a thread simply wants to kill some time. Since I’ve already explained
`whysimply spinning in a while loopis a very bad thing to do, you need another way
`to kill time. The best way to do this is to use this function:
`
`void Sleep (DWORD dwMilliseconds);
`
`Sleep suspends the thread for at least the number of milliseconds specified in the
`adwMilliseconds parameter. Since the quantum, or time slice, on a Windows CE
`
`504
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`system is usually 25 milliseconds, specifying very small numbers of milliseconds
`results in sleeps of at least 25 milliseconds. This strategy is entirely valid, and some-
`timesit’s equally valid to pass a 0 to Sleep. When a thread passesa 0 to Sleep, it gives
`up its time slice but is rescheduled immediately according to the scheduling rules I
`described previously.
`
`Thread Local Storage
`
`Thread local storage is a mechanism that allows a routine to maintain separate in-
`stances of data for each thread calling the routine. This capability might not seem
`like much, but it has some very handy uses. Take the following thread routine:
`
`INT g_nGlobal;
`
`// System global variable
`
`int ThreadProc (pStartData)
`INT nValuel;
`INT nValue2;
`
`{
`
`{
`
`while (unblocked)
`//
`// Do some work.
`iid
`
`terminate the thread by returning.
`
`i /
`
`/ We're done now,
`return Q@;
`
`I F
`
`or this example, imagine that multiple threads are created to execute the same rou-
`tine, ThreadProc. Each thread has its own copy of nValue1 and nValue2 because
`these are stack-based variables and each thread hasits ownstack. All threads, though,
`share the samestatic variable, g_nGlobal.
`Now, imagine that the 7hreadProc routine calls another routine, WorkerBee.
`
`As in
`
`int g_nGlobal;
`
`// System global variable
`
`int ThreadProc (pStartData)
`int nValuel;
`int nValue2;
`while (unblocked)
`WorkerBee();
`
`{
`
`

This document is available on Docket Alarm but you must sign up to view it.


Or .

Accessing this document will incur an additional charge of $.

After purchase, you can access this document again without charge.

Accept $ Charge
throbber

Still Working On It

This document is taking longer than usual to download. This can happen if we need to contact the court directly to obtain the document and their servers are running slowly.

Give it another minute or two to complete, and then try the refresh button.

throbber

A few More Minutes ... Still Working

It can take up to 5 minutes for us to download a document if the court servers are running slowly.

Thank you for your continued patience.

This document could not be displayed.

We could not find this document within its docket. Please go back to the docket page and check the link. If that does not work, go back to the docket and refresh it to pull the newest information.

Your account does not support viewing this document.

You need a Paid Account to view this document. Click here to change your account type.

Your account does not support viewing this document.

Set your membership status to view this document.

With a Docket Alarm membership, you'll get a whole lot more, including:

  • Up-to-date information for this case.
  • Email alerts whenever there is an update.
  • Full text search for other cases.
  • Get email alerts whenever a new case matches your search.

Become a Member

One Moment Please

The filing “” is large (MB) and is being downloaded.

Please refresh this page in a few minutes to see if the filing has been downloaded. The filing will also be emailed to you when the download completes.

Your document is on its way!

If you do not receive the document in five minutes, contact support at support@docketalarm.com.

Sealed Document

We are unable to display this document, it may be under a court ordered seal.

If you have proper credentials to access the file, you may proceed directly to the court's system using your government issued username and password.


Access Government Site

We are redirecting you
to a mobile optimized page.





Document Unreadable or Corrupt

Refresh this Document
Go to the Docket

We are unable to display this document.

Refresh this Document
Go to the Docket