ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
December 2009
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
22 participants
501 discussions
Start a n
N
ew thread
[gschneider] 44742: [msvcrt] Update c++ symbol demangling to Wine 1.1.35 (msvcrt:cpp test buffer overrun)
by gschneider@svn.reactos.org
Author: gschneider Date: Wed Dec 23 18:48:27 2009 New Revision: 44742 URL:
http://svn.reactos.org/svn/reactos?rev=44742&view=rev
Log: [msvcrt] Update c++ symbol demangling to Wine 1.1.35 (msvcrt:cpp test buffer overrun) Modified: trunk/reactos/lib/sdk/crt/wine/undname.c Modified: trunk/reactos/lib/sdk/crt/wine/undname.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/sdk/crt/wine/undname.c…
============================================================================== --- trunk/reactos/lib/sdk/crt/wine/undname.c [iso-8859-1] (original) +++ trunk/reactos/lib/sdk/crt/wine/undname.c [iso-8859-1] Wed Dec 23 18:48:27 2009 @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define __WINE_DEBUG_CHANNEL__ @@ -70,13 +70,13 @@ * */ -#define MAX_ARRAY_ELTS 32 struct array { unsigned start; /* first valid reference in array */ unsigned num; /* total number of used elts */ unsigned max; - char* elts[MAX_ARRAY_ELTS]; + unsigned alloc; + char** elts; }; /* Structure holding a parsed symbol */ @@ -110,7 +110,7 @@ * where we use a poor-man allocator. It's fast, and since all * allocation is pool, memory management is easy (esp. freeing). */ -static void* und_alloc(struct parsed_symbol* sym, size_t len) +static void* und_alloc(struct parsed_symbol* sym, unsigned int len) { void* ptr; @@ -171,19 +171,36 @@ */ static void str_array_init(struct array* a) { - a->start = a->num = a->max = 0; + a->start = a->num = a->max = a->alloc = 0; + a->elts = NULL; } /****************************************************************** * str_array_push * Adding a new string to an array */ -static void str_array_push(struct parsed_symbol* sym, const char* ptr, int len, +static BOOL str_array_push(struct parsed_symbol* sym, const char* ptr, int len, struct array* a) { + char** new; + assert(ptr); assert(a); - assert(a->num < MAX_ARRAY_ELTS); + + if (!a->alloc) + { + new = und_alloc(sym, (a->alloc = 32) * sizeof(a->elts[0])); + if (!new) return FALSE; + a->elts = new; + } + else if (a->max >= a->alloc) + { + new = und_alloc(sym, (a->alloc * 2) * sizeof(a->elts[0])); + if (!new) return FALSE; + memcpy(new, a->elts, a->alloc * sizeof(a->elts[0])); + a->alloc *= 2; + a->elts = new; + } if (len == -1) len = strlen(ptr); a->elts[a->num] = und_alloc(sym, len + 1); assert(a->elts[a->num]); @@ -202,6 +219,8 @@ TRACE("%p\t%d%c %s\n", a, i, c, a->elts[i]); } } + + return TRUE; } /****************************************************************** @@ -230,11 +249,11 @@ */ static char* str_printf(struct parsed_symbol* sym, const char* format, ...) { - va_list args; - size_t len = 1, i, sz; - char* tmp; - char* p; - char* t; + va_list args; + unsigned int len = 1, i, sz; + char* tmp; + char* p; + char* t; va_start(args, format); for (i = 0; format[i]; i++) @@ -316,7 +335,7 @@ } else if (*sym->current >= 'A' && *sym->current <= 'P') { - long ret = 0; + int ret = 0; while (*sym->current >= 'A' && *sym->current <= 'P') { @@ -326,7 +345,7 @@ if (*sym->current != '@') return NULL; ptr = und_alloc(sym, 17); - sprintf(ptr, "%s%ld", sgn ? "-" : "", ret); + sprintf(ptr, "%s%d", sgn ? "-" : "", ret); sym->current++; } else return NULL; @@ -345,6 +364,7 @@ struct datatype_t ct; struct array arg_collect; char* args_str = NULL; + char* last; unsigned int i; str_array_init(&arg_collect); @@ -362,8 +382,9 @@ return NULL; /* 'void' terminates an argument list in a function */ if (z_term && !strcmp(ct.left, "void")) break; - str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1, - &arg_collect); + if (!str_array_push(sym, str_printf(sym, "%s%s", ct.left, ct.right), -1, + &arg_collect)) + return NULL; if (!strcmp(ct.left, "...")) break; } /* Functions are always terminated by 'Z'. If we made it this far and @@ -379,7 +400,8 @@ args_str = str_printf(sym, "%s,%s", args_str, arg_collect.elts[i]); } - if (close_char == '>' && args_str && args_str[strlen(args_str) - 1] == '>') + last = args_str ? args_str : arg_collect.elts[0]; + if (close_char == '>' && last[strlen(last) - 1] == '>') args_str = str_printf(sym, "%c%s%s %c", open_char, arg_collect.elts[0], args_str, close_char); else @@ -493,7 +515,8 @@ } } while (*++sym->current != '@'); sym->current++; - str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->names); + if (!str_array_push(sym, ptr, sym->current - 1 - ptr, &sym->names)) + return NULL; return str_array_get_ref(&sym->names, sym->names.num - sym->names.start - 1); } @@ -561,17 +584,17 @@ if (*++sym->current == '$') { sym->current++; - if ((name = get_template_name(sym))) - str_array_push(sym, name, -1, &sym->names); + if ((name = get_template_name(sym)) && + !str_array_push(sym, name, -1, &sym->names)) + return FALSE; } break; default: name = get_literal_string(sym); break; } - if (!name) + if (!name || !str_array_push(sym, name, -1, &sym->stack)) return FALSE; - str_array_push(sym, name, -1, &sym->stack); } sym->current++; return TRUE; @@ -584,9 +607,9 @@ */ static char* get_class_string(struct parsed_symbol* sym, int start) { - int i; - size_t len, sz; - char* ret; + int i; + unsigned int len, sz; + char* ret; struct array *a = &sym->stack; for (len = 0, i = start; i < a->num; i++) @@ -915,8 +938,9 @@ if (add_pmt && pmt_ref && in_args) { /* left and right are pushed as two separate strings */ - str_array_push(sym, ct->left ? ct->left : "", -1, pmt_ref); - str_array_push(sym, ct->right ? ct->right : "", -1, pmt_ref); + if (!str_array_push(sym, ct->left ? ct->left : "", -1, pmt_ref) || + !str_array_push(sym, ct->right ? ct->right : "", -1, pmt_ref)) + return FALSE; } done: @@ -1323,15 +1347,16 @@ switch (do_after) { case 1: case 2: - sym->stack.num = sym->stack.max = 1; - sym->stack.elts[0] = dashed_null; + if (!str_array_push(sym, dashed_null, -1, &sym->stack)) + return FALSE; break; case 4: sym->result = (char*)function_name; ret = TRUE; goto done; default: - str_array_push(sym, function_name, -1, &sym->stack); + if (!str_array_push(sym, function_name, -1, &sym->stack)) + return FALSE; break; } }
15 years
1
0
0
0
[gschneider] 44741: [win32k] NtGdiSetDIBitsToDeviceInternal: - Choose the number of scan lines from the parameter and the bitmap size - Add scan line offset to the destination rectangle top left corner (fixes drawing images line by line) - Add debug print for further problem solving (deactivated)
by gschneider@svn.reactos.org
Author: gschneider Date: Wed Dec 23 18:41:20 2009 New Revision: 44741 URL:
http://svn.reactos.org/svn/reactos?rev=44741&view=rev
Log: [win32k] NtGdiSetDIBitsToDeviceInternal: - Choose the number of scan lines from the parameter and the bitmap size - Add scan line offset to the destination rectangle top left corner (fixes drawing images line by line) - Add debug print for further problem solving (deactivated) Modified: trunk/reactos/subsystems/win32/win32k/objects/dibobj.c Modified: trunk/reactos/subsystems/win32/win32k/objects/dibobj.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/dibobj.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/objects/dibobj.c [iso-8859-1] Wed Dec 23 18:41:20 2009 @@ -1,6 +1,4 @@ /* - * $Id$ - * * ReactOS W32 Subsystem * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team * @@ -489,6 +487,8 @@ pDestSurf = pSurf ? &pSurf->SurfObj : NULL; + ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan); + rcDest.left = XDest; rcDest.top = YDest; if (bTransformCoordinates) @@ -499,11 +499,14 @@ rcDest.top += pDC->ptlDCOrig.y; rcDest.right = rcDest.left + Width; rcDest.bottom = rcDest.top + Height; + rcDest.top += StartScan; + ptSource.x = XSrc; ptSource.y = YSrc; SourceSize.cx = bmi->bmiHeader.biWidth; - SourceSize.cy = ScanLines; // this one --> abs(bmi->bmiHeader.biHeight) - StartScan + SourceSize.cy = ScanLines; + DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount); hSourceBitmap = EngCreateBitmap(SourceSize, @@ -556,6 +559,9 @@ EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0); /* Copy the bits */ + DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n", + rcDest.left, rcDest.top, rcDest.right, rcDest.bottom, + ptSource.x, ptSource.y, SourceSize.cx, SourceSize.cy); Status = IntEngBitBlt(pDestSurf, pSourceSurf, NULL, @@ -574,8 +580,7 @@ Exit: if (NT_SUCCESS(Status)) { - /* FIXME: Should probably be only the number of lines actually copied */ - ret = ScanLines; // this one --> abs(Info->bmiHeader.biHeight) - StartScan; + ret = ScanLines; } if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
15 years
1
0
0
0
[cwittich] 44740: [winmm_winetest] sync winmm_winetest to wine 1.1.35
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Dec 23 17:02:37 2009 New Revision: 44740 URL:
http://svn.reactos.org/svn/reactos?rev=44740&view=rev
Log: [winmm_winetest] sync winmm_winetest to wine 1.1.35 Modified: trunk/rostests/winetests/winmm/mci.c Modified: trunk/rostests/winetests/winmm/mci.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/winmm/mci.c?rev…
============================================================================== --- trunk/rostests/winetests/winmm/mci.c [iso-8859-1] (original) +++ trunk/rostests/winetests/winmm/mci.c [iso-8859-1] Wed Dec 23 17:02:37 2009 @@ -2,6 +2,7 @@ * Test winmm mci * * Copyright 2006 Jan Zerebecki + * 2009 Jörg Höhle * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,53 +19,843 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include <stdio.h> +#include "windows.h" +#include "mmsystem.h" +#include "mmreg.h" #include "wine/test.h" -#include "winuser.h" -#include "mmsystem.h" - -START_TEST(mci) + +/* The tests use the MCI's own save capability to create the tempfile.wav to play. + * To use a pre-existing file, write-protect it. */ +static MCIERROR ok_saved = MCIERR_FILE_NOT_FOUND; + +typedef union { + MCI_STATUS_PARMS status; + MCI_WAVE_SET_PARMS set; + MCI_WAVE_OPEN_PARMS open; + MCI_SEEK_PARMS seek; + } MCI_PARMS_UNION; + +static const char* dbg_mcierr(MCIERROR err) { - int err; - const char command_open[] = "open new type waveaudio alias mysound"; + switch (err) { + case 0: return "0=NOERROR"; +#define X(label) case label: return #label ; + X(MCIERR_INVALID_DEVICE_ID) + X(MCIERR_UNRECOGNIZED_KEYWORD) + X(MCIERR_UNRECOGNIZED_COMMAND) + X(MCIERR_HARDWARE) + X(MCIERR_INVALID_DEVICE_NAME) + X(MCIERR_OUT_OF_MEMORY) + X(MCIERR_DEVICE_OPEN) + X(MCIERR_CANNOT_LOAD_DRIVER) + X(MCIERR_MISSING_COMMAND_STRING) + X(MCIERR_PARAM_OVERFLOW) + X(MCIERR_MISSING_STRING_ARGUMENT) + X(MCIERR_BAD_INTEGER) + X(MCIERR_PARSER_INTERNAL) + X(MCIERR_DRIVER_INTERNAL) + X(MCIERR_MISSING_PARAMETER) + X(MCIERR_UNSUPPORTED_FUNCTION) + X(MCIERR_FILE_NOT_FOUND) + X(MCIERR_DEVICE_NOT_READY) + X(MCIERR_INTERNAL) + X(MCIERR_DRIVER) + X(MCIERR_CANNOT_USE_ALL) + X(MCIERR_MULTIPLE) + X(MCIERR_EXTENSION_NOT_FOUND) + X(MCIERR_OUTOFRANGE) + X(MCIERR_FLAGS_NOT_COMPATIBLE) + X(MCIERR_FILE_NOT_SAVED) + X(MCIERR_DEVICE_TYPE_REQUIRED) + X(MCIERR_DEVICE_LOCKED) + X(MCIERR_DUPLICATE_ALIAS) + X(MCIERR_BAD_CONSTANT) + X(MCIERR_MUST_USE_SHAREABLE) + X(MCIERR_MISSING_DEVICE_NAME) + X(MCIERR_BAD_TIME_FORMAT) + X(MCIERR_NO_CLOSING_QUOTE) + X(MCIERR_DUPLICATE_FLAGS) + X(MCIERR_INVALID_FILE) + X(MCIERR_NULL_PARAMETER_BLOCK) + X(MCIERR_UNNAMED_RESOURCE) + X(MCIERR_NEW_REQUIRES_ALIAS) + X(MCIERR_NOTIFY_ON_AUTO_OPEN) + X(MCIERR_NO_ELEMENT_ALLOWED) + X(MCIERR_NONAPPLICABLE_FUNCTION) + X(MCIERR_ILLEGAL_FOR_AUTO_OPEN) + X(MCIERR_FILENAME_REQUIRED) + X(MCIERR_EXTRA_CHARACTERS) + X(MCIERR_DEVICE_NOT_INSTALLED) + X(MCIERR_GET_CD) + X(MCIERR_SET_CD) + X(MCIERR_SET_DRIVE) + X(MCIERR_DEVICE_LENGTH) + X(MCIERR_DEVICE_ORD_LENGTH) + X(MCIERR_NO_INTEGER) + X(MCIERR_WAVE_OUTPUTSINUSE) + X(MCIERR_WAVE_SETOUTPUTINUSE) + X(MCIERR_WAVE_INPUTSINUSE) + X(MCIERR_WAVE_SETINPUTINUSE) + X(MCIERR_WAVE_OUTPUTUNSPECIFIED) + X(MCIERR_WAVE_INPUTUNSPECIFIED) + X(MCIERR_WAVE_OUTPUTSUNSUITABLE) + X(MCIERR_WAVE_SETOUTPUTUNSUITABLE) + X(MCIERR_WAVE_INPUTSUNSUITABLE) + X(MCIERR_WAVE_SETINPUTUNSUITABLE) + X(MCIERR_SEQ_DIV_INCOMPATIBLE) + X(MCIERR_SEQ_PORT_INUSE) + X(MCIERR_SEQ_PORT_NONEXISTENT) + X(MCIERR_SEQ_PORT_MAPNODEVICE) + X(MCIERR_SEQ_PORT_MISCERROR) + X(MCIERR_SEQ_TIMER) + X(MCIERR_SEQ_PORTUNSPECIFIED) + X(MCIERR_SEQ_NOMIDIPRESENT) + X(MCIERR_NO_WINDOW) + X(MCIERR_CREATEWINDOW) + X(MCIERR_FILE_READ) + X(MCIERR_FILE_WRITE) + X(MCIERR_NO_IDENTITY) +#undef X + default: { + static char name[20]; /* Not to be called twice in a parameter list! */ + sprintf(name, "MMSYSERR %u", err); + return name; + } + } +} + +static BOOL spurious_message(LPMSG msg) +{ + /* WM_DEVICECHANGE 0x0219 appears randomly */ + if(msg->message != MM_MCINOTIFY) { + trace("skipping spurious message %04x\n",msg->message); + return TRUE; + } + return FALSE; +} + +static void test_notification(HWND hwnd, const char* command, WPARAM type) +{ /* Use type 0 as meaning no message */ + MSG msg; + BOOL seen; + do { seen = PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE); } + while(seen && spurious_message(&msg)); + if(type==0) + ok(!seen, "Expect no message from command %s\n", command); + else + ok(seen, "PeekMessage should succeed for command %s\n", command); + if(seen) { + ok(msg.hwnd == hwnd, "Didn't get the handle to our test window\n"); + ok(msg.message == MM_MCINOTIFY, "got %04x instead of MM_MCINOTIFY from command %s\n", msg.message, command); + ok(msg.wParam == type, "got %04lx instead of MCI_NOTIFY_xyz %04lx from command %s\n", msg.wParam, type, command); + } +} +static void test_notification1(HWND hwnd, const char* command, WPARAM type) +{ /* This version works with todo_wine prefix. */ + MSG msg; + BOOL seen; + do { seen = PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE); } + while(seen && spurious_message(&msg)); + if(type==0) + ok(!seen, "Expect no message from command %s\n", command); + else if(seen) + ok(msg.message == MM_MCINOTIFY && msg.wParam == type,"got %04lx instead of MCI_NOTIFY_xyz %04lx from command %s\n", msg.wParam, type, command); + else ok(seen, "PeekMessage should succeed for command %s\n", command); +} + +static void test_openCloseWAVE(HWND hwnd) +{ + MCIERROR err; + MCI_GENERIC_PARMS parm; + const char command_open[] = "open new type waveaudio alias mysound notify"; const char command_close_my[] = "close mysound notify"; const char command_close_all[] = "close all notify"; const char command_sysinfo[] = "sysinfo waveaudio quantity open"; - MSG msg; char buf[1024]; + memset(buf, 0, sizeof(buf)); + test_notification(hwnd, "-prior to any command-", 0); + + err = mciSendString("sysinfo all quantity", buf, sizeof(buf), hwnd); + todo_wine ok(!err,"mci %s returned %s\n", command_open, dbg_mcierr(err)); + if(!err) trace("[MCI] with %s drivers\n", buf); + + err = mciSendString("open new type waveaudio alias r shareable", buf, sizeof(buf), NULL); + ok(err==MCIERR_UNSUPPORTED_FUNCTION,"mci open new shareable returned %s\n", dbg_mcierr(err)); + if(!err) { + err = mciSendString("close r", NULL, 0, NULL); + ok(!err,"mci close shareable returned %s\n", dbg_mcierr(err)); + } + + err = mciSendString(command_open, buf, sizeof(buf), hwnd); + ok(!err,"mci %s returned %s\n", command_open, dbg_mcierr(err)); + ok(!strcmp(buf,"1"), "mci open deviceId: %s, expected 1\n", buf); + /* Wine<=1.1.33 used to ignore anything past alias XY */ + test_notification(hwnd,"open new alias notify",MCI_NOTIFY_SUCCESSFUL); + + err = mciSendString("status mysound time format", buf, sizeof(buf), hwnd); + ok(!err,"mci status time format returned %s\n", dbg_mcierr(err)); + if(!err) { + if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) == LANG_ENGLISH) + ok(!strcmp(buf,"milliseconds"), "mci status time format: %s\n", buf); + else trace("locale-dependent time format: %s (ms)\n", buf); + } + + err = mciSendString(command_close_my, NULL, 0, hwnd); + ok(!err,"mci %s returned %s\n", command_close_my, dbg_mcierr(err)); + test_notification(hwnd, command_close_my, MCI_NOTIFY_SUCCESSFUL); + Sleep(5); + test_notification(hwnd, command_close_my, 0); + + err = mciSendString("open no-such-file-exists.wav alias y", buf, sizeof(buf), NULL); + ok(err==MCIERR_FILE_NOT_FOUND,"open no-such-file.wav returned %s\n", dbg_mcierr(err)); + if(!err) { + err = mciSendString("close y", NULL, 0, NULL); + ok(!err,"close y returned %s\n", dbg_mcierr(err)); + } + + err = mciSendString("open no-such-dir\\file.wav alias y type waveaudio", buf, sizeof(buf), NULL); + ok(err==MCIERR_FILE_NOT_FOUND || broken(err==MCIERR_INVALID_FILE /* Win9X */),"open no-such-dir/file.wav returned %s\n", dbg_mcierr(err)); + if(!err) { + err = mciSendString("close y", NULL, 0, NULL); + ok(!err,"close y returned %s\n", dbg_mcierr(err)); + } + + err = mciSendString(command_close_all, NULL, 0, NULL); + todo_wine ok(!err,"mci %s (without buffer) returned %s\n", command_close_all, dbg_mcierr(err)); + + memset(buf, 0, sizeof(buf)); + err = mciSendString(command_close_all, buf, sizeof(buf), hwnd); + todo_wine ok(!err,"mci %s (with output buffer) returned %s\n", command_close_all, dbg_mcierr(err)); + ok(buf[0] == 0, "mci %s changed output buffer: %s\n", command_close_all, buf); + /* No notification left, everything closed already */ + test_notification(hwnd, command_close_all, 0); + /* TODO test close all sends one notification per open device */ + + memset(buf, 0, sizeof(buf)); + err = mciSendString(command_sysinfo, buf, sizeof(buf), NULL); + ok(!err,"mci %s returned %s\n", command_sysinfo, dbg_mcierr(err)); + todo_wine ok(buf[0] == '0' && buf[1] == 0, "mci %s, expected output buffer '0', got: '%s'\n", command_sysinfo, buf); + + err = mciSendString("open new type waveaudio", buf, sizeof(buf), NULL); + ok(err==MCIERR_NEW_REQUIRES_ALIAS,"mci open new without alias returned %s\n", dbg_mcierr(err)); + + err = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, 0); /* from MSDN */ + ok(!err,"mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, 0) returned %s\n", dbg_mcierr(err)); + + err = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, 0); + ok(!err,"mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, 0) returned %s\n", dbg_mcierr(err)); + + parm.dwCallback = (DWORD_PTR)hwnd; + err = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, (DWORD_PTR)&parm); + ok(!err,"mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, hwnd) returned %s\n", dbg_mcierr(err)); + test_notification(hwnd, command_close_all, 0); /* None left */ +} + +static void test_recordWAVE(HWND hwnd) +{ + WORD nch = 1; + WORD nbits = 16; + DWORD nsamp = 16000, expect; + MCIERROR err, ok_pcm; + MCIDEVICEID wDeviceID; + MCI_PARMS_UNION parm; + char buf[1024]; + memset(buf, 0, sizeof(buf)); + test_notification(hwnd, "-prior to recording-", 0); + + parm.open.lpstrDeviceType = "waveaudio"; + parm.open.lpstrElementName = ""; /* "new" at the command level */ + parm.open.lpstrAlias = "x"; /* to enable mciSendString */ + parm.open.dwCallback = (DWORD_PTR)hwnd; + err = mciSendCommand(0, MCI_OPEN, + MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_OPEN_ALIAS | MCI_NOTIFY, + (DWORD_PTR)&parm); + ok(!err,"mciCommand open new type waveaudio alias x notify: %s\n", dbg_mcierr(err)); + wDeviceID = parm.open.wDeviceID; + + /* In Wine, both MCI_Open and the individual drivers send notifications. */ + test_notification(hwnd, "open new", MCI_NOTIFY_SUCCESSFUL); + todo_wine test_notification1(hwnd, "open new no #2", 0); + + /* Do not query time format as string because result depends on locale! */ + parm.status.dwItem = MCI_STATUS_TIME_FORMAT; + err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); + ok(!err,"mciCommand status time format: %s\n", dbg_mcierr(err)); + ok(parm.status.dwReturn==MCI_FORMAT_MILLISECONDS,"status time format: %ld\n",parm.status.dwReturn); + + /* Info file fails until named in Open or Save. */ + err = mciSendString("info x file", buf, sizeof(buf), NULL); + todo_wine ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci info new file returned %s\n", dbg_mcierr(err)); + + /* Check the default recording: 8-bits per sample, mono, 11kHz */ + err = mciSendString("status x samplespersec", buf, sizeof(buf), NULL); + ok(!err,"mci status samplespersec returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"11025"), "mci status samplespersec expected 11025, got: %s\n", buf); + + /* MCI seems to solely support PCM, no need for ACM conversion. */ + err = mciSendString("set x format tag 2", NULL, 0, NULL); + ok(err==MCIERR_OUTOFRANGE,"mci set format tag 2 returned %s\n", dbg_mcierr(err)); + + /* MCI appears to scan the available devices for support of this format, + * returning MCIERR_OUTOFRANGE on machines with no sound. + * Don't skip here, record will fail below. */ + err = mciSendString("set x format tag pcm", NULL, 0, NULL); + ok(!err || err==MCIERR_OUTOFRANGE,"mci set format tag pcm returned %s\n", dbg_mcierr(err)); + ok_pcm = err; + + err = mciSendString("set x samplespersec 41000 alignment 4 channels 2", NULL, 0, NULL); + ok(err==ok_pcm,"mci set samples+align+channels returned %s\n", dbg_mcierr(err)); + + /* Investigate: on w2k, set samplespersec 22050 sets nChannels to 2! + * err = mciSendString("set x samplespersec 22050", NULL, 0, NULL); + * ok(!err,"mci set samplespersec returned %s\n", dbg_mcierr(err)); + */ + + parm.set.wFormatTag = WAVE_FORMAT_PCM; + parm.set.nSamplesPerSec = nsamp; + parm.set.wBitsPerSample = nbits; + parm.set.nChannels = nch; + parm.set.nBlockAlign = parm.set.nChannels * parm.set.wBitsPerSample /8; + parm.set.nAvgBytesPerSec= parm.set.nSamplesPerSec * parm.set.nBlockAlign; + err = mciSendCommand(wDeviceID, MCI_SET, + MCI_WAVE_SET_SAMPLESPERSEC | MCI_WAVE_SET_CHANNELS | + MCI_WAVE_SET_BITSPERSAMPLE | MCI_WAVE_SET_BLOCKALIGN | + MCI_WAVE_SET_AVGBYTESPERSEC| MCI_WAVE_SET_FORMATTAG, (DWORD_PTR)&parm); + ok(err==ok_pcm,"mciCommand set wave format: %s\n", dbg_mcierr(err)); + + /* A few ME machines pass all tests except set format tag pcm! */ + err = mciSendString("record x to 2000 wait", NULL, 0, hwnd); + ok(err || !ok_pcm,"can record yet set wave format pcm returned %s\n", dbg_mcierr(ok_pcm)); + ok(!err || err==(ok_pcm==MCIERR_OUTOFRANGE ? MCIERR_WAVE_INPUTSUNSUITABLE : 0),"mci record to 2000 returned %s\n", dbg_mcierr(err)); + if(err) { + if (err==MCIERR_WAVE_INPUTSUNSUITABLE) + skip("Please install audio driver. Everything is skipped.\n"); + else skip("Cannot record cause %s. Everything is skipped.\n", dbg_mcierr(err)); + + err = mciSendString("close x", NULL, 0, NULL); + ok(!err,"mci close returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"record skipped",0); + return; + } + + /* Query some wave format parameters depending on the time format. */ + err = mciSendString("status x position", buf, sizeof(buf), NULL); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + if(!err) todo_wine ok(!strcmp(buf,"2000"), "mci status position gave %s, expected 2000, some tests will fail\n", buf); + + err = mciSendString("set x time format 8", NULL, 0, NULL); /* bytes */ + ok(!err,"mci returned %s\n", dbg_mcierr(err)); + + parm.status.dwItem = MCI_STATUS_POSITION; + err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); + ok(!err,"mciCommand status position: %s\n", dbg_mcierr(err)); + expect = 2 * nsamp * nch * nbits/8; + if(!err) todo_wine ok(parm.status.dwReturn==expect,"recorded %lu bytes, expected %u\n",parm.status.dwReturn,expect); + + parm.set.dwTimeFormat = MCI_FORMAT_SAMPLES; + err = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&parm); + ok(!err,"mciCommand set time format samples: %s\n", dbg_mcierr(err)); + + parm.status.dwItem = MCI_STATUS_POSITION; + err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); + ok(!err,"mciCommand status position: %s\n", dbg_mcierr(err)); + expect = 2 * nsamp; + if(!err) todo_wine ok(parm.status.dwReturn==expect,"recorded %lu samples, expected %u\n",parm.status.dwReturn,expect); + + err = mciSendString("set x time format milliseconds", NULL, 0, NULL); + ok(!err,"mci set time format milliseconds returned %s\n", dbg_mcierr(err)); + + err = mciSendString("save x tempfile1.wav", NULL, 0, NULL); + ok(!err,"mci save returned %s\n", dbg_mcierr(err)); + + err = mciSendString("save x tempfile.wav", NULL, 0, NULL); + ok(!err,"mci save returned %s\n", dbg_mcierr(err)); + if(!err) ok_saved = 0; + + /* Save must not rename the original file. */ + if (!DeleteFile("tempfile1.wav")) + todo_wine ok(FALSE, "Save must not rename the original file; DeleteFile returned %d\n", GetLastError()); + + err = mciSendString("set x channels 2", NULL, 0, NULL); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci set channels after saving returned %s\n", dbg_mcierr(err)); + + parm.seek.dwTo = 600; + err = mciSendCommand(wDeviceID, MCI_SEEK, MCI_TO | MCI_WAIT, (DWORD_PTR)&parm); + ok(!err,"mciCommand seek to 600: %s\n", dbg_mcierr(err)); + + /* Truncate to current position */ + err = mciSendString("delete x", NULL, 0, NULL); + todo_wine ok(!err,"mci delete returned %s\n", dbg_mcierr(err)); + + buf[0]='\0'; + err = mciSendString("status x length", buf, sizeof(buf), NULL); + ok(!err,"mci status length returned %s\n", dbg_mcierr(err)); + todo_wine ok(!strcmp(buf,"600"), "mci status length after delete gave %s, expected 600\n", buf); + + err = mciSendString("close x", NULL, 0, NULL); + ok(!err,"mci close returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"record complete",0); +} + +static void test_playWAVE(HWND hwnd) +{ + MCIERROR err; + char buf[1024]; + memset(buf, 0, sizeof(buf)); + + err = mciSendString("open waveaudio!tempfile.wav alias mysound", NULL, 0, NULL); + ok(err==ok_saved,"mci open waveaudio!tempfile.wav returned %s\n", dbg_mcierr(err)); + if(err) { + skip("Cannot open waveaudio!tempfile.wav for playing (%s), skipping\n", dbg_mcierr(err)); + return; + } + + err = mciSendString("status mysound length", buf, sizeof(buf), NULL); + ok(!err,"mci status length returned %s\n", dbg_mcierr(err)); + todo_wine ok(!strcmp(buf,"2000"), "mci status length gave %s, expected 2000, some tests will fail.\n", buf); + + err = mciSendString("cue output", NULL, 0, NULL); + todo_wine ok(err==MCIERR_UNRECOGNIZED_COMMAND,"mci incorrect cue output returned %s\n", dbg_mcierr(err)); + + /* Test MCI to the bones -- Some todo_wine from Cue and + * from Play from 0 to 0 are not worth fixing. */ + err = mciSendString("cue mysound output notify", NULL, 0, hwnd); + ok(!err,"mci cue output after open file returned %s\n", dbg_mcierr(err)); + /* Notification is delayed as a play thread is started. */ + todo_wine test_notification1(hwnd, "cue immediate", 0); + + /* Cue pretends to put the MCI into paused state. */ + err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + todo_wine ok(!strcmp(buf,"paused"), "mci status mode: %s, expected (pseudo)paused\n", buf); + + /* Strange pause where Pause is rejected, unlike Play; Pause; Pause tested below */ + err = mciSendString("pause mysound", NULL, 0, hwnd); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci pause after cue returned %s\n", dbg_mcierr(err)); + + /* MCI appears to start the play thread in this border case. + * Guessed that from (flaky) status mode and late notification arrival. */ + err = mciSendString("play mysound from 0 to 0 notify", NULL, 0, hwnd); + ok(!err,"mci play from 0 to 0 returned %s\n", dbg_mcierr(err)); + todo_wine test_notification1(hwnd, "cue aborted by play", MCI_NOTIFY_ABORTED); + /* play's own notification follows below */ + + err = mciSendString("play mysound from 250 to 0", NULL, 0, NULL); + ok(err==MCIERR_OUTOFRANGE,"mci play from 250 to 0 returned %s\n", dbg_mcierr(err)); + + Sleep(50); /* Give play from 0 to 0 time to finish. */ + todo_wine test_notification1(hwnd, "play from 0 to 0", MCI_NOTIFY_SUCCESSFUL); + + err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + ok(!strcmp(buf,"stopped"), "mci status mode: %s after play from 0 to 0\n", buf); + + err = mciSendString("play MYSOUND from 250 to 0 notify", NULL, 0, hwnd); + ok(err==MCIERR_OUTOFRANGE,"mci play from 250 to 0 notify returned %s\n", dbg_mcierr(err)); + /* No notification (checked below) sent if error */ + + /* A second play caused Wine<1.1.33 to hang */ + err = mciSendString("play mysound from 500 to 1500 wait", NULL, 0, NULL); + ok(!err,"mci play from 500 to 1500 returned %s\n", dbg_mcierr(err)); + + memset(buf, 0, sizeof(buf)); + err = mciSendString("status mysound position", buf, sizeof(buf), hwnd); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"1500"), "mci status position: %s\n", buf); + + /* mci will not play position < current */ + err = mciSendString("play mysound to 1000", NULL, 0, NULL); + ok(err==MCIERR_OUTOFRANGE,"mci play to 1000 returned %s\n", dbg_mcierr(err)); + + /* mci will not play to > end */ + err = mciSendString("play mysound TO 3000 notify", NULL, 0, hwnd); + ok(err==MCIERR_OUTOFRANGE,"mci play to 3000 notify returned %s\n", dbg_mcierr(err)); + + err = mciSendString("play mysound to 2000", NULL, 0, NULL); + ok(!err,"mci play to 2000 returned %s\n", dbg_mcierr(err)); + + /* Rejected while playing */ + err = mciSendString("cue mysound output", NULL, 0, NULL); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci cue output while playing returned %s\n", dbg_mcierr(err)); + + err = mciSendString("play mysound to 3000", NULL, 0, NULL); + ok(err==MCIERR_OUTOFRANGE,"mci play to 3000 returned %s\n", dbg_mcierr(err)); + + err = mciSendString("stop mysound Wait", NULL, 0, NULL); + ok(!err,"mci stop wait returned %s\n", dbg_mcierr(err)); + test_notification(hwnd, "play/cue/pause/stop", 0); + + err = mciSendString("Seek Mysound to 250 wait Notify", NULL, 0, hwnd); + ok(!err,"mci seek to 250 wait notify returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"seek wait notify",MCI_NOTIFY_SUCCESSFUL); + + memset(buf, 0, sizeof(buf)); + err = mciSendString("status mysound position notify", buf, sizeof(buf), hwnd); + ok(!err,"mci status position notify returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"250"), "mci status position: %s\n", buf); + /* Immediate commands like status also send notifications. */ + test_notification(hwnd,"status position",MCI_NOTIFY_SUCCESSFUL); + + memset(buf, 0, sizeof(buf)); + err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf); + + /* Another play from == to testcase */ + err = mciSendString("play mysound to 250 wait notify", NULL, 0, hwnd); + ok(!err,"mci play (from 250) to 250 returned %s\n", dbg_mcierr(err)); + todo_wine test_notification1(hwnd,"play to 250 wait notify",MCI_NOTIFY_SUCCESSFUL); + + err = mciSendString("cue mysound output", NULL, 0, NULL); + ok(!err,"mci cue output after play returned %s\n", dbg_mcierr(err)); + + err = mciSendString("close mysound", NULL, 0, NULL); + ok(!err,"mci close returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"after close",0); +} + +static void test_asyncWAVE(HWND hwnd) +{ + MCIDEVICEID wDeviceID; + MCI_PARMS_UNION parm; + int err, p1, p2; + char buf[1024]; + memset(buf, 0, sizeof(buf)); + + err = mciSendString("open tempfile.wav alias mysound notify", buf, sizeof(buf), hwnd); + ok(err==ok_saved,"mci open tempfile.wav returned %s\n", dbg_mcierr(err)); + if(err) { + skip("Cannot open tempfile.wav for playing (%s), skipping\n", dbg_mcierr(err)); + return; + } + ok(!strcmp(buf,"1"), "mci open deviceId: %s, expected 1\n", buf); + wDeviceID = atoi(buf); + ok(wDeviceID,"mci open DeviceID: %d\n", wDeviceID); + test_notification(hwnd,"open alias notify",MCI_NOTIFY_SUCCESSFUL); + + err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf); + + err = mciSendString("play mysound notify", NULL, 0, hwnd); + ok(!err,"mci play returned %s\n", dbg_mcierr(err)); + + /* Give Wine's asynchronous thread time to start up. Furthermore, + * it uses 3 buffers per second, so that the positions reported + * will be 333ms, 667ms etc. at best. */ + Sleep(100); /* milliseconds */ + + /* Do not query time format as string because result depends on locale! */ + parm.status.dwItem = MCI_STATUS_TIME_FORMAT; + err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); + ok(!err,"mciCommand status time format: %s\n", dbg_mcierr(err)); + if(!err) ok(parm.status.dwReturn==MCI_FORMAT_MILLISECONDS,"status time format: %ld\n",parm.status.dwReturn); + + parm.set.dwTimeFormat = MCI_FORMAT_MILLISECONDS; + err = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&parm); + ok(!err,"mciCommand set time format ms: %s\n", dbg_mcierr(err)); + + buf[0]=0; + err = mciSendString("status mysound position", buf, sizeof(buf), hwnd); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + ok(strcmp(buf,"2000"), "mci status position: %s, expected 2000\n", buf); + trace("position after Sleep: %sms\n",buf); + p2 = atoi(buf); + /* Some machines reach 79ms only during the 100ms sleep. */ + ok(p2>=67,"not enough time elapsed %ums\n",p2); + test_notification(hwnd,"play (nowait)",0); + + err = mciSendString("pause mysound wait", NULL, 0, hwnd); + ok(!err,"mci pause wait returned %s\n", dbg_mcierr(err)); + + buf[0]=0; + err = mciSendString("status mysound mode notify", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"paused"), "mci status mode: %s\n", buf); + test_notification(hwnd,"play",MCI_NOTIFY_SUPERSEDED); + test_notification(hwnd,"status",MCI_NOTIFY_SUCCESSFUL); + + buf[0]=0; + err = mciSendString("status mysound position", buf, sizeof(buf), hwnd); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + trace("position while paused: %sms\n",buf); + p1 = atoi(buf); + ok(p1>=p2, "position not increasing: %u > %u\n", p2, p1); + + err = mciSendString("stop mysound wait", NULL, 0, NULL); + ok(!err,"mci stop returned %s\n", dbg_mcierr(err)); + + buf[0]=0; + err = mciSendString("info mysound file notify", buf, sizeof(buf), hwnd); + ok(!err,"mci info file returned %s\n", dbg_mcierr(err)); + if(!err) { /* fully qualified name */ + int len = strlen(buf); + todo_wine ok(len>2 && buf[1]==':',"Expected full pathname from info file: %s\n", buf); + ok(len>=12 && !strcmp(&buf[len-12],"tempfile.wav"), "info file returned: %s\n", buf); + } + test_notification(hwnd,"info file",MCI_NOTIFY_SUCCESSFUL); + + buf[0]=0; + err = mciSendString("status mysound mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf); + + buf[0]=0; + err = mciSendString("status mysound position", buf, sizeof(buf), hwnd); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + trace("position once stopped: %sms\n",buf); + p2 = atoi(buf); + /* An XP machine let the position increase slightly after pause. */ + ok(p2>=p1 && p2<=p1+16,"position changed from %ums to %ums\n",p1,p2); + + /* No Resume once stopped (waveaudio, sequencer and cdaudio differ). */ + err = mciSendString("resume mysound wait", NULL, 0, NULL); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci resume wait returned %s\n", dbg_mcierr(err)); + + err = mciSendString("play mysound wait", NULL, 0, NULL); + ok(!err,"mci play wait returned %s\n", dbg_mcierr(err)); + + buf[0]=0; + err = mciSendString("status mysound position", buf, sizeof(buf), hwnd); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + todo_wine ok(!strcmp(buf,"2000"), "mci status position: %s\n", buf); + + err = mciSendString("seek mysound to start wait", NULL, 0, NULL); + ok(!err,"mci seek to start wait returned %s\n", dbg_mcierr(err)); + + err = mciSendString("play mysound to 1000 notify", NULL, 0, hwnd); + ok(!err,"mci play returned %s\n", dbg_mcierr(err)); + + /* Sleep(200); not needed with Wine any more. */ + + err = mciSendString("pause mysound notify", NULL, 0, NULL); /* notify no callback */ + ok(!err,"mci pause notify returned %s\n", dbg_mcierr(err)); + /* Supersede even though pause cannot notify given no callback */ + test_notification(hwnd,"pause aborted play #1 notification",MCI_NOTIFY_SUPERSEDED); + test_notification(hwnd,"impossible pause notification",0); + + err = mciSendString("cue mysound output notify", NULL, 0, hwnd); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci cue output while paused returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"cue output notify #2",0); + + err = mciSendString("resume mysound notify", NULL, 0, hwnd); + ok(!err,"mci resume notify returned %s\n", dbg_mcierr(err)); + test_notification(hwnd, "resume notify", MCI_NOTIFY_SUCCESSFUL); + + /* Seek or even Stop used to hang Wine<1.1.32 on MacOS. */ + err = mciSendString("seek mysound to 0 wait", NULL, 0, NULL); + ok(!err,"mci seek to start returned %s\n", dbg_mcierr(err)); + + /* Seek stops. */ + err = mciSendString("status mysound mode", buf, sizeof(buf), NULL); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"stopped"), "mci status mode: %s\n", buf); + + err = mciSendString("seek mysound wait", NULL, 0, NULL); + ok(err==MCIERR_MISSING_PARAMETER,"mci seek to nowhere returned %s\n", dbg_mcierr(err)); + + /* cdaudio does not detect to start to end as error */ + err = mciSendString("seek mysound to start to 0", NULL, 0, NULL); + ok(err==MCIERR_FLAGS_NOT_COMPATIBLE,"mci seek to start to 0 returned %s\n", dbg_mcierr(err)); + + err = mciSendString("PLAY mysound to 1000 notify", NULL, 0, hwnd); + ok(!err,"mci play to 1000 notify returned %s\n", dbg_mcierr(err)); + + /* Sleep(200); not needed with Wine any more. */ + /* Give it 400ms and resume will appear to complete below. */ + + err = mciSendString("pause mysound wait", NULL, 0, NULL); + ok(!err,"mci pause wait returned %s\n", dbg_mcierr(err)); + /* Unlike sequencer and cdaudio, waveaudio's pause does not abort. */ + test_notification(hwnd,"pause aborted play #2 notification",0); + + err = mciSendString("resume mysound wait", NULL, 0, NULL); + ok(!err,"mci resume wait returned %s\n", dbg_mcierr(err)); + /* Resume is a short asynchronous call, something else is playing. */ + + err = mciSendString("status mysound mode", buf, sizeof(buf), NULL); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"playing"), "mci status mode: %s\n", buf); + + /* Note extra space before alias */ + err = mciSendString("pause mysound wait", NULL, 0, NULL); + todo_wine ok(!err,"mci pause (space) wait returned %s\n", dbg_mcierr(err)); + + err = mciSendString("pause mysound wait", NULL, 0, NULL); + ok(!err,"mci pause wait returned %s\n", dbg_mcierr(err)); + + /* Better ask position only when paused, is it updated while playing? */ + buf[0]='\0'; + err = mciSendString("status mysound position", buf, sizeof(buf), NULL); + ok(!err,"mci status position returned %s\n", dbg_mcierr(err)); + /* TODO compare position < 900 */ + ok(strcmp(buf,"1000"), "mci resume waited\n"); + ok(strcmp(buf,"2000"), "mci resume played to end\n"); + trace("position after resume: %sms\n",buf); + test_notification(hwnd,"play (aborted by pause/resume/pause)",0); + + err = mciSendString("close mysound wait", NULL, 0, NULL); + ok(!err,"mci close wait returned %s\n", dbg_mcierr(err)); + test_notification(hwnd,"play (aborted by close)",MCI_NOTIFY_ABORTED); +} + +static void test_AutoOpenWAVE(HWND hwnd) +{ + /* This test used(?) to cause intermittent crashes when Wine exits, after + * fixme:winmm:MMDRV_Exit Closing while ll-driver open + */ + MCIERROR err, ok_snd; + char buf[512], path[300], command[330]; + memset(buf, 0, sizeof(buf)); memset(path, 0, sizeof(path)); + + /* Do not crash on NULL buffer pointer */ + err = mciSendString("sysinfo waveaudio quantity open", NULL, 0, NULL); + ok(err==MCIERR_PARAM_OVERFLOW,"mci sysinfo without buffer returned %s\n", dbg_mcierr(err)); + + err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL); + ok(!err,"mci sysinfo waveaudio quantity open returned %s\n", dbg_mcierr(err)); + if(!err) todo_wine ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0, got: %s, some more tests will fail.\n", buf); + + ok_snd = waveOutGetNumDevs() ? 0 : MCIERR_HARDWARE; + err = mciSendString("sound NoSuchSoundDefined wait", NULL, 0, NULL); + todo_wine ok(err==ok_snd,"mci sound NoSuchSoundDefined returned %s\n", dbg_mcierr(err)); + + err = mciSendString("sound SystemExclamation notify wait", NULL, 0, hwnd); + todo_wine ok(err==ok_snd,"mci sound SystemExclamation returned %s\n", dbg_mcierr(err)); + test_notification(hwnd, "sound notify", err ? 0 : MCI_NOTIFY_SUCCESSFUL); + + buf[0]=0; + err = mciSendString("sysinfo waveaudio name 1 open", buf, sizeof(buf), NULL); + todo_wine ok(err==MCIERR_OUTOFRANGE,"sysinfo waveaudio name 1 returned %s\n", dbg_mcierr(err)); + if(!err) trace("sysinfo dangling open alias: %s\n", buf); + + err = mciSendString("play no-such-file-exists.wav notify", buf, sizeof(buf), NULL); + if(err==MCIERR_FILE_NOT_FOUND) { /* a Wine detector */ + /* Unsupported auto-open leaves the file open, preventing clean-up */ + skip("Skipping auto-open tests in Wine\n"); + return; + } + + err = mciSendString("play tempfile.wav notify", buf, sizeof(buf), hwnd); + todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN,"mci auto-open play notify returned %s\n", dbg_mcierr(err)); + + if(err) /* FIXME: don't open twice yet, it confuses Wine. */ + err = mciSendString("play tempfile.wav", buf, sizeof(buf), hwnd); + ok(err==ok_saved,"mci auto-open play returned %s\n", dbg_mcierr(err)); + + if(err==MCIERR_FILE_NOT_FOUND) { + skip("Cannot open tempfile.wav for auto-play, skipping\n"); + return; + } + + buf[0]=0; + err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL); + ok(!err,"mci sysinfo waveaudio quantity after auto-open returned %s\n", dbg_mcierr(err)); + if(!err) todo_wine ok(!strcmp(buf,"1"), "sysinfo quantity open expected 1, got: %s\n", buf); + + buf[0]=0; + err = mciSendString("sysinfo waveaudio name 1 open", buf, sizeof(buf), NULL); + todo_wine ok(!err,"mci sysinfo waveaudio name after auto-open returned %s\n", dbg_mcierr(err)); + /* This is the alias, not necessarily a file name. */ + if(!err) ok(!strcmp(buf,"tempfile.wav"), "sysinfo name 1 open: %s\n", buf); + + /* Save the full pathname to the file. */ + err = mciSendString("info tempfile.wav file", path, sizeof(path), NULL); + ok(!err,"mci info tempfile.wav file returned %s\n", dbg_mcierr(err)); + if(err) strcpy(path,"tempfile.wav"); + + err = mciSendString("status tempfile.wav mode", NULL, 0, hwnd); + ok(!err,"mci status tempfile.wav mode without buffer returned %s\n", dbg_mcierr(err)); + + sprintf(command,"status \"%s\" mode",path); + err = mciSendString(command, buf, sizeof(buf), hwnd); + ok(!err,"mci status \"%s\" mode returned %s\n", path, dbg_mcierr(err)); + + buf[0]=0; + err = mciSendString("status tempfile.wav mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status tempfile.wav mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"playing"), "mci auto-open status mode, got: %s\n", buf); + + err = mciSendString("open tempfile.wav", buf, sizeof(buf), NULL); + todo_wine ok(err==MCIERR_DEVICE_OPEN, "mci open from auto-open returned %s\n", dbg_mcierr(err)); + + /* w2k/xp and Wine differ. While the device is busy playing, it is + * regularly open and accessible via the filename: subsequent + * commands must not cause auto-open each. In Wine, a subsequent + * command with notify request may cause the initial play + * notification to be superseded, in turn causing MCI to close the + * device. I.e. MCI uses the auto-open notification for itself, + * that's why it's not available to the app. On w2k/xp, + * subsequent commands with notify requests are returned with + * MCIERR_NOTIFY_ON_AUTO_OPEN and thus don't abort the original + * command. + */ + err = mciSendString("status tempfile.wav mode notify", buf, sizeof(buf), hwnd); + todo_wine ok(err==MCIERR_NOTIFY_ON_AUTO_OPEN, "mci status auto-open notify returned %s\n", dbg_mcierr(err)); + if(!err) { + trace("Wine style MCI auto-close upon notification\n"); + + /* "playing" because auto-close comes after the status call. */ + todo_wine ok(!strcmp(buf,"playing"), "mci auto-open status mode notify, got: %s\n", buf); + /* fixme:winmm:MMDRV_Exit Closing while ll-driver open + * is explained by failure to auto-close a device. */ + test_notification(hwnd,"status notify",MCI_NOTIFY_SUCCESSFUL); + /* MCI received NOTIFY_SUPERSEDED and auto-closed the device. */ + Sleep(16); + test_notification(hwnd,"auto-open",0); + } else if(err==MCIERR_NOTIFY_ON_AUTO_OPEN) { /* MS style */ + trace("MS style MCI auto-open forbids notification\n"); + + err = mciSendString("pause tempfile.wav", NULL, 0, hwnd); + ok(!err,"mci auto-still-open pause returned %s\n", dbg_mcierr(err)); + + err = mciSendString("status tempfile.wav mode", buf, sizeof(buf), hwnd); + ok(!err,"mci status mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"paused"), "mci auto-open status mode, got: %s\n", buf); + + /* Auto-close */ + err = mciSendString("stop tempfile.wav", NULL, 0, hwnd); + ok(!err,"mci auto-still-open stop returned %s\n", dbg_mcierr(err)); + Sleep(16); /* makes sysinfo quantity open below succeed */ + } + + err = mciSendString("sysinfo waveaudio quantity open", buf, sizeof(buf), NULL); + ok(!err,"mci sysinfo waveaudio quantity open after close returned %s\n", dbg_mcierr(err)); + if(!err) todo_wine ok(!strcmp(buf,"0"), "sysinfo quantity open expected 0 after auto-close, got: %s\n", buf); + + /* w95-WinME (not w2k/XP) switch to C:\ after auto-playing once. Prevent + * MCIERR_FILE_NOT_FOUND by using the full path name from the Info file command. + */ + sprintf(command,"status \"%s\" mode wait",path); + err = mciSendString(command, buf, sizeof(buf), hwnd); + ok(!err,"mci re-auto-open status mode returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"stopped"), "mci re-auto-open status mode, got: %s\n", buf); + + err = mciSendString("capability waveaudio device type", buf, sizeof(buf), hwnd); + ok(!err,"mci capability device type returned %s\n", dbg_mcierr(err)); + if(!err) ok(!strcmp(buf,"waveaudio"), "mci capability device type response: %s\n", buf); + + /* waveaudio forbids Pause without Play. */ + sprintf(command,"pause \"%s\"",path); + err = mciSendString(command, NULL, 0, hwnd); + ok(err==MCIERR_NONAPPLICABLE_FUNCTION,"mci auto-open pause returned %s\n", dbg_mcierr(err)); +} + +START_TEST(mci) +{ + MCIERROR err; HWND hwnd; - hwnd = CreateWindowExA(0, "static", "winmm test", WS_POPUP, 0,0,100,100, 0, 0, 0, NULL); - - err = mciSendString(command_open, NULL, 0, NULL); - ok(!err,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_open, err); - - err = mciSendString(command_close_my, NULL, 0, hwnd); - ok(!err,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_close_my, err); - - ok(PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "PeekMessage should succeed\n"); - ok(msg.hwnd == hwnd, "Didn't get the handle to our test window\n"); - ok(msg.message == MM_MCINOTIFY, "got %04x instead of MM_MCINOTIFY\n", msg.message); - ok(msg.wParam == MCI_NOTIFY_SUCCESSFUL, "got %08lx instead of MCI_NOTIFY_SUCCESSFUL\n", msg.wParam); - - err = mciSendString(command_close_all, NULL, 0, NULL); - todo_wine ok(!err,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_close_all, err); - - memset(buf, 0, sizeof(buf)); - err = mciSendString(command_close_all, buf, sizeof(buf), hwnd); - todo_wine ok(!err,"mciSendString(%s, buf, sizeof(buf) , NULL) returned error: %d\n", command_close_all, err); - ok(buf[0] == 0, "mciSendString(%s, buf, sizeof(buf) , NULL) changed output buffer: %s\n", command_close_all, buf); - - memset(buf, 0, sizeof(buf)); - err = mciSendString(command_sysinfo, buf, sizeof(buf), NULL); - ok(!err,"mciSendString(%s, buf, sizeof(buf) , NULL) returned error: %d\n", command_sysinfo, err); - todo_wine ok(buf[0] == '0' && buf[1] == 0, "mciSendString(%s, buf, sizeof(buf) , NULL), expected output buffer '0', got: '%s'\n", command_sysinfo, buf); - - err = mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, 0); - todo_wine ok(err == MCIERR_INVALID_DEVICE_ID || - broken(!err), /* Win9x and WinMe */ - "mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_NOTIFY, NULL) returned %d instead of %d\n", - err, MCIERR_INVALID_DEVICE_ID); - + test_openCloseWAVE(hwnd); + test_recordWAVE(hwnd); + test_playWAVE(hwnd); + test_asyncWAVE(hwnd); + test_AutoOpenWAVE(hwnd); + /* Win9X hangs when exiting with something still open. */ + err = mciSendString("close all", NULL, 0, hwnd); + todo_wine ok(!err,"final close all returned %s\n", dbg_mcierr(err)); + ok(DeleteFile("tempfile.wav")||ok_saved,"Delete tempfile.wav (cause auto-open?)\n"); DestroyWindow(hwnd); }
15 years
1
0
0
0
[cwittich] 44739: [wldap32_winetest] sync wldap32_winetest to wine 1.1.35
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Dec 23 16:58:59 2009 New Revision: 44739 URL:
http://svn.reactos.org/svn/reactos?rev=44739&view=rev
Log: [wldap32_winetest] sync wldap32_winetest to wine 1.1.35 Modified: trunk/rostests/winetests/wldap32/parse.c Modified: trunk/rostests/winetests/wldap32/parse.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/wldap32/parse.c…
============================================================================== --- trunk/rostests/winetests/wldap32/parse.c [iso-8859-1] (original) +++ trunk/rostests/winetests/wldap32/parse.c [iso-8859-1] Wed Dec 23 16:58:59 2009 @@ -57,8 +57,13 @@ ok( !ret, "ldap_search_ext_sA failed 0x%x\n", ret ); ok( res != NULL, "expected res != NULL\n" ); - ret = ldap_parse_resultA( NULL, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); - ok( ret == LDAP_PARAM_ERROR, "ldap_parse_resultA failed 0x%x\n", ret ); + if (GetProcAddress(GetModuleHandle("wldap32.dll"), "ber_init")) + { + ret = ldap_parse_resultA( NULL, res, &result, NULL, NULL, NULL, &server_ctrls, 1 ); + ok( ret == LDAP_PARAM_ERROR, "ldap_parse_resultA failed 0x%x\n", ret ); + } + else + win_skip("Test would crash on older wldap32 versions\n"); result = ~0u; ret = ldap_parse_resultA( ld, res, &result, NULL, NULL, NULL, &server_ctrls, 1 );
15 years
1
0
0
0
[cwittich] 44738: [advapi32_winetest] add eventlog tests to build
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Dec 23 16:57:45 2009 New Revision: 44738 URL:
http://svn.reactos.org/svn/reactos?rev=44738&view=rev
Log: [advapi32_winetest] add eventlog tests to build Modified: trunk/rostests/winetests/advapi32/advapi32.rbuild trunk/rostests/winetests/advapi32/testlist.c Modified: trunk/rostests/winetests/advapi32/advapi32.rbuild URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/advapi…
============================================================================== --- trunk/rostests/winetests/advapi32/advapi32.rbuild [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/advapi32.rbuild [iso-8859-1] Wed Dec 23 16:57:45 2009 @@ -13,6 +13,7 @@ <file>crypt_md4.c</file> <file>crypt_md5.c</file> <file>crypt_sha.c</file> + <file>eventlog.c</file> <file>lsa.c</file> <file>registry.c</file> <file>security.c</file> Modified: trunk/rostests/winetests/advapi32/testlist.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/testli…
============================================================================== --- trunk/rostests/winetests/advapi32/testlist.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/testlist.c [iso-8859-1] Wed Dec 23 16:57:45 2009 @@ -12,6 +12,7 @@ extern void func_crypt_md4(void); extern void func_crypt_md5(void); extern void func_crypt_sha(void); +extern void func_eventlog(void); extern void func_lsa(void); extern void func_registry(void); extern void func_security(void); @@ -25,6 +26,7 @@ { "crypt_md4", func_crypt_md4 }, { "crypt_md5", func_crypt_md5 }, { "crypt_sha", func_crypt_sha }, + { "eventlog", func_eventlog }, { "lsa", func_lsa }, { "registry", func_registry }, { "security", func_security },
15 years
1
0
0
0
[tkreuzer] 44737: Fix release builds
by tkreuzer@svn.reactos.org
Author: tkreuzer Date: Wed Dec 23 16:32:54 2009 New Revision: 44737 URL:
http://svn.reactos.org/svn/reactos?rev=44737&view=rev
Log: Fix release builds Modified: trunk/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c Modified: trunk/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/freeldr/freeldr/windo…
============================================================================== --- trunk/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c [iso-8859-1] (original) +++ trunk/reactos/boot/freeldr/freeldr/windows/i386/wlmemory.c [iso-8859-1] Wed Dec 23 16:32:54 2009 @@ -537,6 +537,7 @@ */ } +#if DBG VOID MempDump() { @@ -557,4 +558,5 @@ DPRINTM(DPRINT_WINDOWS, "\n"); } } - +#endif +
15 years
1
0
0
0
[cwittich] 44736: [advapi32_winetest] sync advapi32_winetest with wine 1.1.35
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Dec 23 16:15:54 2009 New Revision: 44736 URL:
http://svn.reactos.org/svn/reactos?rev=44736&view=rev
Log: [advapi32_winetest] sync advapi32_winetest with wine 1.1.35 Added: trunk/rostests/winetests/advapi32/eventlog.c (with props) Modified: trunk/rostests/winetests/advapi32/crypt.c trunk/rostests/winetests/advapi32/registry.c trunk/rostests/winetests/advapi32/security.c trunk/rostests/winetests/advapi32/service.c Modified: trunk/rostests/winetests/advapi32/crypt.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/crypt.…
============================================================================== --- trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/crypt.c [iso-8859-1] Wed Dec 23 16:15:54 2009 @@ -234,6 +234,7 @@ result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash); ok (result, "%d\n", GetLastError()); if (!result) return; + pCryptDestroyHash(hHash); result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey); ok (result, "%d\n", GetLastError()); @@ -557,6 +558,7 @@ ok(!strcmp(pszProvName, provider), "expected %s, got %s\n", pszProvName, provider); ok(cbName==providerLen, "expected %d, got %d\n", cbName, providerLen); + LocalFree(pszProvName); LocalFree(provider); } @@ -844,6 +846,7 @@ ok(!strcmp(pszProvName, provName), "expected %s, got %s\n", pszProvName, provName); ok(provNameSize==cbProvName, "expected %d, got %d\n", cbProvName, provNameSize); + LocalFree(pszProvName); LocalFree(provName); } @@ -933,17 +936,156 @@ RegCloseKey(key); } +#define key_length 16 + +static const unsigned char key[key_length] = + { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd, + 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 }; + +static void test_rc2_keylen(void) +{ + struct KeyBlob + { + BLOBHEADER header; + DWORD key_size; + BYTE key_data[2048]; + } key_blob; + + HCRYPTPROV provider; + HCRYPTKEY hkey = 0; + BOOL ret; + + SetLastError(0xdeadbeef); + ret = pCryptAcquireContextA(&provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + ok(ret, "CryptAcquireContext error %u\n", GetLastError()); + if (ret) + { + key_blob.header.bType = PLAINTEXTKEYBLOB; + key_blob.header.bVersion = CUR_BLOB_VERSION; + key_blob.header.reserved = 0; + key_blob.header.aiKeyAlg = CALG_RC2; + key_blob.key_size = sizeof(key); + memcpy(key_blob.key_data, key, key_length); + + /* Importing a 16-byte key works with the default provider. */ + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, CRYPT_IPSEC_HMAC_KEY, &hkey); + /* CRYPT_IPSEC_HMAC_KEY is not supported on W2K and lower */ + todo_wine + ok(ret || + broken(!ret && GetLastError() == NTE_BAD_FLAGS), + "CryptImportKey error %08x\n", GetLastError()); + + if (ret) + pCryptDestroyKey(hkey); + pCryptReleaseContext(provider, 0); + } + + SetLastError(0xdeadbeef); + ret = pCryptAcquireContextA(&provider, NULL, MS_DEF_PROV, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + ok(ret, "CryptAcquireContext error %08x\n", GetLastError()); + + if (ret) + { + /* Importing a 16-byte key doesn't work with the base provider.. */ + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, 0, &hkey); + ok(!ret && (GetLastError() == NTE_BAD_DATA || + GetLastError() == NTE_BAD_LEN || /* Win7 */ + GetLastError() == NTE_BAD_TYPE || /* W2K */ + GetLastError() == NTE_PERM), /* Win9x, WinMe and NT4 */ + "unexpected error %08x\n", GetLastError()); + /* but importing an 56-bit (7-byte) key does.. */ + key_blob.key_size = 7; + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, 0, &hkey); + ok(ret || + broken(!ret && GetLastError() == NTE_BAD_TYPE) || /* W2K */ + broken(!ret && GetLastError() == NTE_PERM), /* Win9x, WinMe and NT4 */ + "CryptAcquireContext error %08x\n", GetLastError()); + if (ret) + pCryptDestroyKey(hkey); + /* as does importing a 16-byte key with the base provider when + * CRYPT_IPSEC_HMAC_KEY is specified. + */ + key_blob.key_size = sizeof(key); + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, CRYPT_IPSEC_HMAC_KEY, &hkey); + /* CRYPT_IPSEC_HMAC_KEY is not supported on W2K and lower */ + todo_wine + ok(ret || + broken(!ret && GetLastError() == NTE_BAD_FLAGS), + "CryptImportKey error %08x\n", GetLastError()); + if (ret) + pCryptDestroyKey(hkey); + + pCryptReleaseContext(provider, 0); + } + + key_blob.key_size = sizeof(key); + SetLastError(0xdeadbeef); + ret = pCryptAcquireContextA(&provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + ok(ret, "CryptAcquireContext error %08x\n", GetLastError()); + + if (ret) + { + /* Importing a 16-byte key also works with the default provider when + * CRYPT_IPSEC_HMAC_KEY is specified. + */ + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, CRYPT_IPSEC_HMAC_KEY, &hkey); + todo_wine + ok(ret || + broken(!ret && GetLastError() == NTE_BAD_FLAGS), + "CryptImportKey error %08x\n", GetLastError()); + if (ret) + pCryptDestroyKey(hkey); + + /* There is no apparent limit to the size of the input key when + * CRYPT_IPSEC_HMAC_KEY is specified. + */ + key_blob.key_size = sizeof(key_blob.key_data); + SetLastError(0xdeadbeef); + ret = pCryptImportKey(provider, (BYTE*)&key_blob, + sizeof(BLOBHEADER)+sizeof(DWORD)+key_blob.key_size, + 0, CRYPT_IPSEC_HMAC_KEY, &hkey); + todo_wine + ok(ret || + broken(!ret && GetLastError() == NTE_BAD_FLAGS), + "CryptImportKey error %08x\n", GetLastError()); + if (ret) + pCryptDestroyKey(hkey); + + pCryptReleaseContext(provider, 0); + } +} + START_TEST(crypt) { - init_function_pointers(); - if(pCryptAcquireContextA && pCryptReleaseContext) { + init_function_pointers(); + if (pCryptAcquireContextA && pCryptReleaseContext) + { + test_rc2_keylen(); init_environment(); test_acquire_context(); test_incorrect_api_usage(); test_verify_sig(); test_machine_guid(); clean_up_environment(); - } + } test_enum_providers(); test_enum_provider_types(); Added: trunk/rostests/winetests/advapi32/eventlog.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/eventl…
============================================================================== --- trunk/rostests/winetests/advapi32/eventlog.c (added) +++ trunk/rostests/winetests/advapi32/eventlog.c [iso-8859-1] Wed Dec 23 16:15:54 2009 @@ -1,0 +1,1144 @@ +/* + * Unit tests for Event Logging functions + * + * Copyright (c) 2009 Paul Vriens + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winnt.h" +#include "winreg.h" +#include "sddl.h" + +#include "wine/test.h" + +static BOOL (WINAPI *pCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*); +static BOOL (WINAPI *pGetEventLogInformation)(HANDLE,DWORD,LPVOID,DWORD,LPDWORD); + +static BOOL (WINAPI *pGetComputerNameExA)(COMPUTER_NAME_FORMAT,LPSTR,LPDWORD); +static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID *); +static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID); + +static void init_function_pointers(void) +{ + HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); + HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); + + pCreateWellKnownSid = (void*)GetProcAddress(hadvapi32, "CreateWellKnownSid"); + pGetEventLogInformation = (void*)GetProcAddress(hadvapi32, "GetEventLogInformation"); + + pGetComputerNameExA = (void*)GetProcAddress(hkernel32, "GetComputerNameExA"); + pWow64DisableWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64DisableWow64FsRedirection"); + pWow64RevertWow64FsRedirection = (void*)GetProcAddress(hkernel32, "Wow64RevertWow64FsRedirection"); +} + +static void create_backup(const char *filename) +{ + HANDLE handle; + + DeleteFileA(filename); + handle = OpenEventLogA(NULL, "Application"); + BackupEventLogA(handle, filename); + CloseEventLog(handle); + + todo_wine + ok(GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n"); +} + +static void test_open_close(void) +{ + HANDLE handle; + BOOL ret; + + SetLastError(0xdeadbeef); + ret = CloseEventLog(NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE || + GetLastError() == ERROR_NOACCESS, /* W2K */ + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenEventLogA(NULL, NULL); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenEventLogA("IDontExist", NULL); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenEventLogA("IDontExist", "deadbeef"); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || + GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */ + "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError()); + + /* This one opens the Application log */ + handle = OpenEventLogA(NULL, "deadbeef"); + ok(handle != NULL, "Expected a handle\n"); + ret = CloseEventLog(handle); + ok(ret, "Expected success\n"); + /* Close a second time */ + SetLastError(0xdeadbeef); + ret = CloseEventLog(handle); + todo_wine + { + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + } + + /* Empty servername should be read as local server */ + handle = OpenEventLogA("", "Application"); + ok(handle != NULL, "Expected a handle\n"); + CloseEventLog(handle); + + handle = OpenEventLogA(NULL, "Application"); + ok(handle != NULL, "Expected a handle\n"); + CloseEventLog(handle); +} + +static void test_info(void) +{ + HANDLE handle; + BOOL ret; + DWORD needed; + EVENTLOG_FULL_INFORMATION efi; + + if (!pGetEventLogInformation) + { + /* NT4 */ + win_skip("GetEventLogInformation is not available\n"); + return; + } + SetLastError(0xdeadbeef); + ret = pGetEventLogInformation(NULL, 1, NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_LEVEL, "Expected ERROR_INVALID_LEVEL, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetEventLogInformation(NULL, EVENTLOG_FULL_INFO, NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + handle = OpenEventLogA(NULL, "Application"); + + SetLastError(0xdeadbeef); + ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, NULL, 0, &needed); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == RPC_X_NULL_REF_POINTER, "Expected RPC_X_NULL_REF_POINTER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + needed = 0xdeadbeef; + efi.dwFull = 0xdeadbeef; + ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, 0, &needed); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError()); + ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed); + ok(efi.dwFull == 0xdeadbeef, "Expected no change to the dwFull member\n"); + + /* Not that we care, but on success last error is set to ERROR_IO_PENDING */ + efi.dwFull = 0xdeadbeef; + needed *= 2; + ret = pGetEventLogInformation(handle, EVENTLOG_FULL_INFO, (LPVOID)&efi, needed, &needed); + ok(ret, "Expected success\n"); + ok(needed == sizeof(EVENTLOG_FULL_INFORMATION), "Expected sizeof(EVENTLOG_FULL_INFORMATION), got %d\n", needed); + ok(efi.dwFull == 0 || efi.dwFull == 1, "Expected 0 (not full) or 1 (full), got %d\n", efi.dwFull); + + CloseEventLog(handle); +} + +static void test_count(void) +{ + HANDLE handle; + BOOL ret; + DWORD count; + const char backup[] = "backup.evt"; + + SetLastError(0xdeadbeef); + ret = GetNumberOfEventLogRecords(NULL, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(NULL, &count); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + ok(count == 0xdeadbeef, "Expected count to stay unchanged\n"); + + handle = OpenEventLogA(NULL, "Application"); + + SetLastError(0xdeadbeef); + ret = GetNumberOfEventLogRecords(handle, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(handle, &count); + ok(ret, "Expected success\n"); + ok(count != 0xdeadbeef, "Expected the number of records\n"); + + CloseEventLog(handle); + + /* Make a backup eventlog to work with */ + create_backup(backup); + + handle = OpenBackupEventLogA(NULL, backup); + todo_wine + ok(handle != NULL, "Expected a handle\n"); + + /* Does GetNumberOfEventLogRecords work with backup eventlogs? */ + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(handle, &count); + todo_wine + { + ok(ret, "Expected success\n"); + ok(count != 0xdeadbeef, "Expected the number of records\n"); + } + + CloseEventLog(handle); + DeleteFileA(backup); +} + +static void test_oldest(void) +{ + HANDLE handle; + BOOL ret; + DWORD oldest; + const char backup[] = "backup.evt"; + + SetLastError(0xdeadbeef); + ret = GetOldestEventLogRecord(NULL, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + oldest = 0xdeadbeef; + ret = GetOldestEventLogRecord(NULL, &oldest); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + ok(oldest == 0xdeadbeef, "Expected oldest to stay unchanged\n"); + + handle = OpenEventLogA(NULL, "Application"); + + SetLastError(0xdeadbeef); + ret = GetOldestEventLogRecord(handle, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + oldest = 0xdeadbeef; + ret = GetOldestEventLogRecord(handle, &oldest); + ok(ret, "Expected success\n"); + ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n"); + + CloseEventLog(handle); + + /* Make a backup eventlog to work with */ + create_backup(backup); + + handle = OpenBackupEventLogA(NULL, backup); + todo_wine + ok(handle != NULL, "Expected a handle\n"); + + /* Does GetOldestEventLogRecord work with backup eventlogs? */ + oldest = 0xdeadbeef; + ret = GetOldestEventLogRecord(handle, &oldest); + todo_wine + { + ok(ret, "Expected success\n"); + ok(oldest != 0xdeadbeef, "Expected the number of the oldest record\n"); + } + + CloseEventLog(handle); + DeleteFileA(backup); +} + +static void test_backup(void) +{ + HANDLE handle; + BOOL ret; + const char backup[] = "backup.evt"; + const char backup2[] = "backup2.evt"; + + SetLastError(0xdeadbeef); + ret = BackupEventLogA(NULL, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = BackupEventLogA(NULL, backup); + ok(!ret, "Expected failure\n"); + ok(GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n"); + + handle = OpenEventLogA(NULL, "Application"); + + SetLastError(0xdeadbeef); + ret = BackupEventLogA(handle, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + ret = BackupEventLogA(handle, backup); + ok(ret, "Expected success\n"); + todo_wine + ok(GetFileAttributesA(backup) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n"); + + /* Try to overwrite */ + SetLastError(0xdeadbeef); + ret = BackupEventLogA(handle, backup); + todo_wine + { + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_ALREADY_EXISTS, "Expected ERROR_ALREADY_EXISTS, got %d\n", GetLastError()); + } + + CloseEventLog(handle); + + /* Can we make a backup of a backup? */ + handle = OpenBackupEventLogA(NULL, backup); + todo_wine + ok(handle != NULL, "Expected a handle\n"); + + ret = BackupEventLogA(handle, backup2); + todo_wine + { + ok(ret, "Expected success\n"); + ok(GetFileAttributesA(backup2) != INVALID_FILE_ATTRIBUTES, "Expected a backup file\n"); + } + + CloseEventLog(handle); + DeleteFileA(backup); + DeleteFileA(backup2); +} + +static void test_read(void) +{ + HANDLE handle; + BOOL ret; + DWORD count, toread, read, needed; + void *buf; + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, NULL); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + read = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, NULL); + ok(!ret, "Expected failure\n"); + ok(read == 0xdeadbeef, "Expected 'read' parameter to remain unchanged\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + needed = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, 0, 0, NULL, 0, NULL, &needed); + ok(!ret, "Expected failure\n"); + ok(needed == 0xdeadbeef, "Expected 'needed' parameter to remain unchanged\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + /* 'read' and 'needed' are only filled when the needed buffer size is passed back or when the call succeeds */ + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, 0, 0, NULL, 0, &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, NULL, NULL); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, NULL, 0, &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + buf = NULL; + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); + SetLastError(0xdeadbeef); + ret = ReadEventLogA(NULL, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + HeapFree(GetProcessHeap(), 0, buf); + + handle = OpenEventLogA(NULL, "Application"); + + /* Show that we need the proper dwFlags with a (for the rest) proper call */ + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, 0, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ, 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ | EVENTLOG_BACKWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEEK_READ | EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + todo_wine + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + HeapFree(GetProcessHeap(), 0, buf); + + /* First check if there are any records (in practice only on Wine: FIXME) */ + count = 0; + GetNumberOfEventLogRecords(handle, &count); + if (!count) + { + skip("No records in the 'Application' log\n"); + CloseEventLog(handle); + return; + } + + /* Get the buffer size for the first record */ + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); + read = needed = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + ok(!ret, "Expected failure\n"); + ok(read == 0, "Expected no bytes read\n"); + ok(needed > sizeof(EVENTLOGRECORD), "Expected the needed buffersize to be bigger than sizeof(EVENTLOGRECORD)\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + /* Read the first record */ + toread = needed; + buf = HeapReAlloc(GetProcessHeap(), 0, buf, toread); + read = needed = 0xdeadbeef; + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, 0, buf, toread, &read, &needed); + ok(ret, "Expected success\n"); + ok(read == toread || + broken(read < toread), /* NT4 wants a buffer size way bigger than just 1 record */ + "Expected the requested size to be read\n"); + ok(needed == 0, "Expected no extra bytes to be read\n"); + HeapFree(GetProcessHeap(), 0, buf); + + CloseEventLog(handle); +} + +static void test_openbackup(void) +{ + HANDLE handle, handle2, file; + DWORD written; + const char backup[] = "backup.evt"; + const char text[] = "Just some text"; + + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA(NULL, NULL); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA(NULL, "idontexist.evt"); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA("IDontExist", NULL); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA("IDontExist", "idontexist.evt"); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || + GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */ + "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError()); + + /* Make a backup eventlog to work with */ + create_backup(backup); + + /* FIXME: Wine stops here */ + if (GetFileAttributesA(backup) == INVALID_FILE_ATTRIBUTES) + { + skip("We don't have a backup eventlog to work with\n"); + return; + } + + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA("IDontExist", backup); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == RPC_S_SERVER_UNAVAILABLE || + GetLastError() == RPC_S_INVALID_NET_ADDR, /* Some Vista and Win7 */ + "Expected RPC_S_SERVER_UNAVAILABLE, got %d\n", GetLastError()); + + /* Empty servername should be read as local server */ + handle = OpenBackupEventLogA("", backup); + ok(handle != NULL, "Expected a handle\n"); + CloseEventLog(handle); + + handle = OpenBackupEventLogA(NULL, backup); + ok(handle != NULL, "Expected a handle\n"); + + /* Can we open that same backup eventlog more than once? */ + handle2 = OpenBackupEventLogA(NULL, backup); + ok(handle2 != NULL, "Expected a handle\n"); + ok(handle2 != handle, "Didn't expect the same handle\n"); + CloseEventLog(handle2); + + CloseEventLog(handle); + DeleteFileA(backup); + + /* Is there any content checking done? */ + file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + CloseHandle(file); + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA(NULL, backup); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY || + GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, /* Vista and Win7 */ + "Expected ERROR_NOT_ENOUGH_MEMORY, got %d\n", GetLastError()); + CloseEventLog(handle); + DeleteFileA(backup); + + file = CreateFileA(backup, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); + WriteFile(file, text, sizeof(text), &written, NULL); + CloseHandle(file); + SetLastError(0xdeadbeef); + handle = OpenBackupEventLogA(NULL, backup); + ok(handle == NULL, "Didn't expect a handle\n"); + ok(GetLastError() == ERROR_EVENTLOG_FILE_CORRUPT, "Expected ERROR_EVENTLOG_FILE_CORRUPT, got %d\n", GetLastError()); + CloseEventLog(handle); + DeleteFileA(backup); +} + +static void test_clear(void) +{ + HANDLE handle; + BOOL ret; + const char backup[] = "backup.evt"; + const char backup2[] = "backup2.evt"; + + SetLastError(0xdeadbeef); + ret = ClearEventLogA(NULL, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + /* Make a backup eventlog to work with */ + create_backup(backup); + + SetLastError(0xdeadbeef); + ret = ClearEventLogA(NULL, backup); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + handle = OpenBackupEventLogA(NULL, backup); + todo_wine + ok(handle != NULL, "Expected a handle\n"); + + /* A real eventlog would fail with ERROR_ALREADY_EXISTS */ + SetLastError(0xdeadbeef); + ret = ClearEventLogA(handle, backup); + ok(!ret, "Expected failure\n"); + /* The eventlog service runs under an account that doesn't have the necessary + * permissions on the users home directory on a default Vista+ system. + */ + ok(GetLastError() == ERROR_INVALID_HANDLE || + GetLastError() == ERROR_ACCESS_DENIED, /* Vista+ */ + "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + /* Show that ClearEventLog only works for real eventlogs. */ + SetLastError(0xdeadbeef); + ret = ClearEventLogA(handle, backup2); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + ok(GetFileAttributesA(backup2) == INVALID_FILE_ATTRIBUTES, "Expected no backup file\n"); + + SetLastError(0xdeadbeef); + ret = ClearEventLogA(handle, NULL); + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError()); + + CloseEventLog(handle); + todo_wine + ok(DeleteFileA(backup), "Could not delete the backup file\n"); +} + +static const char eventlogsvc[] = "SYSTEM\\CurrentControlSet\\Services\\Eventlog"; +static const char eventlogname[] = "Wine"; +static const char eventsources[][11] = { "WineSrc", "WineSrc1", "WineSrc20", "WineSrc300" }; + +static BOOL create_new_eventlog(void) +{ + HKEY key, eventkey; + BOOL bret = FALSE; + LONG lret; + int i; + + /* First create our eventlog */ + lret = RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key); + /* FIXME: Wine stops here */ + if (lret != ERROR_SUCCESS) + { + skip("Could not open the EventLog service registry key\n"); + return FALSE; + } + lret = RegCreateKeyA(key, eventlogname, &eventkey); + if (lret != ERROR_SUCCESS) + { + skip("Could not create the eventlog '%s' registry key\n", eventlogname); + goto cleanup; + } + + /* Create some event sources, the registry value 'Sources' is updated automatically */ + for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++) + { + HKEY srckey; + + lret = RegCreateKeyA(eventkey, eventsources[i], &srckey); + if (lret != ERROR_SUCCESS) + { + skip("Could not create the eventsource '%s' registry key\n", eventsources[i]); + goto cleanup; + } + RegFlushKey(srckey); + RegCloseKey(srckey); + } + + bret = TRUE; + + /* The flushing of the registry (here and above) gives us some assurance + * that we are not to quickly writing events as 'Sources' could still be + * not updated. + */ + RegFlushKey(eventkey); +cleanup: + RegCloseKey(eventkey); + RegCloseKey(key); + + return bret; +} + +static const char *one_string[] = { "First string" }; +static const char *two_strings[] = { "First string", "Second string" }; +static const struct +{ + const char *evt_src; + WORD evt_type; + WORD evt_cat; + DWORD evt_id; + BOOL evt_sid; + WORD evt_numstrings; + const char **evt_strings; +} read_write [] = +{ + { eventlogname, EVENTLOG_INFORMATION_TYPE, 1, 1, FALSE, 1, one_string }, + { eventsources[0], EVENTLOG_WARNING_TYPE, 1, 2, FALSE, 0, NULL }, + { eventsources[1], EVENTLOG_AUDIT_FAILURE, 1, 3, FALSE, 2, two_strings }, + { eventsources[2], EVENTLOG_ERROR_TYPE, 1, 4, FALSE, 0, NULL }, + { eventsources[3], EVENTLOG_WARNING_TYPE, 1, 5, FALSE, 1, one_string }, + { eventlogname, EVENTLOG_SUCCESS, 2, 6, TRUE, 2, two_strings }, + { eventsources[0], EVENTLOG_AUDIT_FAILURE, 2, 7, TRUE, 0, NULL }, + { eventsources[1], EVENTLOG_AUDIT_SUCCESS, 2, 8, TRUE, 2, two_strings }, + { eventsources[2], EVENTLOG_WARNING_TYPE, 2, 9, TRUE, 0, NULL }, + { eventsources[3], EVENTLOG_ERROR_TYPE, 2, 10, TRUE, 1, one_string } +}; + +static void test_readwrite(void) +{ + HANDLE handle; + PSID user; + DWORD sidsize, count; + BOOL ret, sidavailable; + BOOL on_vista = FALSE; /* Used to indicate Vista, W2K8 or Win7 */ + int i; + char *localcomputer = NULL; + DWORD size; + + if (pCreateWellKnownSid) + { + sidsize = SECURITY_MAX_SID_SIZE; + user = HeapAlloc(GetProcessHeap(), 0, sidsize); + SetLastError(0xdeadbeef); + pCreateWellKnownSid(WinInteractiveSid, NULL, user, &sidsize); + sidavailable = TRUE; + } + else + { + win_skip("Skipping some SID related tests\n"); + sidavailable = FALSE; + user = NULL; + } + + /* Write an event with an incorrect event type. This will fail on Windows 7 + * but succeed on all others, hence it's not part of the struct. + */ + handle = OpenEventLogA(NULL, eventlogname); + if (!handle) + { + /* Intermittently seen on NT4 when tests are run immediately after boot */ + win_skip("Could not get a handle to the eventlog\n"); + goto cleanup; + } + + count = 0xdeadbeef; + GetNumberOfEventLogRecords(handle, &count); + if (count != 0) + { + /* Needed for W2K3 without a service pack */ + win_skip("We most likely opened the Application eventlog\n"); + CloseEventLog(handle); + Sleep(2000); + + handle = OpenEventLogA(NULL, eventlogname); + count = 0xdeadbeef; + GetNumberOfEventLogRecords(handle, &count); + if (count != 0) + { + win_skip("We didn't open our new eventlog\n"); + CloseEventLog(handle); + goto cleanup; + } + } + + SetLastError(0xdeadbeef); + ret = ReportEvent(handle, 0x20, 0, 0, NULL, 0, 0, NULL, NULL); + if (!ret && GetLastError() == ERROR_CRC) + { + win_skip("Win7 fails when using incorrect event types\n"); + ret = ReportEvent(handle, 0, 0, 0, NULL, 0, 0, NULL, NULL); + } + else + { + void *buf; + DWORD read, needed; + EVENTLOGRECORD *record; + + /* Needed to catch earlier Vista (with no ServicePack for example) */ + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); + ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + + buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed); + ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, needed, &read, &needed); + + record = (EVENTLOGRECORD *)buf; + + /* Vista and W2K8 return EVENTLOG_SUCCESS, Windows versions before return + * the written eventtype (0x20 in this case). + */ + if (record->EventType == EVENTLOG_SUCCESS) + on_vista = TRUE; + + HeapFree(GetProcessHeap(), 0, buf); + } + ok(ret, "Expected success : %d\n", GetLastError()); + + /* This will clear the eventlog. The record numbering for new + * events however differs on Vista SP1+. Before Vista the first + * event would be numbered 1, on Vista SP1+ it's higher as we already + * had at least one event (more in case of multiple test runs without + * a reboot). + */ + ClearEventLogA(handle, NULL); + CloseEventLog(handle); + + /* Write a bunch of events while using different event sources */ + for (i = 0; i < sizeof(read_write)/sizeof(read_write[0]); i++) + { + DWORD oldest; + BOOL run_sidtests = read_write[i].evt_sid & sidavailable; + + /* We don't need to use RegisterEventSource to report events */ + if (i % 2) + handle = OpenEventLogA(NULL, read_write[i].evt_src); + else + handle = RegisterEventSourceA(NULL, read_write[i].evt_src); + ok(handle != NULL, "Expected a handle\n"); + + SetLastError(0xdeadbeef); + ret = ReportEvent(handle, read_write[i].evt_type, read_write[i].evt_cat, + read_write[i].evt_id, run_sidtests ? user : NULL, + read_write[i].evt_numstrings, 0, read_write[i].evt_strings, NULL); + + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(handle, &count); + ok(ret, "Expected success\n"); + ok(count == (i + 1), "Expected %d records, got %d\n", i + 1, count); + + oldest = 0xdeadbeef; + ret = GetOldestEventLogRecord(handle, &oldest); + ok(ret, "Expected success\n"); + ok(oldest == 1 || + (oldest > 1 && oldest != 0xdeadbeef), /* Vista SP1+, W2K8 and Win7 */ + "Expected oldest to be 1 or higher, got %d\n", oldest); + if (oldest > 1 && oldest != 0xdeadbeef) + on_vista = TRUE; + + if (i % 2) + ret = CloseEventLog(handle); + else + ret = DeregisterEventSource(handle); + ok(ret, "Expected success : %d\n", GetLastError()); + } + + handle = OpenEventLogA(NULL, eventlogname); + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(handle, &count); + ok(ret, "Expected success\n"); + ok(count == i, "Expected %d records, got %d\n", i, count); + CloseEventLog(handle); + + if (count == 0) + { + skip("No events were written to the eventlog\n"); + goto cleanup; + } + + /* Report only once */ + if (on_vista) + skip("There is no DWORD alignment enforced for UserSid on Vista, W2K8 or Win7\n"); + + if (on_vista && pGetComputerNameExA) + { + /* New Vista+ behavior */ + size = 0; + SetLastError(0xdeadbeef); + pGetComputerNameExA(ComputerNameDnsFullyQualified, NULL, &size); + localcomputer = HeapAlloc(GetProcessHeap(), 0, size); + pGetComputerNameExA(ComputerNameDnsFullyQualified, localcomputer, &size); + } + else + { + size = MAX_COMPUTERNAME_LENGTH + 1; + localcomputer = HeapAlloc(GetProcessHeap(), 0, size); + GetComputerNameA(localcomputer, &size); + } + + /* Read all events from our created eventlog, one by one */ + handle = OpenEventLogA(NULL, eventlogname); + i = 0; + for (;;) + { + void *buf; + DWORD read, needed; + EVENTLOGRECORD *record; + char *sourcename, *computername; + int k; + char *ptr; + BOOL run_sidtests = read_write[i].evt_sid & sidavailable; + + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(EVENTLOGRECORD)); + SetLastError(0xdeadbeef); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, sizeof(EVENTLOGRECORD), &read, &needed); + if (!ret && GetLastError() == ERROR_HANDLE_EOF) + { + HeapFree(GetProcessHeap(), 0, buf); + break; + } + ok(!ret, "Expected failure\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "Expected ERROR_INVALID_PARAMETER, got %d\n",GetLastError()); + + buf = HeapReAlloc(GetProcessHeap(), 0, buf, needed); + ret = ReadEventLogA(handle, EVENTLOG_SEQUENTIAL_READ | EVENTLOG_FORWARDS_READ, + 0, buf, needed, &read, &needed); + ok(ret, "Expected success: %d\n", GetLastError()); + + record = (EVENTLOGRECORD *)buf; + + ok(record->Length == read, + "Expected %d, got %d\n", read, record->Length); + ok(record->Reserved == 0x654c664c, + "Expected 0x654c664c, got %d\n", record->Reserved); + ok(record->RecordNumber == i + 1 || + (on_vista && (record->RecordNumber > i + 1)), + "Expected %d or higher, got %d\n", i + 1, record->RecordNumber); + ok(record->EventID == read_write[i].evt_id, + "Expected %d, got %d\n", read_write[i].evt_id, record->EventID); + ok(record->EventType == read_write[i].evt_type, + "Expected %d, got %d\n", read_write[i].evt_type, record->EventType); + ok(record->NumStrings == read_write[i].evt_numstrings, + "Expected %d, got %d\n", read_write[i].evt_numstrings, record->NumStrings); + ok(record->EventCategory == read_write[i].evt_cat, + "Expected %d, got %d\n", read_write[i].evt_cat, record->EventCategory); + + sourcename = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD)); + ok(!lstrcmpA(sourcename, read_write[i].evt_src), "Expected '%s', got '%s'\n", + read_write[i].evt_src, sourcename); + + computername = (char *)((BYTE *)buf + sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1); + ok(!lstrcmpiA(computername, localcomputer), "Expected '%s', got '%s'\n", + localcomputer, computername); + + /* Before Vista, UserSid was aligned on a DWORD boundary. Next to that if + * no padding was actually required a 0 DWORD was still used for padding. No + * application should be relying on the padding as we are working with offsets + * anyway. + */ + + if (!on_vista) + { + DWORD calculated_sidoffset = sizeof(EVENTLOGRECORD) + lstrlenA(sourcename) + 1 + lstrlenA(computername) + 1; + + /* We are already DWORD aligned, there should still be some padding */ + if ((((UINT_PTR)buf + calculated_sidoffset) % sizeof(DWORD)) == 0) + ok(*(DWORD *)((BYTE *)buf + calculated_sidoffset) == 0, "Expected 0\n"); + + ok((((UINT_PTR)buf + record->UserSidOffset) % sizeof(DWORD)) == 0, "Expected DWORD alignment\n"); + } + + if (run_sidtests) + { + ok(record->UserSidLength == sidsize, "Expected %d, got %d\n", sidsize, record->UserSidLength); + } + else + { + ok(record->StringOffset == record->UserSidOffset, "Expected offsets to be the same\n"); + ok(record->UserSidLength == 0, "Expected 0, got %d\n", record->UserSidLength); + } + + ok(record->DataLength == 0, "Expected 0, got %d\n", record->DataLength); + + ptr = (char *)((BYTE *)buf + record->StringOffset); + for (k = 0; k < record->NumStrings; k++) + { + ok(!lstrcmpA(ptr, two_strings[k]), "Expected '%s', got '%s'\n", two_strings[k], ptr); + ptr += lstrlenA(ptr) + 1; + } + + ok(record->Length == *(DWORD *)((BYTE *)buf + record->Length - sizeof(DWORD)), + "Expected the closing DWORD to contain the length of the record\n"); + + HeapFree(GetProcessHeap(), 0, buf); + i++; + } + CloseEventLog(handle); + + /* Test clearing a real eventlog */ + handle = OpenEventLogA(NULL, eventlogname); + + SetLastError(0xdeadbeef); + ret = ClearEventLogA(handle, NULL); + ok(ret, "Expected success\n"); + + count = 0xdeadbeef; + ret = GetNumberOfEventLogRecords(handle, &count); + ok(ret, "Expected success\n"); + ok(count == 0, "Expected an empty eventlog, got %d records\n", count); + + CloseEventLog(handle); + +cleanup: + HeapFree(GetProcessHeap(), 0, localcomputer); + HeapFree(GetProcessHeap(), 0, user); +} + +/* Before Vista: + * + * Creating an eventlog on Windows (via the registry) automatically leads + * to creation of a REG_MULTI_SZ named 'Sources'. This value lists all the + * potential event sources for this eventlog. 'Sources' is automatically + * updated when a new key (aka event source) is created. + * + * Although the updating of registry keys is almost instantaneously, we + * check it after some other tests to assure we are not querying the + * registry or file system to quickly. + * + * NT4 and higher: + * + * The eventlog file itself is also automatically created, even before we + * start writing events. + */ +static char eventlogfile[MAX_PATH]; +static void test_autocreation(void) +{ + HKEY key, eventkey; + DWORD type, size; + LONG ret; + int i; + char *p; + char sources[sizeof(eventsources)]; + char sysdir[MAX_PATH]; + void *redir = 0; + + RegOpenKeyA(HKEY_LOCAL_MACHINE, eventlogsvc, &key); + RegOpenKeyA(key, eventlogname, &eventkey); + + size = sizeof(sources); + sources[0] = 0; + ret = RegQueryValueExA(eventkey, "Sources", NULL, &type, (LPBYTE)sources, &size); + if (ret == ERROR_SUCCESS) + { + char sources_verify[sizeof(eventsources)]; + + ok(type == REG_MULTI_SZ, "Expected a REG_MULTI_SZ, got %d\n", type); + + /* Build the expected string */ + memset(sources_verify, 0, sizeof(sources_verify)); + p = sources_verify; + for (i = sizeof(eventsources)/sizeof(eventsources[0]); i > 0; i--) + { + lstrcpyA(p, eventsources[i - 1]); + p += (lstrlenA(eventsources[i - 1]) + 1); + } + lstrcpyA(p, eventlogname); + + ok(!memcmp(sources, sources_verify, size), + "Expected a correct 'Sources' value (size : %d)\n", size); + } + + RegCloseKey(eventkey); + RegCloseKey(key); + + /* The directory that holds the eventlog files could be redirected */ + if (pWow64DisableWow64FsRedirection) + pWow64DisableWow64FsRedirection(&redir); + + /* On Windows we also automatically get an eventlog file */ + GetSystemDirectoryA(sysdir, sizeof(sysdir)); + + /* NT4 - W2K3 */ + lstrcpyA(eventlogfile, sysdir); + lstrcatA(eventlogfile, "\\config\\"); + lstrcatA(eventlogfile, eventlogname); + lstrcatA(eventlogfile, ".evt"); + + if (GetFileAttributesA(eventlogfile) == INVALID_FILE_ATTRIBUTES) + { + /* Vista+ */ + lstrcpyA(eventlogfile, sysdir); + lstrcatA(eventlogfile, "\\winevt\\Logs\\"); + lstrcatA(eventlogfile, eventlogname); + lstrcatA(eventlogfile, ".evtx"); + } + + ok(GetFileAttributesA(eventlogfile) != INVALID_FILE_ATTRIBUTES, + "Expected an eventlog file\n"); + + if (pWow64RevertWow64FsRedirection) + pWow64RevertWow64FsRedirection(redir); +} + +static void cleanup_eventlog(void) +{ + BOOL bret; + LONG lret; + HKEY key; + int i; + char winesvc[MAX_PATH]; + + /* Delete the registry tree */ + lstrcpyA(winesvc, eventlogsvc); + lstrcatA(winesvc, "\\"); + lstrcatA(winesvc, eventlogname); + + RegOpenKeyA(HKEY_LOCAL_MACHINE, winesvc, &key); + for (i = 0; i < sizeof(eventsources)/sizeof(eventsources[0]); i++) + RegDeleteKeyA(key, eventsources[i]); + RegDeleteValueA(key, "Sources"); + RegCloseKey(key); + lret = RegDeleteKeyA(HKEY_LOCAL_MACHINE, winesvc); + todo_wine + ok(lret == ERROR_SUCCESS, "Could not delete the registry tree : %d\n", lret); + + /* A handle to the eventlog is locked by services.exe. We can only + * delete the eventlog file after reboot. + */ + bret = MoveFileExA(eventlogfile, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); + todo_wine + ok(bret, "Expected MoveFileEx to succeed: %d\n", GetLastError()); +} + +START_TEST(eventlog) +{ + SetLastError(0xdeadbeef); + CloseEventLog(NULL); + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("Event log functions are not implemented\n"); + return; + } + + init_function_pointers(); + + /* Parameters only */ + test_open_close(); + test_info(); + test_count(); + test_oldest(); + test_backup(); + test_openbackup(); + test_read(); + test_clear(); + + /* Functional tests */ + if (create_new_eventlog()) + { + test_readwrite(); + test_autocreation(); + } + cleanup_eventlog(); +} Propchange: trunk/rostests/winetests/advapi32/eventlog.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: trunk/rostests/winetests/advapi32/registry.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/regist…
============================================================================== --- trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/registry.c [iso-8859-1] Wed Dec 23 16:15:54 2009 @@ -956,6 +956,28 @@ /* clean up */ RegDeleteKey(hkey2, ""); RegDeleteKey(hkey1, ""); + RegCloseKey(hkey2); + RegCloseKey(hkey1); + + /* test creation of volatile keys */ + ret = RegCreateKeyExA(hkey_main, "Volatile", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey1, NULL); + ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); + ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL); + ok(ret == ERROR_CHILD_MUST_BE_VOLATILE || broken(!ret), /* win9x */ + "RegCreateKeyExA failed with error %d\n", ret); + if (!ret) RegCloseKey( hkey2 ); + ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey2, NULL); + ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); + RegCloseKey(hkey2); + /* should succeed if the key already exists */ + ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL); + ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); + + /* clean up */ + RegDeleteKey(hkey2, ""); + RegDeleteKey(hkey1, ""); + RegCloseKey(hkey2); + RegCloseKey(hkey1); /* beginning backslash character */ ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); @@ -964,6 +986,7 @@ else { ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); RegDeleteKey(hkey1, NULL); + RegCloseKey(hkey1); } /* WOW64 flags - open an existing key */ Modified: trunk/rostests/winetests/advapi32/security.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/securi…
============================================================================== --- trunk/rostests/winetests/advapi32/security.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/security.c [iso-8859-1] Wed Dec 23 16:15:54 2009 @@ -79,6 +79,7 @@ typedef BOOL (WINAPI *fnMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD ); typedef BOOL (WINAPI *fnConvertSidToStringSidA)( PSID pSid, LPSTR *str ); typedef BOOL (WINAPI *fnConvertStringSidToSidA)( LPCSTR str, PSID pSid ); +static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD, PSECURITY_DESCRIPTOR*, PULONG ); static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorW)(LPCWSTR, DWORD, @@ -153,6 +154,7 @@ pAddAccessAllowedAceEx = (void *)GetProcAddress(hmod, "AddAccessAllowedAceEx"); pAddAccessDeniedAceEx = (void *)GetProcAddress(hmod, "AddAccessDeniedAceEx"); pAddAuditAccessAceEx = (void *)GetProcAddress(hmod, "AddAuditAccessAceEx"); + pCheckTokenMembership = (void *)GetProcAddress(hmod, "CheckTokenMembership"); pConvertStringSecurityDescriptorToSecurityDescriptorA = (void *)GetProcAddress(hmod, "ConvertStringSecurityDescriptorToSecurityDescriptorA" ); pConvertStringSecurityDescriptorToSecurityDescriptorW = @@ -254,6 +256,7 @@ ok(pisid->SubAuthority[0] == 21, "Invalid subauthority 0 - expceted 21, got %d\n", pisid->SubAuthority[0]); ok(pisid->SubAuthority[3] == 4576, "Invalid subauthority 0 - expceted 4576, got %d\n", pisid->SubAuthority[3]); LocalFree(str); + LocalFree(psid); for( i = 0; i < sizeof(refs) / sizeof(refs[0]); i++ ) { @@ -1226,10 +1229,18 @@ ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); /* groups */ + SetLastError(0xdeadbeef); ret = GetTokenInformation(Token, TokenGroups, NULL, 0, &Size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "GetTokenInformation(TokenGroups) %s with error %d\n", + ret ? "succeeded" : "failed", GetLastError()); Groups = HeapAlloc(GetProcessHeap(), 0, Size); + SetLastError(0xdeadbeef); ret = GetTokenInformation(Token, TokenGroups, Groups, Size, &Size); ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError()); + ok(GetLastError() == 0xdeadbeef, + "GetTokenInformation shouldn't have set last error to %d\n", + GetLastError()); trace("TokenGroups:\n"); for (i = 0; i < Groups->GroupCount; i++) { @@ -1238,12 +1249,12 @@ DWORD DomainLength = 255; TCHAR Domain[255]; SID_NAME_USE SidNameUse; - pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString); Name[0] = '\0'; Domain[0] = '\0'; ret = LookupAccountSid(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse); if (ret) { + pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString); trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes); LocalFree(SidString); } @@ -1478,6 +1489,8 @@ ok(memcmp(buf2, sid_buffer, cb) == 0, "SID create with domain is different than without (%d)\n", i); } } + + LocalFree(domainsid); } static void test_LookupAccountSid(void) @@ -2047,7 +2060,8 @@ domain = HeapAlloc(GetProcessHeap(), 0, domain_size); ret = LookupAccountNameA(NULL, computer_name, psid, &sid_size, domain, &domain_size, &sid_use); ok(ret, "LookupAccountNameA failed: %d\n", GetLastError()); - ok(sid_use == SidTypeDomain, "expected SidTypeDomain, got %d\n", sid_use); + ok(sid_use == SidTypeDomain || + (sid_use == SidTypeUser && ! strcmp(computer_name, user_name)), "expected SidTypeDomain for %s, got %d\n", computer_name, sid_use); HeapFree(GetProcessHeap(), 0, domain); HeapFree(GetProcessHeap(), 0, psid); } @@ -2528,11 +2542,19 @@ ExplicitAccess.grfAccessPermissions = KEY_WRITE; ExplicitAccess.grfAccessMode = GRANT_ACCESS; ExplicitAccess.grfInheritance = NO_INHERITANCE; + ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ExplicitAccess.Trustee.ptstrName = EveryoneSid; + ExplicitAccess.Trustee.MultipleTrusteeOperation = 0xDEADBEEF; + ExplicitAccess.Trustee.pMultipleTrustee = (PVOID)0xDEADBEEF; + res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); + ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); + ok(NewAcl != NULL, "returned acl was NULL\n"); + LocalFree(NewAcl); + + ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; ExplicitAccess.Trustee.pMultipleTrustee = NULL; ExplicitAccess.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; - ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ExplicitAccess.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; - ExplicitAccess.Trustee.ptstrName = EveryoneSid; res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl); ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res); ok(NewAcl != NULL, "returned acl was NULL\n"); @@ -2651,6 +2673,50 @@ BOOL ret; PSECURITY_DESCRIPTOR pSD; static const WCHAR Blank[] = { 0 }; + int i; + static const struct + { + const char *sidstring; + DWORD revision; + BOOL ret; + DWORD GLE; + DWORD altGLE; + } cssd[] = + { + { "D:(A;;GA;;;WD)", 0xdeadbeef, FALSE, ERROR_UNKNOWN_REVISION }, + /* test ACE string type */ + { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_PARAMETER }, + /* test ACE string with spaces */ + { " D:(D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D: (D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:( D;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D ;;GA;;;WD)", SDDL_REVISION_1, FALSE, RPC_S_INVALID_STRING_UUID, ERROR_INVALID_ACL }, /* Vista+ */ + { "D:(D; ;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;; GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA ;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL }, + { "D:(D;;GA; ;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA;; ;WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA;;; WD)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA;;;WD )", SDDL_REVISION_1, TRUE }, + /* test ACE string access rights */ + { "D:(A;;GA;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, TRUE }, + { "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE }, + { "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, TRUE }, + /* test ACE string access right error case */ + { "D:(A;;ROB;;;WD)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL }, + /* test behaviour with empty strings */ + { "", SDDL_REVISION_1, TRUE }, + /* test ACE string SID */ + { "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, TRUE }, + { "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, FALSE, ERROR_INVALID_ACL, ERROR_INVALID_SID } /* W2K */ + }; if (!pConvertStringSecurityDescriptorToSecurityDescriptorA) { @@ -2658,82 +2724,22 @@ return; } - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;GA;;;WD)", 0xdeadbeef, &pSD, NULL); - ok(!ret && GetLastError() == ERROR_UNKNOWN_REVISION, - "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_UNKNOWN_REVISION instead of %d\n", - GetLastError()); - - /* test ACE string type */ - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "ERROR:(D;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, - "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_PARAMETER instead of %d\n", - GetLastError()); - - /* test ACE string access rights */ - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;GA;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;GRGWGX;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;RCSDWDWO;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;RPWPCCDCLCSWLODTCR;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;FAFRFWFX;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;KAKRKWKX;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "S:(AU;;0xFFFFFFFF;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - LocalFree(pSD); - - /* test ACE string access right error case */ - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(A;;ROB;;;WD)", SDDL_REVISION_1, &pSD, NULL); - ok(!ret && GetLastError() == ERROR_INVALID_ACL, - "ConvertStringSecurityDescriptorToSecurityDescriptor should have failed with ERROR_INVALID_ACL instead of %d\n", - GetLastError()); + for (i = 0; i < sizeof(cssd)/sizeof(cssd[0]); i++) + { + DWORD GLE; + + SetLastError(0xdeadbeef); + ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( + cssd[i].sidstring, cssd[i].revision, &pSD, NULL); + GLE = GetLastError(); + ok(ret == cssd[i].ret, "(%02d) Expected %s (%d)\n", i, cssd[i].ret ? "success" : "failure", GLE); + if (!cssd[i].ret) + ok(GLE == cssd[i].GLE || + (cssd[i].altGLE && GLE == cssd[i].altGLE), + "(%02d) Unexpected last error %d\n", i, GLE); + if (ret) + LocalFree(pSD); + } /* test behaviour with NULL parameters */ SetLastError(0xdeadbeef); @@ -2767,28 +2773,10 @@ /* test behaviour with empty strings */ SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - - SetLastError(0xdeadbeef); ret = pConvertStringSecurityDescriptorToSecurityDescriptorW( Blank, SDDL_REVISION_1, &pSD, NULL); ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); - - /* test ACE string SID */ - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(D;;GA;;;S-1-0-0)", SDDL_REVISION_1, &pSD, NULL); - ok(ret, "ConvertStringSecurityDescriptorToSecurityDescriptor failed with error %d\n", GetLastError()); LocalFree(pSD); - - SetLastError(0xdeadbeef); - ret = pConvertStringSecurityDescriptorToSecurityDescriptorA( - "D:(D;;GA;;;Nonexistent account)", SDDL_REVISION_1, &pSD, NULL); - ok(!ret, "Expected failure, got %d\n", ret); - ok(GetLastError() == ERROR_INVALID_ACL || GetLastError() == ERROR_INVALID_SID, - "Expected ERROR_INVALID_ACL or ERROR_INVALID_SID, got %d\n", GetLastError()); } static void test_ConvertSecurityDescriptorToString(void) @@ -2900,6 +2888,9 @@ CHECK_ONE_OF_AND_FREE("O:SYG:S-1-5-21-93476-23408-4576D:S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)", /* XP */ "O:SYG:S-1-5-21-93476-23408-4576D:NO_ACCESS_CONTROLS:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)" /* Vista */); } + + LocalFree(psid2); + LocalFree(psid); } static void test_SetSecurityDescriptorControl (PSECURITY_DESCRIPTOR sec) @@ -3171,8 +3162,10 @@ ok(sd != NULL, "GetSecurityInfo\n"); ok(owner != NULL, "GetSecurityInfo\n"); ok(group != NULL, "GetSecurityInfo\n"); - ok(dacl != NULL, "GetSecurityInfo\n"); - ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + if (dacl != NULL) + ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + else + win_skip("No ACL information returned\n"); LocalFree(sd); @@ -3191,8 +3184,10 @@ ok(ret == ERROR_SUCCESS, "GetSecurityInfo returned %d\n", ret); ok(owner != NULL, "GetSecurityInfo\n"); ok(group != NULL, "GetSecurityInfo\n"); - ok(dacl != NULL, "GetSecurityInfo\n"); - ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + if (dacl != NULL) + ok(IsValidAcl(dacl), "GetSecurityInfo\n"); + else + win_skip("No ACL information returned\n"); CloseHandle(obj); } @@ -3220,9 +3215,138 @@ ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1)); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); SetLastError(0xbebecaca); - todo_wine ok(*pGetSidSubAuthority(psid,4) == 0,"GetSidSubAuthority gave %d,expected 0\n",*pGetSidSubAuthority(psid,4)); + ok(pGetSidSubAuthority(psid,4) != NULL,"Expected out of bounds GetSidSubAuthority to return a non-NULL pointer\n"); ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError()); LocalFree(psid); +} + +static void test_CheckTokenMembership(void) +{ + PTOKEN_GROUPS token_groups; + DWORD size; + HANDLE process_token, token; + BOOL is_member; + BOOL ret; + DWORD i; + + if (!pCheckTokenMembership) + { + win_skip("CheckTokenMembership is not available\n"); + return; + } + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token); + ok(ret, "OpenProcessToken failed with error %d\n", GetLastError()); + + ret = DuplicateToken(process_token, SecurityImpersonation, &token); + ok(ret, "DuplicateToken failed with error %d\n", GetLastError()); + + /* groups */ + ret = GetTokenInformation(token, TokenGroups, NULL, 0, &size); + ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "GetTokenInformation(TokenGroups) %s with error %d\n", + ret ? "succeeded" : "failed", GetLastError()); + token_groups = HeapAlloc(GetProcessHeap(), 0, size); + ret = GetTokenInformation(token, TokenGroups, token_groups, size, &size); + ok(ret, "GetTokenInformation(TokenGroups) failed with error %d\n", GetLastError()); + + for (i = 0; i < token_groups->GroupCount; i++) + { + if (token_groups->Groups[i].Attributes & SE_GROUP_ENABLED) + break; + } + + if (i == token_groups->GroupCount) + { + HeapFree(GetProcessHeap(), 0, token_groups); + CloseHandle(token); + skip("user not a member of any group\n"); + return; + } + + ret = pCheckTokenMembership(token, token_groups->Groups[i].Sid, &is_member); + ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError()); + ok(is_member, "CheckTokenMembership should have detected sid as member\n"); + + ret = pCheckTokenMembership(NULL, token_groups->Groups[i].Sid, &is_member); + ok(ret, "CheckTokenMembership failed with error %d\n", GetLastError()); + ok(is_member, "CheckTokenMembership should have detected sid as member\n"); + + ret = pCheckTokenMembership(process_token, token_groups->Groups[i].Sid, &is_member); +todo_wine { + ok(!ret && GetLastError() == ERROR_NO_IMPERSONATION_TOKEN, + "CheckTokenMembership with process token %s with error %d\n", + ret ? "succeeded" : "failed", GetLastError()); + ok(!is_member, "CheckTokenMembership should have cleared is_member\n"); +} + + HeapFree(GetProcessHeap(), 0, token_groups); + CloseHandle(token); + CloseHandle(process_token); +} + +static void test_EqualSid(void) +{ + PSID sid1, sid2; + BOOL ret; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY }; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY }; + + SetLastError(0xdeadbeef); + ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid1); + if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("AllocateAndInitializeSid is not implemented\n"); + return; + } + ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError()); + ok(GetLastError() == 0xdeadbeef, + "AllocateAndInitializeSid shouldn't have set last error to %d\n", + GetLastError()); + + ret = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, &sid2); + ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EqualSid(sid1, sid2); + ok(!ret, "World and domain admins sids shouldn't have been equal\n"); + ok(GetLastError() == ERROR_SUCCESS || + broken(GetLastError() == 0xdeadbeef), /* NT4 */ + "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", + GetLastError()); + + SetLastError(0xdeadbeef); + sid2 = FreeSid(sid2); + ok(!sid2, "FreeSid should have returned NULL instead of %p\n", sid2); + ok(GetLastError() == 0xdeadbeef, + "FreeSid shouldn't have set last error to %d\n", + GetLastError()); + + ret = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &sid2); + ok(ret, "AllocateAndInitializeSid failed with error %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = EqualSid(sid1, sid2); + ok(ret, "Same sids should have been equal\n"); + ok(GetLastError() == ERROR_SUCCESS || + broken(GetLastError() == 0xdeadbeef), /* NT4 */ + "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", + GetLastError()); + + ((SID *)sid2)->Revision = 2; + SetLastError(0xdeadbeef); + ret = EqualSid(sid1, sid2); + ok(!ret, "EqualSid with invalid sid should have returned FALSE\n"); + ok(GetLastError() == ERROR_SUCCESS || + broken(GetLastError() == 0xdeadbeef), /* NT4 */ + "EqualSid should have set last error to ERROR_SUCCESS instead of %d\n", + GetLastError()); + ((SID *)sid2)->Revision = SID_REVISION; + + FreeSid(sid1); + FreeSid(sid2); } START_TEST(security) @@ -3255,4 +3379,6 @@ test_acls(); test_GetSecurityInfo(); test_GetSidSubAuthority(); -} + test_CheckTokenMembership(); + test_EqualSid(); +} Modified: trunk/rostests/winetests/advapi32/service.c URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/advapi32/servic…
============================================================================== --- trunk/rostests/winetests/advapi32/service.c [iso-8859-1] (original) +++ trunk/rostests/winetests/advapi32/service.c [iso-8859-1] Wed Dec 23 16:15:54 2009 @@ -38,6 +38,9 @@ static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD, LPDWORD, LPCSTR); +static BOOL (WINAPI *pEnumServicesStatusExW)(SC_HANDLE, SC_ENUM_TYPE, DWORD, + DWORD, LPBYTE, DWORD, LPDWORD, + LPDWORD, LPDWORD, LPCWSTR); static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*); static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD); @@ -51,6 +54,7 @@ pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A"); pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA"); + pEnumServicesStatusExW= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExW"); pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo"); pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A"); pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W"); @@ -1030,6 +1034,7 @@ SC_HANDLE scm_handle; BOOL ret; DWORD bufsize, needed, returned, resume; + DWORD neededW, returnedW; DWORD tempneeded, tempreturned, missing; DWORD servicecountactive, servicecountinactive; ENUM_SERVICE_STATUS *services; @@ -1159,6 +1164,12 @@ ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); } + + /* Test to show we get the same needed buffer size for the W-call */ + neededW = 0xdeadbeef; + ret = EnumServicesStatusW(scm_handle, SERVICE_WIN32, SERVICE_STATE_ALL, NULL, 0, + &neededW, &returnedW, NULL); + ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); /* Store the needed bytes */ tempneeded = needed; @@ -1505,6 +1516,12 @@ ok(GetLastError() == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); } + + /* Test to show we get the same needed buffer size for the W-call */ + neededW = 0xdeadbeef; + ret = pEnumServicesStatusExW(scm_handle, 0, SERVICE_WIN32, SERVICE_STATE_ALL, + NULL, 0, &neededW, &returnedW, NULL, NULL); + ok(neededW == needed, "Expected needed buffersize to be the same for A- and W-calls\n"); /* Store the needed bytes */ tempneeded = needed;
15 years
1
0
0
0
[cwittich] 44735: [psdk] add EVENTLOG_FULL_INFORMATION structure (from wine)
by cwittich@svn.reactos.org
Author: cwittich Date: Wed Dec 23 16:15:21 2009 New Revision: 44735 URL:
http://svn.reactos.org/svn/reactos?rev=44735&view=rev
Log: [psdk] add EVENTLOG_FULL_INFORMATION structure (from wine) Modified: trunk/reactos/include/psdk/winbase.h Modified: trunk/reactos/include/psdk/winbase.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/winbase.h?rev…
============================================================================== --- trunk/reactos/include/psdk/winbase.h [iso-8859-1] (original) +++ trunk/reactos/include/psdk/winbase.h [iso-8859-1] Wed Dec 23 16:15:21 2009 @@ -943,6 +943,14 @@ WCHAR szHwProfileName[MAX_PROFILE_LEN]; } HW_PROFILE_INFOW,*LPHW_PROFILE_INFOW; +/* Event Logging */ + +#define EVENTLOG_FULL_INFO 0 + +typedef struct _EVENTLOG_FULL_INFORMATION { + DWORD dwFull; +} EVENTLOG_FULL_INFORMATION, *LPEVENTLOG_FULL_INFORMATION; + typedef enum _GET_FILEEX_INFO_LEVELS { GetFileExInfoStandard, GetFileExMaxInfoLevel
15 years
1
0
0
0
[ekohl] 44734: Assign the services Dhcp, EventLog, PlugPlay and RpcSs to the LocalSystem account.
by ekohl@svn.reactos.org
Author: ekohl Date: Wed Dec 23 15:59:47 2009 New Revision: 44734 URL:
http://svn.reactos.org/svn/reactos?rev=44734&view=rev
Log: Assign the services Dhcp, EventLog, PlugPlay and RpcSs to the LocalSystem account. Modified: trunk/reactos/boot/bootdata/hivesys_i386.inf Modified: trunk/reactos/boot/bootdata/hivesys_i386.inf URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/hivesys_i386…
============================================================================== --- trunk/reactos/boot/bootdata/hivesys_i386.inf [iso-8859-1] (original) +++ trunk/reactos/boot/bootdata/hivesys_i386.inf [iso-8859-1] Wed Dec 23 15:59:47 2009 @@ -1038,6 +1038,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Group",0x00000000,"Network" HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ImagePath",0x00020000,"%SystemRoot%\system32\dhcp.exe" +HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","ObjectName",0x00000000,"LocalSystem" HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Start",0x00010001,0x00000002 HKLM,"SYSTEM\CurrentControlSet\Services\DHCP","Type",0x00010001,0x00000010 @@ -1048,6 +1049,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Group",0x00000000,"Event log" HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ImagePath",0x00020000,"%SystemRoot%\system32\eventlog.exe" +HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","ObjectName",0x00000000,"LocalSystem" HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Start",0x00010001,0x00000002 HKLM,"SYSTEM\CurrentControlSet\Services\EventLog","Type",0x00010001,0x00000010 @@ -1160,6 +1162,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ErrorControl",0x00010001,0x00000000 HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Group",0x00000000,"PlugPlay" HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ImagePath",0x00020000,"%SystemRoot%\system32\umpnpmgr.exe" +HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","ObjectName",0x00000000,"LocalSystem" HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Start",0x00010001,0x00000004 HKLM,"SYSTEM\CurrentControlSet\Services\PlugPlay","Type",0x00010001,0x00000010 @@ -1169,6 +1172,7 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ErrorControl",0x00010001,0x00000001 HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Group",0x00000000," RPC Service" HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ImagePath",0x00020000,"%SystemRoot%\system32\rpcss.exe" +HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","ObjectName",0x00000000,"LocalSystem" HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Start",0x00010001,0x00000002 HKLM,"SYSTEM\CurrentControlSet\Services\Rpcss","Type",0x00010001,0x00000010
15 years
1
0
0
0
[ekohl] 44733: - RChangeServiceConfigA/W: Update the service group properly and fix the ANSI to Unicode string conversion. This fixes one winetest.
by ekohl@svn.reactos.org
Author: ekohl Date: Wed Dec 23 15:32:15 2009 New Revision: 44733 URL:
http://svn.reactos.org/svn/reactos?rev=44733&view=rev
Log: - RChangeServiceConfigA/W: Update the service group properly and fix the ANSI to Unicode string conversion. This fixes one winetest. Modified: trunk/reactos/base/system/services/groupdb.c trunk/reactos/base/system/services/rpcserver.c Modified: trunk/reactos/base/system/services/groupdb.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/group…
============================================================================== --- trunk/reactos/base/system/services/groupdb.c [iso-8859-1] (original) +++ trunk/reactos/base/system/services/groupdb.c [iso-8859-1] Wed Dec 23 15:32:15 2009 @@ -29,6 +29,15 @@ { PLIST_ENTRY GroupEntry; PSERVICE_GROUP lpGroup; + + DPRINT("ScmSetServiceGroup(%S)\n", lpGroupName); + + if (lpService->lpGroup != NULL) + { + lpService->lpGroup->dwRefCount--; + + /* FIXME: What do we have to do when dwRefCount is 0? */ + } GroupEntry = GroupListHead.Flink; while (GroupEntry != &GroupListHead) Modified: trunk/reactos/base/system/services/rpcserver.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/services/rpcse…
============================================================================== --- trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] (original) +++ trunk/reactos/base/system/services/rpcserver.c [iso-8859-1] Wed Dec 23 15:32:15 2009 @@ -1282,7 +1282,11 @@ (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); if (dwError != ERROR_SUCCESS) goto done; - /* FIXME: Update lpService->lpServiceGroup */ + + dwError = ScmSetServiceGroup(lpService, + lpLoadOrderGroup); + if (dwError != ERROR_SUCCESS) + goto done; } if (lpdwTagId != NULL) @@ -3058,7 +3062,7 @@ if (lpBinaryPathName != NULL && *lpBinaryPathName != 0) { lpBinaryPathNameW=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName)+1) * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, wcslen(lpBinaryPathNameW)+1); + MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, strlen(lpBinaryPathName)+1); dwError = RegSetValueExW(hServiceKey, L"ImagePath", 0, @@ -3090,7 +3094,7 @@ { lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, - (strlen(lpLoadOrderGroup)+1) * sizeof(WCHAR)); + (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR)); if (lpLoadOrderGroupW == NULL) { dwError = ERROR_NOT_ENOUGH_MEMORY; @@ -3102,7 +3106,7 @@ lpLoadOrderGroup, -1, lpLoadOrderGroupW, - wcslen(lpLoadOrderGroupW) + 1); + strlen(lpLoadOrderGroup) + 1); dwError = RegSetValueExW(hServiceKey, L"Group", @@ -3111,11 +3115,18 @@ (LPBYTE)lpLoadOrderGroupW, (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR)); if (dwError != ERROR_SUCCESS) + { + HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); goto done; - - /* FIXME: Update lpService->lpServiceGroup */ + } + + dwError = ScmSetServiceGroup(lpService, + lpLoadOrderGroupW); HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW); + + if (dwError != ERROR_SUCCESS) + goto done; } if (lpdwTagId != NULL) @@ -3141,7 +3152,7 @@ { lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, - (strlen(lpDependencies)+1) * sizeof(WCHAR)); + (strlen(lpDependencies) + 1) * sizeof(WCHAR)); if (lpDependenciesW == NULL) { dwError = ERROR_NOT_ENOUGH_MEMORY; @@ -3153,7 +3164,7 @@ lpDependencies, dwDependSize, lpDependenciesW, - wcslen(lpDependenciesW)+1); + strlen(lpDependencies) + 1); dwError = ScmWriteDependencies(hServiceKey, (LPWSTR)lpDependenciesW, @@ -3469,8 +3480,7 @@ RtlCreateUnicodeStringFromAsciiz(&DatabaseName, lpDatabaseName); - dwError = ROpenSCManagerW(//BindingHandle, - lpMachineName ? MachineName.Buffer : NULL, + dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL, lpDatabaseName ? DatabaseName.Buffer : NULL, dwDesiredAccess, lpScHandle); @@ -3501,8 +3511,7 @@ RtlCreateUnicodeStringFromAsciiz(&ServiceName, lpServiceName); - dwError = ROpenServiceW(//BindingHandle, - hSCManager, + dwError = ROpenServiceW(hSCManager, lpServiceName ? ServiceName.Buffer : NULL, dwDesiredAccess, lpServiceHandle);
15 years
1
0
0
0
← Newer
1
...
8
9
10
11
12
13
14
...
51
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Results per page:
10
25
50
100
200