throbber
Includes
`
`Windows CE .
`
`Platform
`
`SDKs
`
`Powered by
`
`‘-
`Microsoft”
`Windows“CE
`
`©C
`
`D-ROM
`Included
`
` Microsoft‘g’ Programming Series
`
`
`“DOUG’S CODE
`
`DEMONSTRATES
`
`A PERFECT GRASP
`
`OF WINDOWS CE—
`
`CRAFTY AND ELEGANT. ”
`
`—Char|es Petzoid, author,
`Programming Windows
`
`The
`
`definitive
`
`guide to
`programming
`the Windows CE
`
`API
`
`Douglas Boling
`
`Microsoft Corp. Exhibit 1058
`
`Q
`
`Microsoft Corp. Exhibit 1058
`
`

`

`PROGRAMMING
`Mlcnosow
`WINDOW? 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—57251-856—2
`1. Microsoft Windows (Computer file)
`(Computers)
`1. Title.
`QA76.76.063B623
`1998
`005.4'469-—dc21
`
`2. Operating Systems
`
`98-39279
`CIP
`
`Printed and bound in the United States of America.
`
`125456789 QMQM 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) 956-7529. Visit our Web site at
`ms;2ress.microsoft.com.
`
`Active Desktop, Developer Studio, Microsoft, Microsoft Press, MS—DOS, Visual C++, Win52, Win—
`dows, the Windows CE logo, and Windows NT are 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, Windows CE is 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 process is 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 has at least one thread. A thread executes code within a process. A
`process can have multiple threads running “at the same time.” 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 of threads by rapidly switch—
`ing between the threads, alternatively stopping one thread and switching to another.
`
`PROCESSES
`
`Windows CE treats processes differently than does Windows 98 or Windows NT. First
`and foremost, Windows CE has the aforementioned system limit of 32 processes being
`run at any one time. When the system starts, at least four processes are created: NK.EXE,
`which provides the kernel services; FILESYSEXE, which provides file system services;
`GWES.EXE, which provides the GUI support; and DEVICEEXE, 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
`
`

`

`Part II Windows CE Basics
`
`also started, such as the shell, EXPLOREREXE, and, if the system is connected to a
`PC, REPLLOG.EXE and RAPISRVEXE, which service the link between the PC and the
`Windows CE system. This leaves room for about 24 processes that the user or other
`applications that are running can start. While this sounds like a harsh limit, most sys—
`tems don’t need that many processes. A typical H/PC that’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
`much less state information. Since Windows CE supports neither drives nor the con—
`cept of a current directory, the individual processes don’t need to store that informa-
`tion. Windows CE also doesn’t maintain a set of environment variables, so processes
`don’t need to keep an environment block. Windows CE doesn’t support handle in—
`heritance, so there’s no need to tell 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.
`Many of 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 support fibers, a lightweight version of a
`thread supported by Windows NT. So, the fiber API doesn’t exist under Windows CE.
`Some functions aren’t supported because there’s an easy way to work around the lack
`of the function. For example, GetCommandLme doesn’t exist in Windows CE, so an
`application needs to save a pointer to the command line passed to WinMain if it needs
`to access it later. Finally, ExitProcess doesn’t exist under Windows CE. But, as you
`might expect, there’s a workaround that allows a process to 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 process is
`
`BOOL CreateProcess (LPCTSTR 1pApplicationName,
`LPTSTR lpCommandLine,
`LPSECURITY_ATTRIBUTES 1pProcessAttributes,
`LPSECURITY_ATTRIBUTES 1pThreadAttributes.
`BOOL bInheritHandies, DWORD dwCreationFiags,
`LPVOID 1pEnvironment,
`LPCTSTR 1pCurrentDirectory,
`LPSTARTUPINFO 1pStartupInf0,
`LPPROCESS_INFORMAT10N lpProcessInformation);
`
`While the list of parameters looks daunting, most of the parameters must be set to
`NULL 0r 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 does it handle inheritance. This results in a function prototype that looks more
`like this:
`
`BOOL CreateProcess (LPCTSTR lpApplicationName,
`LPTSTR 1pCommandLine,
`NULL, NULL. FALSE.
`DNORD dwCreationFlags, NULL, NULL, NULL,
`LPPROCESS_INFORMATION lpProcessInformation);
`
`The parameters that remain start with a pointer to the name of the application to launch.
`Windows CE looks for the application in the following directories, in this order:
`
`1. The path, if any, specified in the lpApplz'catz'onName.
`
`2.
`
`For Windows CE 2.1 or later, the path specified in the SystemPat/a value in
`[HKEY_LOCAL_MACHINE]\Loader. For earlier versions, the root of any
`external storage devices, such as PC Cards.
`
`\
`
`The windows directory, (\Windows).
`
`4. The root directory in the object store, (\).
`
`This action is different from Windows NT, where CreateProcess searches for the
`
`executable only if lpApplz'cationName is set to NULL and the executable name is passed
`through the lpCcommnadLine parameter. In the case of Windows CE, the applica—
`tion name must be passed in the lpApplz'caz’tonName parameter because Windows CE
`doesn’t support the technique of passing a NULL in @Applz’cationName with the ap—
`plication name as the first token in the lpCommansz’ne parameter.
`The lpCommomdLine parameter specifies the command line 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
`Unicode string. And, as I mentioned previously, you can’t pass the name of the exe-
`cutable as the first token in lpCommcmdLine.
`The dwCreatz’onFlags parameter specifies the initial state of the process after it
`has been loaded. Windows CE limits the allowable flags to the following:
`
`I
`
`I
`
`I
`
`0 Creates a standard process.
`
`CREATE_SUSPENDED Creates the process, then suspends the primary
`thread.
`
`DEBUG_PROCESS The process being created is treated as a process being
`debugged by the caller. The calling process receives debug information
`from the process being launched.
`
`I
`
`DEB UG_ONL Y_77-IIS_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
`
`

`

