Fix the case of product and company names.
[wine] / dlls / ntdll / nt.c
1 /*
2  * NT basis DLL
3  *
4  * This file contains the Nt* API functions of NTDLL.DLL.
5  * In the original ntdll.dll they all seem to just call int 0x2e (down to the NTOSKRNL)
6  *
7  * Copyright 1996-1998 Marcus Meissner
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include "wine/debug.h"
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winreg.h"
34 #include "winternl.h"
35 #include "ntdll_misc.h"
36 #include "wine/server.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
39
40 /* Structures used by NtConnectPort */
41
42 typedef struct LpcSectionInfo
43 {
44   DWORD Length;
45   HANDLE SectionHandle;
46   DWORD Param1;
47   DWORD SectionSize;
48   DWORD ClientBaseAddress;
49   DWORD ServerBaseAddress;
50 } LPCSECTIONINFO, *PLPCSECTIONINFO;
51
52 typedef struct LpcSectionMapInfo
53 {
54   DWORD Length;
55   DWORD SectionSize;
56   DWORD ServerBaseAddress;
57 } LPCSECTIONMAPINFO, *PLPCSECTIONMAPINFO;
58
59 /* Structure used by NtAcceptConnectPort, NtReplyWaitReceivePort */
60
61 #define MAX_MESSAGE_DATA 328
62
63 typedef struct LpcMessage
64 {
65   WORD ActualMessageLength;
66   WORD TotalMessageLength;
67   DWORD MessageType;
68   DWORD ClientProcessId;
69   DWORD ClientThreadId;
70   DWORD MessageId;
71   DWORD SharedSectionSize;
72   BYTE MessageData[MAX_MESSAGE_DATA];
73 } LPCMESSAGE, *PLPCMESSAGE;
74
75 /*
76  *      Process object
77  */
78
79 /******************************************************************************
80  *  NtTerminateProcess                  [NTDLL.@]
81  *
82  *  Native applications must kill themselves when done
83  */
84 NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
85 {
86     NTSTATUS ret;
87     BOOL self;
88     SERVER_START_REQ( terminate_process )
89     {
90         req->handle    = handle;
91         req->exit_code = exit_code;
92         ret = wine_server_call( req );
93         self = !ret && reply->self;
94     }
95     SERVER_END_REQ;
96     if (self) exit( exit_code );
97     return ret;
98 }
99
100 /******************************************************************************
101 *  NtQueryInformationProcess            [NTDLL.@]
102 *  ZwQueryInformationProcess            [NTDLL.@]
103 *
104 */
105 NTSTATUS WINAPI NtQueryInformationProcess(
106         IN HANDLE ProcessHandle,
107         IN PROCESSINFOCLASS ProcessInformationClass,
108         OUT PVOID ProcessInformation,
109         IN ULONG ProcessInformationLength,
110         OUT PULONG ReturnLength)
111 {
112         NTSTATUS ret = STATUS_SUCCESS;
113         ULONG len = 0;
114
115         switch (ProcessInformationClass) {
116         case ProcessDebugPort:
117                 /* "These are not the debuggers you are looking for." */
118                 /* set it to 0 aka "no debugger" to satisfy copy protections */
119                 if (ProcessInformationLength == 4)
120                 {
121                         memset(ProcessInformation,0,ProcessInformationLength);
122                         len = 4;
123                 }
124                 else
125                         ret = STATUS_INFO_LENGTH_MISMATCH;
126                 break;
127         case ProcessWow64Information:
128                 if (ProcessInformationLength == 4)
129                 {
130                         memset(ProcessInformation,0,ProcessInformationLength);
131                         len = 4;
132                 }
133                 else
134                         ret = STATUS_INFO_LENGTH_MISMATCH;
135                 break;
136         default:
137                 FIXME("(%p,0x%08x,%p,0x%08lx,%p),stub!\n",
138                         ProcessHandle,ProcessInformationClass,
139                         ProcessInformation,ProcessInformationLength,
140                         ReturnLength
141                 );
142                 break;
143         }
144
145         if (ReturnLength)
146                 *ReturnLength = len;
147
148         return ret;
149 }
150
151 /******************************************************************************
152  * NtSetInformationProcess [NTDLL.@]
153  * ZwSetInformationProcess [NTDLL.@]
154  */
155 NTSTATUS WINAPI NtSetInformationProcess(
156         IN HANDLE ProcessHandle,
157         IN PROCESSINFOCLASS ProcessInformationClass,
158         IN PVOID ProcessInformation,
159         IN ULONG ProcessInformationLength)
160 {
161         FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
162         ProcessHandle,ProcessInformationClass,ProcessInformation,ProcessInformationLength);
163         return 0;
164 }
165
166 /*
167  *      Token
168  */
169
170 /******************************************************************************
171  *  NtDuplicateToken            [NTDLL.@]
172  *  ZwDuplicateToken            [NTDLL.@]
173  */
174 NTSTATUS WINAPI NtDuplicateToken(
175         IN HANDLE ExistingToken,
176         IN ACCESS_MASK DesiredAccess,
177         IN POBJECT_ATTRIBUTES ObjectAttributes,
178         IN SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
179         IN TOKEN_TYPE TokenType,
180         OUT PHANDLE NewToken)
181 {
182         FIXME("(%p,0x%08lx,%p,0x%08x,0x%08x,%p),stub!\n",
183         ExistingToken, DesiredAccess, ObjectAttributes,
184         ImpersonationLevel, TokenType, NewToken);
185         dump_ObjectAttributes(ObjectAttributes);
186         return 0;
187 }
188
189 /******************************************************************************
190  *  NtOpenProcessToken          [NTDLL.@]
191  *  ZwOpenProcessToken          [NTDLL.@]
192  */
193 NTSTATUS WINAPI NtOpenProcessToken(
194         HANDLE ProcessHandle,
195         DWORD DesiredAccess,
196         HANDLE *TokenHandle)
197 {
198     NTSTATUS ret;
199
200     TRACE("(%p,0x%08lx,%p)\n", ProcessHandle,DesiredAccess, TokenHandle);
201
202     SERVER_START_REQ( open_token )
203     {
204         req->handle = ProcessHandle;
205         req->flags  = 0;
206         ret = wine_server_call( req );
207         if (!ret) *TokenHandle = reply->token;
208     }
209     SERVER_END_REQ;
210
211     return ret;
212 }
213
214 /******************************************************************************
215  *  NtOpenThreadToken           [NTDLL.@]
216  *  ZwOpenThreadToken           [NTDLL.@]
217  */
218 NTSTATUS WINAPI NtOpenThreadToken(
219         HANDLE ThreadHandle,
220         DWORD DesiredAccess,
221         BOOLEAN OpenAsSelf,
222         HANDLE *TokenHandle)
223 {
224     NTSTATUS ret;
225
226     TRACE("(%p,0x%08lx,0x%08x,%p)\n",
227           ThreadHandle,DesiredAccess, OpenAsSelf, TokenHandle);
228
229     SERVER_START_REQ( open_token )
230     {
231         req->handle = ThreadHandle;
232         req->flags  = OPEN_TOKEN_THREAD;
233         if (OpenAsSelf) req->flags |= OPEN_TOKEN_AS_SELF;
234         ret = wine_server_call( req );
235         if (!ret) *TokenHandle = reply->token;
236     }
237     SERVER_END_REQ;
238
239     return ret;
240 }
241
242 /******************************************************************************
243  *  NtAdjustPrivilegesToken             [NTDLL.@]
244  *  ZwAdjustGroupsToken         [NTDLL.@]
245  *
246  * FIXME: parameters unsafe
247  */
248 NTSTATUS WINAPI NtAdjustPrivilegesToken(
249         IN HANDLE TokenHandle,
250         IN BOOLEAN DisableAllPrivileges,
251         IN PTOKEN_PRIVILEGES NewState,
252         IN DWORD BufferLength,
253         OUT PTOKEN_PRIVILEGES PreviousState,
254         OUT PDWORD ReturnLength)
255 {
256         FIXME("(%p,0x%08x,%p,0x%08lx,%p,%p),stub!\n",
257         TokenHandle, DisableAllPrivileges, NewState, BufferLength, PreviousState, ReturnLength);
258         return 0;
259 }
260
261 /******************************************************************************
262 *  NtQueryInformationToken              [NTDLL.@]
263 *  ZwQueryInformationToken              [NTDLL.@]
264 *
265 * NOTES
266 *  Buffer for TokenUser:
267 *   0x00 TOKEN_USER the PSID field points to the SID
268 *   0x08 SID
269 *
270 */
271 NTSTATUS WINAPI NtQueryInformationToken(
272         HANDLE token,
273         DWORD tokeninfoclass,
274         LPVOID tokeninfo,
275         DWORD tokeninfolength,
276         LPDWORD retlen )
277 {
278     unsigned int len = 0;
279
280     FIXME("(%p,%ld,%p,%ld,%p): stub\n",
281           token,tokeninfoclass,tokeninfo,tokeninfolength,retlen);
282
283     switch (tokeninfoclass)
284     {
285     case TokenUser:
286         len = sizeof(TOKEN_USER) + sizeof(SID);
287         break;
288     case TokenGroups:
289         len = sizeof(TOKEN_GROUPS);
290         break;
291     case TokenPrivileges:
292         len = sizeof(TOKEN_PRIVILEGES);
293         break;
294     case TokenOwner:
295         len = sizeof(TOKEN_OWNER);
296         break;
297     case TokenPrimaryGroup:
298         len = sizeof(TOKEN_PRIMARY_GROUP);
299         break;
300     case TokenDefaultDacl:
301         len = sizeof(TOKEN_DEFAULT_DACL);
302         break;
303     case TokenSource:
304         len = sizeof(TOKEN_SOURCE);
305         break;
306     case TokenType:
307         len = sizeof (TOKEN_TYPE);
308         break;
309 #if 0
310     case TokenImpersonationLevel:
311     case TokenStatistics:
312 #endif /* 0 */
313     }
314
315     /* FIXME: what if retlen == NULL ? */
316     *retlen = len;
317
318     if (tokeninfolength < len)
319         return STATUS_BUFFER_TOO_SMALL;
320
321     switch (tokeninfoclass)
322     {
323     case TokenUser:
324         if( tokeninfo )
325         {
326             TOKEN_USER * tuser = tokeninfo;
327             PSID sid = (PSID) (tuser + 1);
328             SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
329             RtlInitializeSid(sid, &localSidAuthority, 1);
330             *(RtlSubAuthoritySid(sid, 0)) = SECURITY_INTERACTIVE_RID;
331             tuser->User.Sid = sid;
332         }
333         break;
334     case TokenGroups:
335         if (tokeninfo)
336         {
337             TOKEN_GROUPS *tgroups = tokeninfo;
338             SID_IDENTIFIER_AUTHORITY sid = {SECURITY_NT_AUTHORITY};
339
340             /* we need to show admin privileges ! */
341             tgroups->GroupCount = 1;
342             tgroups->Groups->Attributes = SE_GROUP_ENABLED;
343             RtlAllocateAndInitializeSid( &sid,
344                                          2,
345                                          SECURITY_BUILTIN_DOMAIN_RID,
346                                          DOMAIN_ALIAS_RID_ADMINS,
347                                          0, 0, 0, 0, 0, 0,
348                                          &(tgroups->Groups->Sid));
349         }
350         break;
351     case TokenPrivileges:
352         if (tokeninfo)
353         {
354             TOKEN_PRIVILEGES *tpriv = tokeninfo;
355             tpriv->PrivilegeCount = 1;
356         }
357         break;
358     }
359     return 0;
360 }
361
362 /*
363  *      Section
364  */
365
366 /******************************************************************************
367  *  NtQuerySection      [NTDLL.@]
368  */
369 NTSTATUS WINAPI NtQuerySection(
370         IN HANDLE SectionHandle,
371         IN PVOID SectionInformationClass,
372         OUT PVOID SectionInformation,
373         IN ULONG Length,
374         OUT PULONG ResultLength)
375 {
376         FIXME("(%p,%p,%p,0x%08lx,%p) stub!\n",
377         SectionHandle,SectionInformationClass,SectionInformation,Length,ResultLength);
378         return 0;
379 }
380
381 /*
382  *      ports
383  */
384
385 /******************************************************************************
386  *  NtCreatePort                [NTDLL.@]
387  *  ZwCreatePort                [NTDLL.@]
388  */
389 NTSTATUS WINAPI NtCreatePort(PHANDLE PortHandle,POBJECT_ATTRIBUTES ObjectAttributes,
390                              DWORD MaxConnectInfoLength,DWORD MaxDataLength,DWORD unknown)
391 {
392   FIXME("(%p,%p,0x%08lx,0x%08lx,0x%08lx),stub!\n",PortHandle,ObjectAttributes,
393         MaxConnectInfoLength,MaxDataLength,unknown);
394   return 0;
395 }
396
397 /******************************************************************************
398  *  NtConnectPort               [NTDLL.@]
399  *  ZwConnectPort               [NTDLL.@]
400  */
401 NTSTATUS WINAPI NtConnectPort(PHANDLE PortHandle,PUNICODE_STRING PortName,PVOID Unknown1,
402                               PLPCSECTIONINFO sectionInfo,PLPCSECTIONMAPINFO mapInfo,PVOID Unknown2,
403                               PVOID ConnectInfo,PDWORD pConnectInfoLength)
404 {
405   FIXME("(%p,%s,%p,%p,%p,%p,%p,%p (%ld)),stub!\n",PortHandle,debugstr_w(PortName->Buffer),Unknown1,
406         sectionInfo,mapInfo,Unknown2,ConnectInfo,pConnectInfoLength,pConnectInfoLength?*pConnectInfoLength:-1);
407   if(ConnectInfo && pConnectInfoLength)
408     TRACE("\tMessage = %s\n",debugstr_an(ConnectInfo,*pConnectInfoLength));
409   return 0;
410 }
411
412 /******************************************************************************
413  *  NtListenPort                [NTDLL.@]
414  *  ZwListenPort                [NTDLL.@]
415  */
416 NTSTATUS WINAPI NtListenPort(HANDLE PortHandle,PLPCMESSAGE pLpcMessage)
417 {
418   FIXME("(%p,%p),stub!\n",PortHandle,pLpcMessage);
419   return 0;
420 }
421
422 /******************************************************************************
423  *  NtAcceptConnectPort [NTDLL.@]
424  *  ZwAcceptConnectPort [NTDLL.@]
425  */
426 NTSTATUS WINAPI NtAcceptConnectPort(PHANDLE PortHandle,DWORD Unknown,PLPCMESSAGE pLpcMessage,
427                                     DWORD acceptIt,DWORD Unknown2,PLPCSECTIONMAPINFO mapInfo)
428 {
429   FIXME("(%p,0x%08lx,%p,0x%08lx,0x%08lx,%p),stub!\n",PortHandle,Unknown,pLpcMessage,acceptIt,Unknown2,mapInfo);
430   return 0;
431 }
432
433 /******************************************************************************
434  *  NtCompleteConnectPort       [NTDLL.@]
435  *  ZwCompleteConnectPort       [NTDLL.@]
436  */
437 NTSTATUS WINAPI NtCompleteConnectPort(HANDLE PortHandle)
438 {
439   FIXME("(%p),stub!\n",PortHandle);
440   return 0;
441 }
442
443 /******************************************************************************
444  *  NtRegisterThreadTerminatePort       [NTDLL.@]
445  *  ZwRegisterThreadTerminatePort       [NTDLL.@]
446  */
447 NTSTATUS WINAPI NtRegisterThreadTerminatePort(HANDLE PortHandle)
448 {
449   FIXME("(%p),stub!\n",PortHandle);
450   return 0;
451 }
452
453 /******************************************************************************
454  *  NtRequestWaitReplyPort              [NTDLL.@]
455  *  ZwRequestWaitReplyPort              [NTDLL.@]
456  */
457 NTSTATUS WINAPI NtRequestWaitReplyPort(HANDLE PortHandle,PLPCMESSAGE pLpcMessageIn,PLPCMESSAGE pLpcMessageOut)
458 {
459   FIXME("(%p,%p,%p),stub!\n",PortHandle,pLpcMessageIn,pLpcMessageOut);
460   if(pLpcMessageIn)
461   {
462     TRACE("Message to send:\n");
463     TRACE("\tActualMessageLength = %d\n",pLpcMessageIn->ActualMessageLength);
464     TRACE("\tTotalMessageLength  = %d\n",pLpcMessageIn->TotalMessageLength);
465     TRACE("\tMessageType         = %ld\n",pLpcMessageIn->MessageType);
466     TRACE("\tClientProcessId     = %ld\n",pLpcMessageIn->ClientProcessId);
467     TRACE("\tClientThreadId      = %ld\n",pLpcMessageIn->ClientThreadId);
468     TRACE("\tMessageId           = %ld\n",pLpcMessageIn->MessageId);
469     TRACE("\tSharedSectionSize   = %ld\n",pLpcMessageIn->SharedSectionSize);
470     TRACE("\tMessageData         = %s\n",debugstr_an(pLpcMessageIn->MessageData,pLpcMessageIn->ActualMessageLength));
471   }
472   return 0;
473 }
474
475 /******************************************************************************
476  *  NtReplyWaitReceivePort      [NTDLL.@]
477  *  ZwReplyWaitReceivePort      [NTDLL.@]
478  */
479 NTSTATUS WINAPI NtReplyWaitReceivePort(HANDLE PortHandle,PDWORD Unknown,PLPCMESSAGE pLpcMessageOut,PLPCMESSAGE pLpcMessageIn)
480 {
481   FIXME("(%p,%p,%p,%p),stub!\n",PortHandle,Unknown,pLpcMessageOut,pLpcMessageIn);
482   return 0;
483 }
484
485 /*
486  *      Misc
487  */
488
489  /******************************************************************************
490  *  NtSetIntervalProfile        [NTDLL.@]
491  *  ZwSetIntervalProfile        [NTDLL.@]
492  */
493 NTSTATUS WINAPI NtSetIntervalProfile(DWORD x1,DWORD x2) {
494         FIXME("(0x%08lx,0x%08lx),stub!\n",x1,x2);
495         return 0;
496 }
497
498 /******************************************************************************
499  *  NtQueryPerformanceCounter   [NTDLL.@]
500  */
501 NTSTATUS WINAPI NtQueryPerformanceCounter(
502         IN PLARGE_INTEGER Counter,
503         IN PLARGE_INTEGER Frequency)
504 {
505         FIXME("(%p, 0%p) stub\n",
506         Counter, Frequency);
507         return 0;
508 }
509
510 /******************************************************************************
511  *  NtCreateMailslotFile        [NTDLL.@]
512  *  ZwCreateMailslotFile        [NTDLL.@]
513  */
514 NTSTATUS WINAPI NtCreateMailslotFile(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5,DWORD x6,DWORD x7,DWORD x8)
515 {
516         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4,x5,x6,x7,x8);
517         return 0;
518 }
519
520 /******************************************************************************
521  * NtQuerySystemInformation [NTDLL.@]
522  * ZwQuerySystemInformation [NTDLL.@]
523  *
524  * ARGUMENTS:
525  *  SystemInformationClass      Index to a certain information structure
526  *      SystemTimeAdjustmentInformation SYSTEM_TIME_ADJUSTMENT
527  *      SystemCacheInformation          SYSTEM_CACHE_INFORMATION
528  *      SystemConfigurationInformation  CONFIGURATION_INFORMATION
529  *      observed (class/len):
530  *              0x0/0x2c
531  *              0x12/0x18
532  *              0x2/0x138
533  *              0x8/0x600
534  *              0x25/0xc
535  *  SystemInformation   caller supplies storage for the information structure
536  *  Length              size of the structure
537  *  ResultLength        Data written
538  */
539 NTSTATUS WINAPI NtQuerySystemInformation(
540         IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
541         OUT PVOID SystemInformation,
542         IN ULONG Length,
543         OUT PULONG ResultLength)
544 {
545     switch(SystemInformationClass)
546     {
547     case 0x25:
548         /* Something to do with the size of the registry             *
549          * Since we don't have a size limitation, fake it            *
550          * This is almost certainly wrong.                           *
551          * This sets each of the three words in the struct to 32 MB, *
552          * which is enough to make the IE 5 installer happy.         */
553         FIXME("(0x%08x,%p,0x%08lx,%p) faking max registry size of 32 MB\n",
554               SystemInformationClass,SystemInformation,Length,ResultLength);
555         *(DWORD *)SystemInformation = 0x2000000;
556         *(((DWORD *)SystemInformation)+1) = 0x200000;
557         *(((DWORD *)SystemInformation)+2) = 0x200000;
558         break;
559
560     default:
561         FIXME("(0x%08x,%p,0x%08lx,%p) stub\n",
562               SystemInformationClass,SystemInformation,Length,ResultLength);
563         ZeroMemory (SystemInformation, Length);
564     }
565
566     return STATUS_SUCCESS;
567 }
568
569
570 /******************************************************************************
571  *  NtCreatePagingFile          [NTDLL.@]
572  *  ZwCreatePagingFile          [NTDLL.@]
573  */
574 NTSTATUS WINAPI NtCreatePagingFile(
575         IN PUNICODE_STRING PageFileName,
576         IN ULONG MiniumSize,
577         IN ULONG MaxiumSize,
578         OUT PULONG ActualSize)
579 {
580         FIXME("(%p(%s),0x%08lx,0x%08lx,%p),stub!\n",
581         PageFileName->Buffer, debugstr_w(PageFileName->Buffer),MiniumSize,MaxiumSize,ActualSize);
582         return 0;
583 }
584
585 /******************************************************************************
586  *  NtDisplayString                             [NTDLL.@]
587  *
588  * writes a string to the nt-textmode screen eg. during startup
589  */
590 NTSTATUS WINAPI NtDisplayString ( PUNICODE_STRING string )
591 {
592     STRING stringA;
593     NTSTATUS ret;
594
595     if (!(ret = RtlUnicodeStringToAnsiString( &stringA, string, TRUE )))
596     {
597         MESSAGE( "%.*s", stringA.Length, stringA.Buffer );
598         RtlFreeAnsiString( &stringA );
599     }
600     return ret;
601 }
602
603 /******************************************************************************
604  *  NtPowerInformation                          [NTDLL.@]
605  *
606  */
607 NTSTATUS WINAPI NtPowerInformation(DWORD x1,DWORD x2,DWORD x3,DWORD x4,DWORD x5)
608 {
609         FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub\n",x1,x2,x3,x4,x5);
610         return 0;
611 }
612
613 /******************************************************************************
614  *  NtAllocateLocallyUniqueId (NTDLL.@)
615  *
616  * FIXME: the server should do that
617  */
618 NTSTATUS WINAPI NtAllocateLocallyUniqueId(PLUID Luid)
619 {
620     static LUID luid;
621
622     FIXME("%p (0x%08lx%08lx)\n", Luid, luid.HighPart, luid.LowPart);
623
624     luid.LowPart++;
625     if (luid.LowPart==0)
626         luid.HighPart++;
627     Luid->HighPart = luid.HighPart;
628     Luid->LowPart = luid.LowPart;
629
630     return STATUS_SUCCESS;
631 }
632
633 /******************************************************************************
634  *        VerSetConditionMask   (NTDLL.@)
635  */
636 ULONGLONG WINAPI VerSetConditionMask( ULONGLONG dwlConditionMask, DWORD dwTypeBitMask,
637                                       BYTE dwConditionMask)
638 {
639     if(dwTypeBitMask == 0)
640         return dwlConditionMask;
641     dwConditionMask &= 0x07;
642     if(dwConditionMask == 0)
643         return dwlConditionMask;
644
645     if(dwTypeBitMask & VER_PRODUCT_TYPE)
646         dwlConditionMask |= dwConditionMask << 7*3;
647     else if (dwTypeBitMask & VER_SUITENAME)
648         dwlConditionMask |= dwConditionMask << 6*3;
649     else if (dwTypeBitMask & VER_SERVICEPACKMAJOR)
650         dwlConditionMask |= dwConditionMask << 5*3;
651     else if (dwTypeBitMask & VER_SERVICEPACKMINOR)
652         dwlConditionMask |= dwConditionMask << 4*3;
653     else if (dwTypeBitMask & VER_PLATFORMID)
654         dwlConditionMask |= dwConditionMask << 3*3;
655     else if (dwTypeBitMask & VER_BUILDNUMBER)
656         dwlConditionMask |= dwConditionMask << 2*3;
657     else if (dwTypeBitMask & VER_MAJORVERSION)
658         dwlConditionMask |= dwConditionMask << 1*3;
659     else if (dwTypeBitMask & VER_MINORVERSION)
660         dwlConditionMask |= dwConditionMask << 0*3;
661     return dwlConditionMask;
662 }