`PaflH
`
`Windows CE Basics
`
`I
`
`CREAYF_NEW_CONSOLE Forces a new console to be created. This is
`
`supported only in Windows CE 2.1 and later.
`
`The only other parameter of CreateProcess used by Windows CE is lpProcess—
`Information. This parameter can be set to NULL, or it can point to a PROCESS_
`INFORMATION structure that’s filled by CreateProcess with information about the new
`
`process. The PROCESS_INFORMATION structure is defined this way:
`
`typedef struct _PROCESS_INFORMATION {
`HANDLE hProcess;
`HANDLE hThread;
`DNORD derocessId;
`DNORD dwThreadId;
`} PROCESS_INFORMATION;
`
`The first 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 some responsibility. When
`the system copies the handles for use in the PROCESS_INFORMATION structure, it
`increments the use count for the handles. This means that, 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. I’ll describe some good uses
`for these handles later in this Chapter in the section, “Synchronization.”
`The other two fields in the PROCESS_INFORMATION structure 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 Windows functions to iden-
`tify the target of the function. Be careful when using these IDs. If the new process
`terminates and another new one is created, the system can reuse the old ID values.
`You must take measures to assure that ID values for other processes are 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 not to use the ID values for that process.
`Using the create process is simple, as you can see in the following code
`fragment:
`
`TCHAR stileNameEMAX_PATH];
`TCHAR sszdLineE64];
`DWORD dwCreationFlags;
`PROCESS_INFORMATION pi;
`INT rc;
`
`Tstrcpy (stiTeName, TEXT ("calc"));
`Tstrcpy (sszdLine, TEXT (""));
`dwCreationFTags
`0;
`
`496
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`rc = CreateProcess (stiIeName, sszdLine, NULL, NULL, FALSE,
`dwCreationFlags. NULL, NULL, NULL, &p1);
`
`if (rc) {
`CIoseHandie (p1.hThread);
`CloseHandle (pi.hProcess);
`
`} T
`
`his code launches the 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 CE search path, find calc.exe in the \Windows directory. Because I
`didn’t pass a command line to Cale, I could have simply passed a NULL value in
`the lpCmdLme parameter. But I passed a null string in sszdLme to differentiate the
`lpCmdLme parameter from the many other parameters in CreateProcess that aren’t
`used. I used the same technique for dwCreationFlags. If the call to CreateProcess is
`successful, it returns a nonzero value. The code above checks for this, and if the call
`was successful, closes the process and thread handles returned in the PROCESS_
`
`INFORMATION structure. Remember that this must be done by all Win52 applica-
`tions to prevent memory leaks.
`
`Terminating a Process
`
`A process can terminate itself by simply returning from the WinMam procedure. For
`console applications, a simple return from main suffices. Windows CE doesn’t sup—
`port the ExitProcess function found in Windows 98 and Windows NT. Instead, you
`can have the primary thread of the process call Exitfloread. Under Windows CE, 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 ExitT/oread. You can determine the exit code of a process by calling
`
`BOOL GetExitCodeProcess (HANDLE hProcess, LPDNORD lpExitCode);
`
`The parameters are the handle to the process and a pointer to a DWORD that receives
`the exit code that was returned by the terminating process. If the process is 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 some sort 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_CLOSE message. This is especially effective on the Palm—size PC, where
`
`497
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Partll Windows CE Basics
`
`applications are designed to respond to WM_CLOSE messages 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, DNORD 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). The first function is OpenProcess, which returns thehandle of an already
`running process. OpenProcess is prototyped as
`
`HANDLE OpenProcess (DNORD deesiredAccess, BOOL bInheritHandle,
`DNORD derocessId);
`
`Under Windows CE, the first parameter isn’t used and should be set to 0. The
`
`bIn/oem'tHandle 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 circumstance is
`
`DNORD GetwindowThreadProcessId (HNND hNnd, LPDNORD 1pderocessId);
`
`This function takes a handle to a window and returns the process ID for the
`process that created the window. 80, using these two functions, you can trace a win-
`dow back to the process that created it.
`
`Two other functions allow you to directly read from and write to the memory
`space of another process. These functions are
`
`BOOL ReadPr‘ocessMemory (HANDLE hProcess , LPCVOID 1pBaseAddress ,.
`LPVOID lpBuffer, DWORD nSize,
`LPDNORD 1pNumber0fotesRead);
`
`and
`
`BOOL NriteProcessMemory (HANDLE hProcess, LPVOID 1pBaseAddress.
`LPVOID 1pBuffer. DNORD nSize,
`LPDNORD 1pNumberOfotesNritten);
`
`The parameters for these functions are 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 and the 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. That is, 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 threads 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 Windows CE are 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 number of additional threads within the process. The
`only limit to the number of threads in a Windows CE process is the memory and process
`address space available for the threads 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, 0r
`handles to synchronization objects.
`Before Windows CE 2.1, the size of all thread stacks was set at around 58 KB.
`
`Starting with Windows CE 2.1, the stack size of all threads created within a process is
`set by the linker. (The linker switch for setting the stack size in Microsoft Visual C++
`is /5tac/e.) 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. Threads of a higher priority are sched-
`uled before threads of lower priority.
`The rules for how Windows CE allocates 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 Windows NT, 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
`
`

`

`Pan II Windows CE Basics
`
`Because Windows CE has no priority 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 Windows CE, a thread can have one of eight priority levels. Those priorities
`are listed below:
`
`I
`
`I
`
`I
`
`I
`
`7HREAD_PRIOR1TY_77ME_CRITICAL Indicates 3 points above normal
`priority. Threads of this priority aren’t preempted.
`
`THREAD_PRIORITY_HIGHEST Indicates 2 points above normal priority.
`
`THREAD_PRIORITY_ABOVILNORZVML Indicates 1 point above normal
`
`priority.
`
`7HRE4D_PRIORITY_NORM4L Indicates normal priority. All threads are
`created with this priority.
`
`I
`
`7HREAD_PRIORITY_BELOW_NORMAL Indicates 1 point below normal
`
`priority.
`
`I
`
`I
`
`THREAD_PRIORITY_LOWEST Indicates 2 points below normal priority.
`
`YHREAD_PRIORITY_ABOVF_IDLE Indicates 3 points below normal
`
`priority.
`
`I
`
`THREAD_PRIORITY_IDLE Indicates 4 points below normal priority.
`
`All higher-priority threads run before lower-priority threads. This means that
`before a thread set 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 time slice, all other threads of the
`same priority are allowed to run before the original 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_CRITICAL thread. As you can see, a THREAD_PRIORITY_
`TIME_CRITICAL thread 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 performs its 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 happens if 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 known as 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 change their priority level, a thread
`
`is usually at an equal priority to most of the other threads in the system. Even at the
`normal priority 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 arrangement I just described, or by any other thread—
`based scheme, is code like the following:
`
`{
`while (bFIag == 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 why this is impor—
`tant, I need to digress into a quick lesson on Windows CE power management.
`Windows CE is designed so that when all threads are blocked, which happens
`over 90 percent of the 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-
`
`it simply stops
`cally, this low—power state means that the CPU is halted; that is,
`executing instructions. Because the CPU isn’t executing any instructions, no power—
`consuming reads and writes of memory are performed by the CPU. At this point, the
`only power necessary for the system is to maintain the contents of the RAM and light
`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 turns itself 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 more of its time in its low-power idle 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-power state. So, instead of
`
`501
`
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Parill Windows CE Basics
`
`900 minutes of battery time (15 hours X 60 minutes/hour), the system spends 100 per-
`cent of its 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 Windows applications usually spend their time blocked in a
`
`call to GetMessage, the system power management works 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 lpThreadAttributes,
`DWORD detackSize,
`LPTHREAD_START_ROUTINE lpStartAddress,
`LPVOID lpParameter, DWORD dwCreationFlags,
`LPDWORD lpThreadId);
`
`As with CreateProcess, Windows CE doesn’t support a number of the parameters in
`CreateTYoread, and so they are set to NULL or O as appropriate. For CreateT/aread,
`the lprreadAtmbutes, and demc/eSz'ze parameters aren’t supported. The parameter
`lprreadAtm‘butes must be set to NULL and detac/eSz’ze is ignored by the system
`and should be set to 0. The third parameter, lpSmwAddress, must point to the start of
`the thread routine. The lpPammeter parameter in Createflaread is 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_SUSPENDED is passed, the thread is created in a suspended state and must
`be resumed with a call to Resumeflaread. The final parameter is a pointer to a 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 lpParameler value, passed unaltered from the call to
`CreateT/oread. The parameter can be an integer or a pointer. Make sure, however,
`that you don’t pass a pointer to a stack—based structure that will disappear when the
`routine that called CreateT/aread returns.
`
`If CreateTYoread is 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
`
`.
`.
`.
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Chapter 8 Processes and Threads
`
`// - - - - - - - - - - — - ~ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - — - - - - --
`//
`//
`HANDLE hThreadl;
`DWORD dwThreadlID = 0;
`INT nParameter = 5;
`
`hThreadl = CreateThread (NULL, 0, ThreadZ. nParameter, 0,
`&dwThread11D);
`
`CloseHandie (hThreadl);
`
`// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --
`// Second thread routine
`//
`
`DNORD WINAPI ThreadZ (PVOID pArg)
`
`{
`
`INT nParam = (INT) pArg;
`
`//
`// Do something here.
`// .
`// .
`// .
`return 0x15;
`
`In this code, the second thread is started with a call to CreateT/aread. The
`nPammeter value is passed to the second thread as the single parameter to 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 (DNORD dwExitCode);
`
`The only parameter is 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 IpExitCode);
`
`The function takes the handle to the thread (not the thread ID) and returns the exit
`
`code of the thread. If the thread is still running, the exit code is STILL_ACTIVE, a con-
`stant defined as 0X0103. The exit code is set by a thread using Exiflbread or the value
`returned by the thread procedure. In the preceding code, the thread sets its exit code
`to 0X15 when it returns.
`
`All threads Within a process are terminated when the process terminates. As I
`said earlier, a process is terminated When its primary thread terminates.
`
`503
`.
`Microsoft Corp. Exhibit 1058
`
`Microsoft Corp. Exhibit 1058
`
`

`

`Part II 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 thread itself 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 one of 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. Remember that threads of a lower priority almost
`never preempt threads of higher priority. So, a simple bumping up of a thread one
`notch above normal can harm the responsiveness of the 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 returns the 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 change to 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 coum‘ for the thread. Windows maintains a suspend count for each thread.
`Any thread with a suspend count greater than 0 is suspended. Since Suspendflaread
`increments the suspend count, multiple calls to Suspendflaread must be matched with
`an equal number of calls to Resumefloread before a thread is actually scheduled to
`run. ResumeCoum is prototyped as
`
`DNORD ResumeThread (HANDLE hThread);
`
`Here again, the parameter is the handle to the thread and the return value is
`
`the previous suspend count. So, if Resumeflaread returns 1, the thread is no longer
`suspended.
`
`At times, a thread simply wants to kill some time. Since I’ve already explained
`why simply spinning in a while loop is 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 deiiiiseconds);
`
`Sleep suspends the thread for at least the number of milliseconds specified in the
`dez’llz'seconds 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-
`times it’s equally valid to pass a 0 to Sleep. When a thread passes a O 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 nValueZ;
`
`{
`
`{
`
`while (unblocked)
`//
`// Do some work.
`//
`
`terminate the thread by returning.
`
`} /
`
`/ We're done now,
`return 0;
`
`} F
`
`or this example, imagine that multiple threads are created to execute t

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