diff --git a/rostests/apitests/w32kdll/w32kdll_2k3sp2/w32k_2k3sp2-x86.db b/rostests/apitests/w32kdll/w32kdll_2k3sp2/w32k_2k3sp2-x86.db
new file mode 100644
index 00000000000..8808dec397f
--- /dev/null
+++ b/rostests/apitests/w32kdll/w32kdll_2k3sp2/w32k_2k3sp2-x86.db
@@ -0,0 +1,668 @@
+#
+# win32k systemcalls taken from Windows 2003 SP2 x86
+#
+NtGdiAbortDoc 1
+NtGdiAbortPath 1
+NtGdiAddFontResourceW 6
+NtGdiAddRemoteFontToDC 4
+NtGdiAddFontMemResourceEx 5
+NtGdiRemoveMergeFont 2
+NtGdiAddRemoteMMInstanceToDC 3
+NtGdiAlphaBlend 12
+NtGdiAngleArc 6
+NtGdiAnyLinkedFonts 0
+NtGdiFontIsLinked 1
+NtGdiArcInternal 10
+NtGdiBeginPath 1
+NtGdiBitBlt 11
+NtGdiCancelDC 1
+NtGdiCheckBitmapBits 8
+NtGdiCloseFigure 1
+NtGdiClearBitmapAttributes 2
+NtGdiClearBrushAttributes 2
+NtGdiColorCorrectPalette 6
+NtGdiCombineRgn 4
+NtGdiCombineTransform 3
+NtGdiComputeXformCoefficients 1
+NtGdiConsoleTextOut 4
+NtGdiConvertMetafileRect 2
+NtGdiCreateBitmap 5
+NtGdiCreateClientObj 1
+NtGdiCreateColorSpace 1
+NtGdiCreateColorTransform 8
+NtGdiCreateCompatibleBitmap 3
+NtGdiCreateCompatibleDC 1
+NtGdiCreateDIBBrush 6
+NtGdiCreateDIBitmapInternal 11
+NtGdiCreateDIBSection 9
+NtGdiCreateEllipticRgn 4
+NtGdiCreateHalftonePalette 1
+NtGdiCreateHatchBrushInternal 3
+NtGdiCreateMetafileDC 1
+NtGdiCreatePaletteInternal 2
+NtGdiCreatePatternBrushInternal 3
+NtGdiCreatePen 4
+NtGdiCreateRectRgn 4
+NtGdiCreateRoundRectRgn 6
+NtGdiCreateServerMetaFile 6
+NtGdiCreateSolidBrush 2
+NtGdiD3dContextCreate 4
+NtGdiD3dContextDestroy 1
+NtGdiD3dContextDestroyAll 1
+NtGdiD3dValidateTextureStageState 1
+NtGdiD3dDrawPrimitives2 7
+NtGdiDdGetDriverState 1
+NtGdiDdAddAttachedSurface 3
+NtGdiDdAlphaBlt 3
+NtGdiDdAttachSurface 2
+NtGdiDdBeginMoCompFrame 2
+NtGdiDdBlt 3
+NtGdiDdCanCreateSurface 2
+NtGdiDdCanCreateD3DBuffer 2
+NtGdiDdColorControl 2
+NtGdiDdCreateDirectDrawObject 1
+NtGdiDdCreateSurface 8
+NtGdiDdCreateD3DBuffer 8
+NtGdiDdCreateMoComp 2
+NtGdiDdCreateSurfaceObject 6
+NtGdiDdDeleteDirectDrawObject 1
+NtGdiDdDeleteSurfaceObject 1
+NtGdiDdDestroyMoComp 2
+NtGdiDdDestroySurface 2
+NtGdiDdDestroyD3DBuffer 1
+NtGdiDdEndMoCompFrame 2
+NtGdiDdFlip 5
+NtGdiDdFlipToGDISurface 2
+NtGdiDdGetAvailDriverMemory 2
+NtGdiDdGetBltStatus 2
+NtGdiDdGetDC 2
+NtGdiDdGetDriverInfo 2
+NtGdiDdGetDxHandle 3
+NtGdiDdGetFlipStatus 2
+NtGdiDdGetInternalMoCompInfo 2
+NtGdiDdGetMoCompBuffInfo 2
+NtGdiDdGetMoCompGuids 2
+NtGdiDdGetMoCompFormats 2
+NtGdiDdGetScanLine 2
+NtGdiDdLock 3
+NtGdiDdLockD3D 2
+NtGdiDdQueryDirectDrawObject 11
+NtGdiDdQueryMoCompStatus 2
+NtGdiDdReenableDirectDrawObject 2
+NtGdiDdReleaseDC 1
+NtGdiDdRenderMoComp 2
+NtGdiDdResetVisrgn 2
+NtGdiDdSetColorKey 2
+NtGdiDdSetExclusiveMode 2
+NtGdiDdSetGammaRamp 3
+NtGdiDdCreateSurfaceEx 3
+NtGdiDdSetOverlayPosition 3
+NtGdiDdUnattachSurface 2
+NtGdiDdUnlock 2
+NtGdiDdUnlockD3D 2
+NtGdiDdUpdateOverlay 3
+NtGdiDdWaitForVerticalBlank 2
+NtGdiDvpCanCreateVideoPort 2
+NtGdiDvpColorControl 2
+NtGdiDvpCreateVideoPort 2
+NtGdiDvpDestroyVideoPort 2
+NtGdiDvpFlipVideoPort 4
+NtGdiDvpGetVideoPortBandwidth 2
+NtGdiDvpGetVideoPortField 2
+NtGdiDvpGetVideoPortFlipStatus 2
+NtGdiDvpGetVideoPortInputFormats 2
+NtGdiDvpGetVideoPortLine 2
+NtGdiDvpGetVideoPortOutputFormats 2
+NtGdiDvpGetVideoPortConnectInfo 2
+NtGdiDvpGetVideoSignalStatus 2
+NtGdiDvpUpdateVideoPort 4
+NtGdiDvpWaitForVideoPortSync 2
+NtGdiDvpAcquireNotification 3
+NtGdiDvpReleaseNotification 2
+NtGdiDxgGenericThunk 6
+NtGdiDeleteClientObj 1
+NtGdiDeleteColorSpace 1
+NtGdiDeleteColorTransform 2
+NtGdiDeleteObjectApp 1
+NtGdiDescribePixelFormat 4
+NtGdiGetPerBandInfo 2
+NtGdiDoBanding 4
+NtGdiDoPalette 6
+NtGdiDrawEscape 4
+NtGdiEllipse 5
+NtGdiEnableEudc 1
+NtGdiEndDoc 1
+NtGdiEndPage 1
+NtGdiEndPath 1
+NtGdiEnumFontChunk 5
+NtGdiEnumFontClose 1
+NtGdiEnumFontOpen 7
+NtGdiEnumObjects 4
+NtGdiEqualRgn 2
+NtGdiEudcLoadUnloadLink 7
+NtGdiExcludeClipRect 5
+NtGdiExtCreatePen 11
+NtGdiExtCreateRegion 3
+NtGdiExtEscape 8
+NtGdiExtFloodFill 5
+NtGdiExtGetObjectW 3
+NtGdiExtSelectClipRgn 3
+NtGdiExtTextOutW 9
+NtGdiFillPath 1
+NtGdiFillRgn 3
+NtGdiFlattenPath 1
+NtGdiFlush 0
+NtGdiForceUFIMapping 2
+NtGdiFrameRgn 5
+NtGdiFullscreenControl 5
+NtGdiGetAndSetDCDword 4
+NtGdiGetAppClipBox 2
+NtGdiGetBitmapBits 3
+NtGdiGetBitmapDimension 2
+NtGdiGetBoundsRect 3
+NtGdiGetCharABCWidthsW 6
+NtGdiGetCharacterPlacementW 6
+NtGdiGetCharSet 1
+NtGdiGetCharWidthW 6
+NtGdiGetCharWidthInfo 2
+NtGdiGetColorAdjustment 2
+NtGdiGetColorSpaceforBitmap 1
+NtGdiGetDCDword 3
+NtGdiGetDCforBitmap 1
+NtGdiGetDCObject 2
+NtGdiGetDCPoint 3
+NtGdiGetDeviceCaps 2
+NtGdiGetDeviceGammaRamp 2
+NtGdiGetDeviceCapsAll 2
+NtGdiGetDIBitsInternal 9
+NtGdiGetETM 2
+NtGdiGetEudcTimeStampEx 3
+NtGdiGetFontData 5
+NtGdiGetFontResourceInfoInternalW 7
+NtGdiGetGlyphIndicesW 5
+NtGdiGetGlyphIndicesWInternal 6
+NtGdiGetGlyphOutline 8
+NtGdiGetKerningPairs 3
+NtGdiGetLinkedUFIs 3
+NtGdiGetMiterLimit 2
+NtGdiGetMonitorID 3
+NtGdiGetNearestColor 2
+NtGdiGetNearestPaletteIndex 2
+NtGdiGetObjectBitmapHandle 2
+NtGdiGetOutlineTextMetricsInternalW 4
+NtGdiGetPath 4
+NtGdiGetPixel 3
+NtGdiGetRandomRgn 3
+NtGdiGetRasterizerCaps 2
+NtGdiGetRealizationInfo 3
+NtGdiGetRegionData 3
+NtGdiGetRgnBox 2
+NtGdiGetServerMetaFileBits 7
+NtGdiGetSpoolMessage 4
+NtGdiGetStats 5
+NtGdiGetStockObject 1
+NtGdiGetStringBitmapW 5
+NtGdiGetSystemPaletteUse 1
+NtGdiGetTextCharsetInfo 3
+NtGdiGetTextExtent 5
+NtGdiGetTextExtentExW 8
+NtGdiGetTextFaceW 4
+NtGdiGetTextMetricsW 3
+NtGdiGetTransform 3
+NtGdiGetUFI 6
+NtGdiGetEmbUFI 7
+NtGdiGetUFIPathname 10
+NtGdiGetEmbedFonts 0
+NtGdiChangeGhostFont 2
+NtGdiAddEmbFontToDC 2
+NtGdiGetFontUnicodeRanges 2
+NtGdiGetWidthTable 7
+NtGdiGradientFill 6
+NtGdiHfontCreate 5
+NtGdiIcmBrushInfo 8
+NtGdiInit 0
+NtGdiInitSpool 0
+NtGdiIntersectClipRect 5
+NtGdiInvertRgn 2
+NtGdiLineTo 3
+NtGdiMakeFontDir 5
+NtGdiMakeInfoDC 2
+NtGdiMaskBlt 13
+NtGdiModifyWorldTransform 3
+NtGdiMonoBitmap 1
+NtGdiMoveTo 4
+NtGdiOffsetClipRgn 3
+NtGdiOffsetRgn 3
+NtGdiOpenDCW 7
+NtGdiPatBlt 6
+NtGdiPolyPatBlt 5
+NtGdiPathToRegion 1
+NtGdiPlgBlt 11
+NtGdiPolyDraw 4
+NtGdiPolyPolyDraw 5
+NtGdiPolyTextOutW 4
+NtGdiPtInRegion 3
+NtGdiPtVisible 3
+NtGdiQueryFonts 3
+NtGdiQueryFontAssocInfo 1
+NtGdiRectangle 5
+NtGdiRectInRegion 2
+NtGdiRectVisible 2
+NtGdiRemoveFontResourceW 6
+NtGdiRemoveFontMemResourceEx 1
+NtGdiResetDC 5
+NtGdiResizePalette 2
+NtGdiRestoreDC 2
+NtGdiRoundRect 7
+NtGdiSaveDC 1
+NtGdiScaleViewportExtEx 6
+NtGdiScaleWindowExtEx 6
+GreSelectBitmap 2
+NtGdiSelectBrush 2
+NtGdiSelectClipPath 2
+NtGdiSelectFont 2
+NtGdiSelectPen 2
+NtGdiSetBitmapAttributes 2
+NtGdiSetBitmapBits 3
+NtGdiSetBitmapDimension 4
+NtGdiSetBoundsRect 3
+NtGdiSetBrushAttributes 2
+NtGdiSetBrushOrg 4
+NtGdiSetColorAdjustment 2
+NtGdiSetColorSpace 2
+NtGdiSetDeviceGammaRamp 2
+NtGdiSetDIBitsToDeviceInternal 16
+NtGdiSetFontEnumeration 1
+NtGdiSetFontXform 3
+NtGdiSetIcmMode 3
+NtGdiSetLinkedUFIs 3
+NtGdiSetMagicColors 3
+NtGdiSetMetaRgn 1
+NtGdiSetMiterLimit 3
+NtGdiGetDeviceWidth 1
+NtGdiMirrorWindowOrg 1
+NtGdiSetLayout 3
+NtGdiSetPixel 4
+NtGdiSetPixelFormat 2
+NtGdiSetRectRgn 5
+NtGdiSetSystemPaletteUse 2
+NtGdiSetTextJustification 3
+NtGdiSetupPublicCFONT 3
+NtGdiSetVirtualResolution 5
+NtGdiSetSizeDevice 3
+NtGdiStartDoc 4
+NtGdiStartPage 1
+NtGdiStretchBlt 12
+NtGdiStretchDIBitsInternal 16
+NtGdiStrokeAndFillPath 1
+NtGdiStrokePath 1
+NtGdiSwapBuffers 1
+NtGdiTransformPoints 5
+NtGdiTransparentBlt 11
+NtGdiUnloadPrinterDriver 2
+NtGdiUnmapMemFont 1
+NtGdiUnrealizeObject 1
+NtGdiUpdateColors 1
+NtGdiWidenPath 1
+NtUserActivateKeyboardLayout 2
+NtUserAlterWindowStyle 3
+NtUserAssociateInputContext 3
+NtUserAttachThreadInput 3
+NtUserBeginPaint 2
+NtUserBitBltSysBmp 8
+NtUserBlockInput 1
+NtUserBuildHimcList 4
+NtUserBuildHwndList 7
+NtUserBuildNameList 4
+NtUserBuildPropList 4
+NtUserCallHwnd 2
+NtUserCallHwndLock 2
+NtUserCallHwndOpt 2
+NtUserCallHwndParam 3
+NtUserCallHwndParamLock 3
+NtUserCallMsgFilter 2
+NtUserCallNextHookEx 4
+NtUserCallNoParam 1
+NtUserCallOneParam 2
+NtUserCallTwoParam 3
+NtUserChangeClipboardChain 2
+NtUserChangeDisplaySettings 4
+NtUserCheckImeHotKey 2
+NtUserCheckMenuItem 3
+NtUserChildWindowFromPointEx 4
+NtUserClipCursor 1
+NtUserCloseClipboard 0
+NtUserCloseDesktop 1
+NtUserCloseWindowStation 1
+NtUserConsoleControl 3
+NtUserConvertMemHandle 2
+NtUserCopyAcceleratorTable 3
+NtUserCountClipboardFormats 0
+NtUserCreateAcceleratorTable 2
+NtUserCreateCaret 4
+NtUserCreateDesktop 5
+NtUserCreateInputContext 1
+NtUserCreateLocalMemHandle 4
+NtUserCreateWindowEx 15
+NtUserCreateWindowStation 7
+NtUserDdeGetQualityOfService 3
+NtUserDdeInitialize 5
+NtUserDdeSetQualityOfService 3
+NtUserDeferWindowPos 8
+NtUserDefSetText 2
+NtUserDeleteMenu 3
+NtUserDestroyAcceleratorTable 1
+NtUserDestroyCursor 2
+NtUserDestroyInputContext 1
+NtUserDestroyMenu 1
+NtUserDestroyWindow 1
+NtUserDisableThreadIme 1
+NtUserDispatchMessage 1
+NtUserDragDetect 3
+NtUserDragObject 5
+NtUserDrawAnimatedRects 4
+NtUserDrawCaption 4
+NtUserDrawCaptionTemp 7
+NtUserDrawIconEx 11
+NtUserDrawMenuBarTemp 5
+NtUserEmptyClipboard 0
+NtUserEnableMenuItem 3
+NtUserEnableScrollBar 3
+NtUserEndDeferWindowPosEx 2
+NtUserEndMenu 0
+NtUserEndPaint 2
+NtUserEnumDisplayDevices 4
+NtUserEnumDisplayMonitors 4
+NtUserEnumDisplaySettings 4
+NtUserEvent 1
+NtUserExcludeUpdateRgn 2
+NtUserFillWindow 4
+NtUserFindExistingCursorIcon 3
+NtUserFindWindowEx 5
+NtUserFlashWindowEx 1
+NtUserGetAltTabInfo 6
+NtUserGetAncestor 2
+NtUserGetAppImeLevel 1
+NtUserGetAsyncKeyState 1
+NtUserGetAtomName 2
+NtUserGetCaretBlinkTime 0
+NtUserGetCaretPos 1
+NtUserGetClassInfoEx 5
+NtUserGetClassName 3
+NtUserGetClipboardData 2
+NtUserGetClipboardFormatName 3
+NtUserGetClipboardOwner 0
+NtUserGetClipboardSequenceNumber 0
+NtUserGetClipboardViewer 0
+NtUserGetClipCursor 1
+NtUserGetComboBoxInfo 2
+NtUserGetControlBrush 3
+NtUserGetControlColor 4
+NtUserGetCPD 3
+NtUserGetCursorFrameInfo 4
+NtUserGetCursorInfo 1
+NtUserGetDC 1
+NtUserGetDCEx 3
+NtUserGetDoubleClickTime 0
+NtUserGetForegroundWindow 0
+NtUserGetGuiResources 2
+NtUserGetGUIThreadInfo 2
+NtUserGetIconInfo 6
+NtUserGetIconSize 4
+NtUserGetImeHotKey 4
+NtUserGetImeInfoEx 2
+NtUserGetInternalWindowPos 3
+NtUserGetKeyboardLayoutList 2
+NtUserGetKeyboardLayoutName 1
+NtUserGetKeyboardState 1
+NtUserGetKeyNameText 3
+NtUserGetKeyState 1
+NtUserGetListBoxInfo 1
+NtUserGetMenuBarInfo 4
+NtUserGetMenuIndex 2
+NtUserGetMenuItemRect 4
+NtUserGetMessage 4
+NtUserGetMouseMovePointsEx 5
+NtUserGetObjectInformation 5
+NtUserGetOpenClipboardWindow 0
+NtUserGetPriorityClipboardFormat 2
+NtUserGetProcessWindowStation 0
+NtUserGetRawInputBuffer 3
+NtUserGetRawInputData 5
+NtUserGetRawInputDeviceInfo 4
+NtUserGetRawInputDeviceList 3
+NtUserGetRegisteredRawInputDevices 3
+NtUserGetScrollBarInfo 3
+NtUserGetSystemMenu 2
+NtUserGetThreadDesktop 2
+NtUserGetThreadState 1
+NtUserGetTitleBarInfo 2
+NtUserGetUpdateRect 3
+NtUserGetUpdateRgn 3
+NtUserGetWindowDC 1
+NtUserGetWindowPlacement 2
+NtUserGetWOWClass 2
+NtUserHardErrorControl 3
+NtUserHideCaret 1
+NtUserHiliteMenuItem 4
+NtUserImpersonateDdeClientWindow 2
+NtUserInitialize 3
+NtUserInitializeClientPfnArrays 4
+NtUserInitTask 12
+NtUserInternalGetWindowText 3
+NtUserInvalidateRect 3
+NtUserInvalidateRgn 3
+NtUserIsClipboardFormatAvailable 1
+NtUserKillTimer 2
+NtUserLoadKeyboardLayoutEx 7
+NtUserLockWindowStation 1
+NtUserLockWindowUpdate 1
+NtUserLockWorkStation 0
+NtUserMapVirtualKeyEx 4
+NtUserMenuItemFromPoint 4
+NtUserMessageCall 7
+NtUserMinMaximize 3
+NtUserMNDragLeave 0
+NtUserMNDragOver 2
+NtUserModifyUserStartupInfoFlags 2
+NtUserMoveWindow 6
+NtUserNotifyIMEStatus 3
+NtUserNotifyProcessCreate 4
+NtUserNotifyWinEvent 4
+NtUserOpenClipboard 2
+NtUserOpenDesktop 3
+NtUserOpenInputDesktop 3
+NtUserOpenWindowStation 2
+NtUserPaintDesktop 1
+NtUserPeekMessage 5
+NtUserPostMessage 4
+NtUserPostThreadMessage 4
+NtUserPrintWindow 3
+NtUserProcessConnect 3
+NtUserQueryInformationThread 4
+NtUserQueryInputContext 2
+NtUserQuerySendMessage 1
+NtUserQueryWindow 2
+NtUserRealChildWindowFromPoint 3
+NtUserRealInternalGetMessage 6
+NtUserRealWaitMessageEx 2
+NtUserRedrawWindow 4
+NtUserRegisterClassExWOW 7
+NtUserRegisterUserApiHook 4
+NtUserRegisterHotKey 4
+NtUserRegisterRawInputDevices 3
+NtUserRegisterTasklist 1
+NtUserRegisterWindowMessage 1
+NtUserRemoveMenu 3
+NtUserRemoveProp 2
+NtUserResolveDesktop 4
+NtUserResolveDesktopForWOW 1
+NtUserSBGetParms 4
+NtUserScrollDC 7
+NtUserScrollWindowEx 8
+NtUserSelectPalette 3
+NtUserSendInput 3
+NtUserSetActiveWindow 1
+NtUserSetAppImeLevel 2
+NtUserSetCapture 1
+NtUserSetClassLong 4
+NtUserSetClassWord 3
+NtUserSetClipboardData 3
+NtUserSetClipboardViewer 1
+NtUserSetConsoleReserveKeys 2
+NtUserSetCursor 1
+NtUserSetCursorContents 2
+NtUserSetCursorIconData 4
+NtUserSetFocus 1
+NtUserSetImeHotKey 5
+NtUserSetImeInfoEx 1
+NtUserSetImeOwnerWindow 2
+NtUserSetInformationProcess 4
+NtUserSetInformationThread 4
+NtUserSetInternalWindowPos 4
+NtUserSetKeyboardState 1
+NtUserSetLogonNotifyWindow 1
+NtUserSetMenu 3
+NtUserSetMenuContextHelpId 2
+NtUserSetMenuDefaultItem 3
+NtUserSetMenuFlagRtoL 1
+NtUserSetObjectInformation 4
+NtUserSetParent 2
+NtUserSetProcessWindowStation 1
+NtUserSetProp 3
+NtUserSetScrollInfo 4
+NtUserSetShellWindowEx 2
+NtUserSetSysColors 4
+NtUserSetSystemCursor 2
+NtUserSetSystemMenu 2
+NtUserSetSystemTimer 4
+NtUserSetThreadDesktop 1
+NtUserSetThreadLayoutHandles 2
+NtUserSetThreadState 2
+NtUserSetTimer 4
+NtUserSetWindowFNID 2
+NtUserSetWindowLong 4
+NtUserSetWindowPlacement 2
+NtUserSetWindowPos 7
+NtUserSetWindowRgn 3
+NtUserSetWindowsHookAW 3
+NtUserSetWindowsHookEx 6
+NtUserSetWindowStationUser 4
+NtUserSetWindowWord 3
+NtUserSetWinEventHook 8
+NtUserShowCaret 1
+NtUserShowScrollBar 3
+NtUserShowWindow 2
+NtUserShowWindowAsync 2
+NtUserSoundSentry 0
+NtUserSwitchDesktop 1
+NtUserSystemParametersInfo 4
+NtUserTestForInteractiveUser 1
+NtUserThunkedMenuInfo 2
+NtUserThunkedMenuItemInfo 6
+NtUserToUnicodeEx 7
+NtUserTrackMouseEvent 1
+NtUserTrackPopupMenuEx 6
+NtUserCalcMenuBar 5
+NtUserPaintMenuBar 6
+NtUserTranslateAccelerator 3
+NtUserTranslateMessage 2
+NtUserUnhookWindowsHookEx 1
+NtUserUnhookWinEvent 1
+NtUserUnloadKeyboardLayout 1
+NtUserUnlockWindowStation 1
+NtUserUnregisterClass 3
+NtUserUnregisterUserApiHook 0
+NtUserUnregisterHotKey 2
+NtUserUpdateInputContext 3
+NtUserUpdateInstance 3
+NtUserUpdateLayeredWindow 10
+NtUserGetLayeredWindowAttributes 4
+NtUserSetLayeredWindowAttributes 4
+NtUserUpdatePerUserSystemParameters 2
+NtUserUserHandleGrantAccess 3
+NtUserValidateHandleSecure 1
+NtUserValidateRect 2
+NtUserValidateTimerCallback 1
+NtUserVkKeyScanEx 3
+NtUserWaitForInputIdle 3
+NtUserWaitForMsgAndEvent 1
+NtUserWaitMessage 0
+NtUserWin32PoolAllocationStats 6
+NtUserWindowFromPoint 2
+NtUserYieldTask 0
+NtUserRemoteConnect 3
+NtUserRemoteRedrawRectangle 4
+NtUserRemoteRedrawScreen 0
+NtUserRemoteStopScreenUpdates 0
+NtUserCtxDisplayIOCtl 3
+NtGdiEngAssociateSurface 3
+NtGdiEngCreateBitmap 6
+NtGdiEngCreateDeviceSurface 4
+NtGdiEngCreateDeviceBitmap 4
+NtGdiEngCreatePalette 6
+NtGdiEngComputeGlyphSet 3
+NtGdiEngCopyBits 6
+NtGdiEngDeletePalette 1
+NtGdiEngDeleteSurface 1
+NtGdiEngEraseSurface 3
+NtGdiEngUnlockSurface 1
+NtGdiEngLockSurface 1
+NtGdiEngBitBlt 11
+NtGdiEngStretchBlt 11
+NtGdiEngPlgBlt 11
+NtGdiEngMarkBandingSurface 1
+NtGdiEngStrokePath 8
+NtGdiEngFillPath 7
+NtGdiEngStrokeAndFillPath 10
+NtGdiEngPaint 5
+NtGdiEngLineTo 9
+NtGdiEngAlphaBlend 7
+NtGdiEngGradientFill 10
+NtGdiEngTransparentBlt 8
+NtGdiEngTextOut 10
+NtGdiEngStretchBltROP 13
+NtGdiXLATEOBJ_cGetPalette 4
+NtGdiXLATEOBJ_iXlate 2
+NtGdiXLATEOBJ_hGetColorTransform 1
+NtGdiCLIPOBJ_bEnum 3
+NtGdiCLIPOBJ_cEnumStart 5
+NtGdiCLIPOBJ_ppoGetPath 1
+NtGdiEngDeletePath 1
+NtGdiEngCreateClip 0
+NtGdiEngDeleteClip 1
+NtGdiBRUSHOBJ_ulGetBrushColor 1
+NtGdiBRUSHOBJ_pvAllocRbrush 2
+NtGdiBRUSHOBJ_pvGetRbrush 1
+NtGdiBRUSHOBJ_hGetColorTransform 1
+NtGdiXFORMOBJ_bApplyXform 5
+NtGdiXFORMOBJ_iGetXform 2
+NtGdiFONTOBJ_vGetInfo 3
+NtGdiFONTOBJ_pxoGetXform 1
+NtGdiFONTOBJ_cGetGlyphs 5
+NtGdiFONTOBJ_pifi 1
+NtGdiFONTOBJ_pfdg 1
+NtGdiFONTOBJ_pQueryGlyphAttrs 2
+NtGdiFONTOBJ_pvTrueTypeFontFile 2
+NtGdiFONTOBJ_cGetAllGlyphHandles 2
+NtGdiSTROBJ_bEnum 3
+NtGdiSTROBJ_bEnumPositionsOnly 3
+NtGdiSTROBJ_bGetAdvanceWidths 4
+NtGdiSTROBJ_vEnumStart 1
+NtGdiSTROBJ_dwGetCodePage 1
+NtGdiPATHOBJ_vGetBounds 2
+NtGdiPATHOBJ_bEnum 2
+NtGdiPATHOBJ_vEnumStart 1
+NtGdiPATHOBJ_vEnumStartClipLines 4
+NtGdiPATHOBJ_bEnumClipLines 3
+NtGdiGetDhpdev 1
+NtGdiEngCheckAbort 1
+NtGdiHT_Get8BPPFormatPalette 4
+NtGdiHT_Get8BPPMaskPalette 6
+NtGdiUpdateTransform 1
+NtGdiSetPUMPDOBJ 4
+NtGdiBRUSHOBJ_DeleteRbrush 2
+NtGdiUnmapMemFont 1
+NtGdiDrawStream 3
+NtGdiMakeObjectXferable 2
+NtGdiMakeObjectUnXferable 1
diff --git a/rostests/apitests/w32kdll/w32kdll_2ksp4/w32k_2ksp4-x86.db b/rostests/apitests/w32kdll/w32kdll_2ksp4/w32k_2ksp4-x86.db
new file mode 100644
index 00000000000..b8fda7a4f0d
--- /dev/null
+++ b/rostests/apitests/w32kdll/w32kdll_2ksp4/w32k_2ksp4-x86.db
@@ -0,0 +1,643 @@
+#
+# win32k systemcalls taken from Windows 2000 SP4 x86
+#
+NtGdiAbortDoc 1
+NtGdiAbortPath 1
+NtGdiAddFontResourceW 6
+NtGdiAddRemoteFontToDC 4
+NtGdiAddFontMemResourceEx 5
+NtGdiRemoveMergeFont 2
+NtGdiAddRemoteMMInstanceToDC 3
+NtGdiAlphaBlend 12
+NtGdiAngleArc 6
+NtGdiAnyLinkedFonts 0
+NtGdiFontIsLinked 1
+NtGdiArcInternal 10
+NtGdiBeginPath 1
+NtGdiBitBlt 11
+NtGdiCancelDC 1
+NtGdiCheckBitmapBits 8
+NtGdiCloseFigure 1
+NtGdiColorCorrectPalette 6
+NtGdiCombineRgn 4
+NtGdiCombineTransform 3
+NtGdiComputeXformCoefficients 1
+NtGdiConsoleTextOut 4
+NtGdiConvertMetafileRect 2
+NtGdiCreateBitmap 5
+NtGdiCreateClientObj 1
+NtGdiCreateColorSpace 1
+NtGdiCreateColorTransform 8
+NtGdiCreateCompatibleBitmap 3
+NtGdiCreateCompatibleDC 1
+NtGdiCreateDIBBrush 6
+NtGdiCreateDIBitmapInternal 11
+NtGdiCreateDIBSection 9
+NtGdiCreateEllipticRgn 4
+NtGdiCreateHalftonePalette 1
+NtGdiCreateHatchBrushInternal 3
+NtGdiCreateMetafileDC 1
+NtGdiCreatePaletteInternal 2
+NtGdiCreatePatternBrushInternal 3
+NtGdiCreatePen 4
+NtGdiCreateRectRgn 4
+NtGdiCreateRoundRectRgn 6
+NtGdiCreateServerMetaFile 6
+NtGdiCreateSolidBrush 2
+NtGdiD3dContextCreate 4
+NtGdiD3dContextDestroy 1
+NtGdiD3dContextDestroyAll 1
+NtGdiD3dValidateTextureStageState 1
+NtGdiD3dDrawPrimitives2 7
+NtGdiDdGetDriverState 1
+NtGdiDdAddAttachedSurface 3
+NtGdiDdAlphaBlt 3
+NtGdiDdAttachSurface 2
+NtGdiDdBeginMoCompFrame 2
+NtGdiDdBlt 3
+NtGdiDdCanCreateSurface 2
+NtGdiDdCanCreateD3DBuffer 2
+NtGdiDdColorControl 2
+NtGdiDdCreateDirectDrawObject 1
+NtGdiDdCreateSurface 8
+NtGdiDdCreateD3DBuffer 8
+NtGdiDdCreateMoComp 2
+NtGdiDdCreateSurfaceObject 6
+NtGdiDdDeleteDirectDrawObject 1
+NtGdiDdDeleteSurfaceObject 1
+NtGdiDdDestroyMoComp 2
+NtGdiDdDestroySurface 2
+NtGdiDdDestroyD3DBuffer 1
+NtGdiDdEndMoCompFrame 2
+NtGdiDdFlip 5
+NtGdiDdFlipToGDISurface 2
+NtGdiDdGetAvailDriverMemory 2
+NtGdiDdGetBltStatus 2
+NtGdiDdGetDC 2
+NtGdiDdGetDriverInfo 2
+NtGdiDdGetDxHandle 3
+NtGdiDdGetFlipStatus 2
+NtGdiDdGetInternalMoCompInfo 2
+NtGdiDdGetMoCompBuffInfo 2
+NtGdiDdGetMoCompGuids 2
+NtGdiDdGetMoCompFormats 2
+NtGdiDdGetScanLine 2
+NtGdiDdLock 3
+NtGdiDdLockD3D 2
+NtGdiDdQueryDirectDrawObject 11
+NtGdiDdQueryMoCompStatus 2
+NtGdiDdReenableDirectDrawObject 2
+NtGdiDdReleaseDC 1
+NtGdiDdRenderMoComp 2
+NtGdiDdResetVisrgn 2
+NtGdiDdSetColorKey 2
+NtGdiDdSetExclusiveMode 2
+NtGdiDdSetGammaRamp 3
+NtGdiDdCreateSurfaceEx 3
+NtGdiDdSetOverlayPosition 3
+NtGdiDdUnattachSurface 2
+NtGdiDdUnlock 2
+NtGdiDdUnlockD3D 2
+NtGdiDdUpdateOverlay 3
+NtGdiDdWaitForVerticalBlank 2
+NtGdiDvpCanCreateVideoPort 2
+NtGdiDvpColorControl 2
+NtGdiDvpCreateVideoPort 2
+NtGdiDvpDestroyVideoPort 2
+NtGdiDvpFlipVideoPort 4
+NtGdiDvpGetVideoPortBandwidth 2
+NtGdiDvpGetVideoPortField 2
+NtGdiDvpGetVideoPortFlipStatus 2
+NtGdiDvpGetVideoPortInputFormats 2
+NtGdiDvpGetVideoPortLine 2
+NtGdiDvpGetVideoPortOutputFormats 2
+NtGdiDvpGetVideoPortConnectInfo 2
+NtGdiDvpGetVideoSignalStatus 2
+NtGdiDvpUpdateVideoPort 4
+NtGdiDvpWaitForVideoPortSync 2
+NtGdiDeleteClientObj 1
+NtGdiDeleteColorSpace 1
+NtGdiDeleteColorTransform 2
+NtGdiDeleteObjectApp 1
+NtGdiDescribePixelFormat 4
+NtGdiGetPerBandInfo 2
+NtGdiDoBanding 4
+NtGdiDoPalette 6
+NtGdiDrawEscape 4
+NtGdiEllipse 5
+NtGdiEnableEudc 1
+NtGdiEndDoc 1
+NtGdiEndPage 1
+NtGdiEndPath 1
+NtGdiEnumFontChunk 5
+NtGdiEnumFontClose 1
+NtGdiEnumFontOpen 7
+NtGdiEnumObjects 4
+NtGdiEqualRgn 2
+NtGdiEudcEnumFaceNameLinkW 4
+NtGdiEudcLoadUnloadLink 7
+NtGdiExcludeClipRect 5
+NtGdiExtCreatePen 11
+NtGdiExtCreateRegion 3
+NtGdiExtEscape 8
+NtGdiExtFloodFill 5
+NtGdiExtGetObjectW 3
+NtGdiExtSelectClipRgn 3
+NtGdiExtTextOutW 9
+NtGdiFillPath 1
+NtGdiFillRgn 3
+NtGdiFlattenPath 1
+NtGdiFlushUserBatch 0
+NtGdiFlush 0
+NtGdiForceUFIMapping 2
+NtGdiFrameRgn 5
+NtGdiFullscreenControl 5
+NtGdiGetAndSetDCDword 4
+NtGdiGetAppClipBox 2
+NtGdiGetBitmapBits 3
+NtGdiGetBitmapDimension 2
+NtGdiGetBoundsRect 3
+NtGdiGetCharABCWidthsW 6
+NtGdiGetCharacterPlacementW 6
+NtGdiGetCharSet 1
+NtGdiGetCharWidthW 6
+NtGdiGetCharWidthInfo 2
+NtGdiGetColorAdjustment 2
+NtGdiGetColorSpaceforBitmap 1
+NtGdiGetDCDword 3
+NtGdiGetDCforBitmap 1
+NtGdiGetDCObject 2
+NtGdiGetDCPoint 3
+NtGdiGetDeviceCaps 2
+NtGdiGetDeviceGammaRamp 2
+NtGdiGetDeviceCapsAll 2
+NtGdiGetDIBitsInternal 9
+NtGdiGetETM 2
+NtGdiGetEudcTimeStampEx 3
+NtGdiGetFontData 5
+NtGdiGetFontResourceInfoInternalW 7
+NtGdiGetGlyphIndicesW 5
+NtGdiGetGlyphIndicesWInternal 6
+NtGdiGetGlyphOutline 8
+NtGdiGetKerningPairs 3
+NtGdiGetLinkedUFIs 3
+NtGdiGetMiterLimit 2
+NtGdiGetMonitorID 3
+NtGdiGetNearestColor 2
+NtGdiGetNearestPaletteIndex 2
+NtGdiGetObjectBitmapHandle 2
+NtGdiGetOutlineTextMetricsInternalW 4
+NtGdiGetPath 4
+NtGdiGetPixel 3
+NtGdiGetRandomRgn 3
+NtGdiGetRasterizerCaps 2
+NtGdiGetRealizationInfo 2
+NtGdiGetRegionData 3
+NtGdiGetRgnBox 2
+NtGdiGetServerMetaFileBits 7
+NtGdiGetSpoolMessage 4
+NtGdiGetStats 5
+NtGdiGetStockObject 1
+NtGdiGetStringBitmapW 5
+NtGdiGetSystemPaletteUse 1
+NtGdiGetTextCharsetInfo 3
+NtGdiGetTextExtent 5
+NtGdiGetTextExtentExW 8
+NtGdiGetTextFaceW 4
+NtGdiGetTextMetricsW 3
+NtGdiGetTransform 3
+NtGdiGetUFI 6
+NtGdiGetUFIPathname 10
+NtGdiGetFontUnicodeRanges 2
+NtGdiGetWidthTable 7
+NtGdiGradientFill 6
+NtGdiHfontCreate 5
+NtGdiIcmBrushInfo 8
+NtGdiInit 0
+NtGdiInitSpool 0
+NtGdiIntersectClipRect 5
+NtGdiInvertRgn 2
+NtGdiLineTo 3
+NtGdiMakeFontDir 5
+NtGdiMakeInfoDC 2
+NtGdiMaskBlt 13
+NtGdiModifyWorldTransform 3
+NtGdiMonoBitmap 1
+NtGdiMoveTo 4
+NtGdiOffsetClipRgn 3
+NtGdiOffsetRgn 3
+NtGdiOpenDCW 7
+NtGdiPatBlt 6
+NtGdiPolyPatBlt 5
+NtGdiPathToRegion 1
+NtGdiPlgBlt 11
+NtGdiPolyDraw 4
+NtGdiPolyPolyDraw 5
+NtGdiPolyTextOutW 4
+NtGdiPtInRegion 3
+NtGdiPtVisible 3
+NtGdiQueryFonts 3
+NtGdiQueryFontAssocInfo 1
+NtGdiRectangle 5
+NtGdiRectInRegion 2
+NtGdiRectVisible 2
+NtGdiRemoveFontResourceW 6
+NtGdiRemoveFontMemResourceEx 1
+NtGdiResetDC 5
+NtGdiResizePalette 2
+NtGdiRestoreDC 2
+NtGdiRoundRect 7
+NtGdiSaveDC 1
+NtGdiScaleViewportExtEx 6
+NtGdiScaleWindowExtEx 6
+NtGdiSelectBitmap 2
+NtGdiSelectBrush 2
+NtGdiSelectClipPath 2
+NtGdiSelectFont 2
+NtGdiSelectPen 2
+NtGdiSetBitmapBits 3
+NtGdiSetBitmapDimension 4
+NtGdiSetBoundsRect 3
+NtGdiSetBrushOrg 4
+NtGdiSetColorAdjustment 2
+NtGdiSetColorSpace 2
+NtGdiSetDeviceGammaRamp 2
+NtGdiSetDIBitsToDeviceInternal 16
+NtGdiSetFontEnumeration 1
+NtGdiSetFontXform 3
+NtGdiSetIcmMode 3
+NtGdiSetLinkedUFIs 3
+NtGdiSetMagicColors 3
+NtGdiSetMetaRgn 1
+NtGdiSetMiterLimit 3
+NtGdiGetDeviceWidth 1
+NtGdiMirrorWindowOrg 1
+NtGdiSetLayout 3
+NtGdiSetPixel 4
+NtGdiSetPixelFormat 2
+NtGdiSetRectRgn 5
+NtGdiSetSystemPaletteUse 2
+NtGdiSetTextJustification 3
+NtGdiSetupPublicCFONT 3
+NtGdiSetVirtualResolution 5
+NtGdiSetSizeDevice 3
+NtGdiStartDoc 4
+NtGdiStartPage 1
+NtGdiStretchBlt 12
+NtGdiStretchDIBitsInternal 16
+NtGdiStrokeAndFillPath 1
+NtGdiStrokePath 1
+NtGdiSwapBuffers 1
+NtGdiTransformPoints 5
+NtGdiTransparentBlt 11
+NtGdiUnloadPrinterDriver 2
+NtGdiUnmapMemFont 1
+NtGdiUnrealizeObject 1
+NtGdiUpdateColors 1
+NtGdiWidenPath 1
+NtUserActivateKeyboardLayout 2
+NtUserAlterWindowStyle 3
+NtUserAssociateInputContext 3
+NtUserAttachThreadInput 3
+NtUserBeginPaint 2
+NtUserBitBltSysBmp 8
+NtUserBlockInput 1
+NtUserBuildHimcList 4
+NtUserBuildHwndList 7
+NtUserBuildNameList 4
+NtUserBuildPropList 4
+NtUserCallHwnd 2
+NtUserCallHwndLock 2
+NtUserCallHwndOpt 2
+NtUserCallHwndParam 3
+NtUserCallHwndParamLock 3
+NtUserCallMsgFilter 2
+NtUserCallNextHookEx 4
+NtUserCallNoParam 1
+NtUserCallOneParam 1
+NtUserCallTwoParam 3
+NtUserChangeClipboardChain 2
+NtUserChangeDisplaySettings 5
+NtUserCheckImeHotKey 3
+NtUserCheckMenuItem 3
+NtUserChildWindowFromPointEx 4
+NtUserClipCursor 1
+NtUserCloseClipboard 0
+NtUserCloseDesktop 1
+NtUserCloseWindowStation 1
+NtUserConsoleControl 3
+NtUserConvertMemHandle 2
+NtUserCopyAcceleratorTable 3
+NtUserCountClipboardFormats 1
+NtUserCreateAcceleratorTable 2
+NtUserCreateCaret 4
+NtUserCreateDesktop 5
+NtUserCreateInputContext 1
+NtUserCreateLocalMemHandle 4
+NtUserCreateWindowEx 13
+NtUserCreateWindowStation 6
+NtUserDdeGetQualityOfService 3
+NtUserDdeInitialize 5
+NtUserDdeSetQualityOfService 3
+NtUserDeferWindowPos 8
+NtUserDefSetText 2
+NtUserDeleteMenu 3
+NtUserDestroyAcceleratorTable 1
+NtUserDestroyCursor 2
+NtUserDestroyInputContext 1
+NtUserDestroyMenu 1
+NtUserDestroyWindow 1
+NtUserDisableThreadIme 1
+NtUserDispatchMessage 1
+NtUserDragDetect 3
+NtUserDragObject 5
+NtUserDrawAnimatedRects 4
+NtUserDrawCaption 4
+NtUserDrawCaptionTemp 7
+NtUserDrawIconEx 11
+NtUserDrawMenuBarTemp 5
+NtUserEmptyClipboard 0
+NtUserEnableMenuItem 3
+NtUserEnableScrollBar 3
+NtUserEndDeferWindowPosEx 2
+NtUserEndMenu 0
+NtUserEndPaint 2
+NtUserEnumDisplayDevices 4
+NtUserEnumDisplayMonitors 4
+NtUserEnumDisplaySettings 4
+NtUserEvent 1
+NtUserExcludeUpdateRgn 2
+NtUserFillWindow 4
+NtUserFindExistingCursorIcon 3
+NtUserFindWindowEx 5
+NtUserFlashWindowEx 1
+NtUserGetAltTabInfo 6
+NtUserGetAncestor 2
+NtUserGetAppImeLevel 1
+NtUserGetAsyncKeyState 1
+NtUserGetCaretBlinkTime 0
+NtUserGetCaretPos 1
+NtUserGetClassInfo 5
+NtUserGetClassName 3
+NtUserGetClipboardData 2
+NtUserGetClipboardFormatName 3
+NtUserGetClipboardOwner 0
+NtUserGetClipboardSequenceNumber 0
+NtUserGetClipboardViewer 0
+NtUserGetClipCursor 1
+NtUserGetComboBoxInfo 2
+NtUserGetControlBrush 3
+NtUserGetControlColor 4
+NtUserGetCPD 3
+NtUserGetCursorFrameInfo 4
+NtUserGetCursorInfo 1
+NtUserGetDC 1
+NtUserGetDCEx 3
+NtUserGetDoubleClickTime 0
+NtUserGetForegroundWindow 0
+NtUserGetGuiResources 2
+NtUserGetGUIThreadInfo 2
+NtUserGetIconInfo 6
+NtUserGetIconSize 4
+NtUserGetImeHotKey 4
+NtUserGetImeInfoEx 2
+NtUserGetInternalWindowPos 3
+NtUserGetKeyboardLayoutList 2
+NtUserGetKeyboardLayoutName 1
+NtUserGetKeyboardState 1
+NtUserGetKeyNameText 3
+NtUserGetKeyState 1
+NtUserGetListBoxInfo 1
+NtUserGetMenuBarInfo 4
+NtUserGetMenuIndex 2
+NtUserGetMenuItemRect 4
+NtUserGetMessage 4
+NtUserGetMouseMovePointsEx 5
+NtUserGetObjectInformation 5
+NtUserGetOpenClipboardWindow 0
+NtUserGetPriorityClipboardFormat 2
+NtUserGetProcessWindowStation 0
+NtUserGetScrollBarInfo 3
+NtUserGetSystemMenu 2
+NtUserGetThreadDesktop 2
+NtUserGetThreadState 1
+NtUserGetTitleBarInfo 2
+NtUserGetUpdateRect 3
+NtUserGetUpdateRgn 3
+NtUserGetWindowDC 1
+NtUserGetWindowPlacement 2
+NtUserGetWOWClass 2
+NtUserHardErrorControl 3
+NtUserHideCaret 1
+NtUserHiliteMenuItem 4
+NtUserImpersonateDdeClientWindow 2
+NtUserInitialize 3
+NtUserInitializeClientPfnArrays 4
+NtUserInitTask 11
+NtUserInternalGetWindowText 3
+NtUserInvalidateRect 3
+NtUserInvalidateRgn 3
+NtUserIsClipboardFormatAvailable 1
+NtUserKillTimer 2
+NtUserLoadKeyboardLayoutEx 6
+NtUserLockWindowStation 1
+NtUserLockWindowUpdate 1
+NtUserLockWorkStation 0
+NtUserMapVirtualKeyEx 4
+NtUserMenuItemFromPoint 4
+NtUserMessageCall 7
+NtUserMinMaximize 3
+NtUserMNDragLeave 1
+NtUserMNDragOver 2
+NtUserModifyUserStartupInfoFlags 2
+NtUserMoveWindow 6
+NtUserNotifyIMEStatus 3
+NtUserNotifyProcessCreate 4
+NtUserNotifyWinEvent 4
+NtUserOpenClipboard 2
+NtUserOpenDesktop 3
+NtUserOpenInputDesktop 3
+NtUserOpenWindowStation 2
+NtUserPaintDesktop 1
+NtUserPeekMessage 5
+NtUserPostMessage 4
+NtUserPostThreadMessage 4
+NtUserProcessConnect 3
+NtUserQueryInformationThread 5
+NtUserQueryInputContext 2
+NtUserQuerySendMessage 1
+NtUserQueryUserCounters 5
+NtUserQueryWindow 2
+NtUserRealChildWindowFromPoint 3
+NtUserRedrawWindow 4
+NtUserRegisterClassExWOW 6
+NtUserRegisterHotKey 4
+NtUserRegisterTasklist 1
+NtUserRegisterWindowMessage 1
+NtUserRemoveMenu 3
+NtUserRemoveProp 2
+NtUserResolveDesktop 4
+NtUserResolveDesktopForWOW 1
+NtUserSBGetParms 4
+NtUserScrollDC 7
+NtUserScrollWindowEx 8
+NtUserSelectPalette 3
+NtUserSendInput 3
+NtUserSendMessageCallback 6
+NtUserSendNotifyMessage 4
+NtUserSetActiveWindow 1
+NtUserSetAppImeLevel 2
+NtUserSetCapture 1
+NtUserSetClassLong 4
+NtUserSetClassWord 3
+NtUserSetClipboardData 3
+NtUserSetClipboardViewer 1
+NtUserSetConsoleReserveKeys 2
+NtUserSetCursor 1
+NtUserSetCursorContents 2
+NtUserSetCursorIconData 4
+NtUserSetDbgTag 2
+NtUserSetFocus 1
+NtUserSetImeHotKey 5
+NtUserSetImeInfoEx 1
+NtUserSetImeOwnerWindow 2
+NtUserSetInformationProcess 4
+NtUserSetInformationThread 5
+NtUserSetInternalWindowPos 4
+NtUserSetKeyboardState 1
+NtUserSetLogonNotifyWindow 1
+NtUserSetMenu 3
+NtUserSetMenuContextHelpId 2
+NtUserSetMenuDefaultItem 3
+NtUserSetMenuFlagRtoL 1
+NtUserSetObjectInformation 4
+NtUserSetParent 2
+NtUserSetProcessWindowStation 1
+NtUserSetProp 3
+NtUserSetRipFlags 2
+NtUserSetScrollInfo 4
+NtUserSetShellWindowEx 2
+NtUserSetSysColors 4
+NtUserSetSystemCursor 2
+NtUserSetSystemMenu 2
+NtUserSetSystemTimer 4
+NtUserSetThreadDesktop 1
+NtUserSetThreadLayoutHandles 2
+NtUserSetThreadState 2
+NtUserSetTimer 4
+NtUserSetWindowFNID 2
+NtUserSetWindowLong 4
+NtUserSetWindowPlacement 2
+NtUserSetWindowPos 7
+NtUserSetWindowRgn 3
+NtUserSetWindowsHookAW 3
+NtUserSetWindowsHookEx 6
+NtUserSetWindowStationUser 4
+NtUserSetWindowWord 3
+NtUserSetWinEventHook 8
+NtUserShowCaret 1
+NtUserShowScrollBar 3
+NtUserShowWindow 2
+NtUserShowWindowAsync 2
+NtUserSoundSentry 0
+NtUserSwitchDesktop 1
+NtUserSystemParametersInfo 4
+NtUserTestForInteractiveUser 1
+NtUserThunkedMenuInfo 2
+NtUserThunkedMenuItemInfo 6
+NtUserToUnicodeEx 7
+NtUserTrackMouseEvent 1
+NtUserTrackPopupMenuEx 6
+NtUserTranslateAccelerator 3
+NtUserTranslateMessage 2
+NtUserUnhookWindowsHookEx 1
+NtUserUnhookWinEvent 1
+NtUserUnloadKeyboardLayout 1
+NtUserUnlockWindowStation 1
+NtUserUnregisterClass 3
+NtUserUnregisterHotKey 2
+NtUserUpdateInputContext 3
+NtUserUpdateInstance 3
+NtUserUpdateLayeredWindow 9
+NtUserSetLayeredWindowAttributes 4
+NtUserUpdatePerUserSystemParameters 2
+NtUserUserHandleGrantAccess 3
+NtUserValidateHandleSecure 1
+NtUserValidateRect 2
+NtUserVkKeyScanEx 3
+NtUserWaitForInputIdle 3
+NtUserWaitForMsgAndEvent 1
+NtUserWaitMessage 0
+NtUserWin32PoolAllocationStats 6
+NtUserWindowFromPoint 2
+NtUserYieldTask 0
+NtUserRemoteConnect 3
+NtUserRemoteRedrawRectangle 4
+NtUserRemoteRedrawScreen 0
+NtUserRemoteStopScreenUpdates 0
+NtUserCtxDisplayIOCtl 3
+NtGdiEngAssociateSurface 3
+NtGdiEngCreateBitmap 6
+NtGdiEngCreateDeviceSurface 4
+NtGdiEngCreateDeviceBitmap 4
+NtGdiEngCreatePalette 6
+NtGdiEngComputeGlyphSet 3
+NtGdiEngCopyBits 6
+NtGdiEngDeletePalette 1
+NtGdiEngDeleteSurface 1
+NtGdiEngEraseSurface 3
+NtGdiEngUnlockSurface 1
+NtGdiEngLockSurface 1
+NtGdiEngBitBlt 11
+NtGdiEngStretchBlt 11
+NtGdiEngPlgBlt 11
+NtGdiEngMarkBandingSurface 1
+NtGdiEngStrokePath 8
+NtGdiEngFillPath 7
+NtGdiEngStrokeAndFillPath 10
+NtGdiEngPaint 5
+NtGdiEngLineTo 9
+NtGdiEngAlphaBlend 7
+NtGdiEngGradientFill 10
+NtGdiEngTransparentBlt 8
+NtGdiEngTextOut 10
+NtGdiEngStretchBltROP 13
+NtGdiXLATEOBJ_cGetPalette 4
+NtGdiXLATEOBJ_iXlate 2
+NtGdiXLATEOBJ_hGetColorTransform 1
+NtGdiCLIPOBJ_bEnum 3
+NtGdiCLIPOBJ_cEnumStart 5
+NtGdiCLIPOBJ_ppoGetPath 1
+NtGdiEngDeletePath 1
+NtGdiEngCreateClip 0
+NtGdiEngDeleteClip 1
+NtGdiBRUSHOBJ_ulGetBrushColor 1
+NtGdiBRUSHOBJ_pvAllocRbrush 2
+NtGdiBRUSHOBJ_pvGetRbrush 1
+NtGdiBRUSHOBJ_hGetColorTransform 1
+NtGdiXFORMOBJ_bApplyXform 5
+NtGdiXFORMOBJ_iGetXform 2
+NtGdiFONTOBJ_vGetInfo 3
+NtGdiFONTOBJ_pxoGetXform 1
+NtGdiFONTOBJ_cGetGlyphs 5
+NtGdiFONTOBJ_pifi 1
+NtGdiFONTOBJ_pfdg 1
+NtGdiFONTOBJ_pQueryGlyphAttrs 2
+NtGdiFONTOBJ_pvTrueTypeFontFile 2
+NtGdiFONTOBJ_cGetAllGlyphHandles 2
+NtGdiSTROBJ_bEnum 3
+NtGdiSTROBJ_bEnumPositionsOnly 3
+NtGdiSTROBJ_bGetAdvanceWidths 4
+NtGdiSTROBJ_vEnumStart 1
+NtGdiSTROBJ_dwGetCodePage 1
+NtGdiPATHOBJ_vGetBounds 2
+NtGdiPATHOBJ_bEnum 2
+NtGdiPATHOBJ_vEnumStart 1
+NtGdiPATHOBJ_vEnumStartClipLines 4
+NtGdiPATHOBJ_bEnumClipLines 3
+NtGdiGetDhpdev 1
+NtGdiEngCheckAbort 1
+NtGdiHT_Get8BPPFormatPalette 4
+NtGdiHT_Get8BPPMaskPalette 6
+NtGdiUpdateTransform 1
+NtUserValidateTimerCallback 3
diff --git a/rostests/apitests/w32kdll/w32kdll_vista/w32kdll_vista-x86.db b/rostests/apitests/w32kdll/w32kdll_vista/w32kdll_vista-x86.db
new file mode 100644
index 00000000000..1ab85e69981
--- /dev/null
+++ b/rostests/apitests/w32kdll/w32kdll_vista/w32kdll_vista-x86.db
@@ -0,0 +1,775 @@
+#
+# win32k systemcalls taken from Windows Vista SP0 x86
+#
+NtGdiAbortDoc 1
+NtGdiAbortPath 1
+NtGdiAddFontResourceW 6
+NtGdiAddRemoteFontToDC 4
+NtGdiAddFontMemResourceEx 5
+NtGdiRemoveMergeFont 2
+NtGdiAddRemoteMMInstanceToDC 3
+NtGdiAlphaBlend 12
+NtGdiAngleArc 6
+NtGdiAnyLinkedFonts 0
+NtGdiFontIsLinked 1
+NtGdiArcInternal 10
+NtGdiBeginPath 1
+NtGdiBitBlt 11
+NtGdiCancelDC 1
+NtGdiCheckBitmapBits 8
+NtGdiCloseFigure 1
+NtGdiClearBitmapAttributes 2
+NtGdiClearBrushAttributes 2
+NtGdiColorCorrectPalette 6
+NtGdiCombineRgn 4
+NtGdiCombineTransform 3
+NtGdiComputeXformCoefficients 1
+NtGdiConfigureOPMProtectedOutput 4
+NtGdiConsoleTextOut 4
+NtGdiConvertMetafileRect 2
+NtGdiCreateBitmap 5
+NtGdiCreateClientObj 1
+NtGdiCreateColorSpace 1
+NtGdiCreateColorTransform 8
+NtGdiCreateCompatibleBitmap 3
+NtGdiCreateCompatibleDC 1
+NtGdiCreateDIBBrush 6
+NtGdiCreateDIBitmapInternal 11
+NtGdiCreateDIBSection 9
+NtGdiCreateEllipticRgn 4
+NtGdiCreateHalftonePalette 1
+NtGdiCreateHatchBrushInternal 3
+NtGdiCreateMetafileDC 1
+NtGdiCreateOPMProtectedOutputs 5
+NtGdiCreatePaletteInternal 2
+NtGdiCreatePatternBrushInternal 3
+NtGdiCreatePen 4
+NtGdiCreateRectRgn 4
+NtGdiCreateRoundRectRgn 6
+NtGdiCreateServerMetaFile 6
+NtGdiCreateSolidBrush 2
+NtGdiD3dContextCreate 4
+NtGdiD3dContextDestroy 1
+NtGdiD3dContextDestroyAll 1
+NtGdiD3dValidateTextureStageState 1
+NtGdiD3dDrawPrimitives2 7
+NtGdiDdGetDriverState 1
+NtGdiDdAddAttachedSurface 3
+NtGdiDdAlphaBlt 3
+NtGdiDdAttachSurface 2
+NtGdiDdBeginMoCompFrame 2
+NtGdiDdBlt 3
+NtGdiDdCanCreateSurface 2
+NtGdiDdCanCreateD3DBuffer 2
+NtGdiDdColorControl 2
+NtGdiDdCreateDirectDrawObject 1
+NtGdiDdCreateSurface 8
+NtGdiDdCreateD3DBuffer 8
+NtGdiDdCreateMoComp 2
+NtGdiDdCreateSurfaceObject 6
+NtGdiDdDeleteDirectDrawObject 1
+NtGdiDdDeleteSurfaceObject 1
+NtGdiDdDestroyMoComp 2
+NtGdiDdDestroySurface 2
+NtGdiDdDestroyD3DBuffer 1
+NtGdiDdEndMoCompFrame 2
+NtGdiDdFlip 5
+NtGdiDdFlipToGDISurface 2
+NtGdiDdGetAvailDriverMemory 2
+NtGdiDdGetBltStatus 2
+NtGdiDdGetDC 2
+NtGdiDdGetDriverInfo 2
+NtGdiDdGetDxHandle 3
+NtGdiDdGetFlipStatus 2
+NtGdiDdGetInternalMoCompInfo 2
+NtGdiDdGetMoCompBuffInfo 2
+NtGdiDdGetMoCompGuids 2
+NtGdiDdGetMoCompFormats 2
+NtGdiDdGetScanLine 2
+NtGdiDdLock 3
+NtGdiDdLockD3D 2
+NtGdiDdQueryDirectDrawObject 11
+NtGdiDdQueryMoCompStatus 2
+NtGdiDdReenableDirectDrawObject 2
+NtGdiDdReleaseDC 1
+NtGdiDdRenderMoComp 2
+NtGdiDdResetVisrgn 2
+NtGdiDdSetColorKey 2
+NtGdiDdSetExclusiveMode 2
+NtGdiDdSetGammaRamp 3
+NtGdiDdCreateSurfaceEx 3
+NtGdiDdSetOverlayPosition 3
+NtGdiDdUnattachSurface 2
+NtGdiDdUnlock 2
+NtGdiDdUnlockD3D 2
+NtGdiDdUpdateOverlay 3
+NtGdiDdWaitForVerticalBlank 2
+NtGdiDvpCanCreateVideoPort 2
+NtGdiDvpColorControl 2
+NtGdiDvpCreateVideoPort 2
+NtGdiDvpDestroyVideoPort 2
+NtGdiDvpFlipVideoPort 4
+NtGdiDvpGetVideoPortBandwidth 2
+NtGdiDvpGetVideoPortField 2
+NtGdiDvpGetVideoPortFlipStatus 2
+NtGdiDvpGetVideoPortInputFormats 2
+NtGdiDvpGetVideoPortLine 2
+NtGdiDvpGetVideoPortOutputFormats 2
+NtGdiDvpGetVideoPortConnectInfo 2
+NtGdiDvpGetVideoSignalStatus 2
+NtGdiDvpUpdateVideoPort 4
+NtGdiDvpWaitForVideoPortSync 2
+NtGdiDvpAcquireNotification 3
+NtGdiDvpReleaseNotification 2
+NtGdiDxgGenericThunk 6
+NtGdiDeleteClientObj 1
+NtGdiDeleteColorSpace 1
+NtGdiDeleteColorTransform 2
+NtGdiDeleteObjectApp 1
+NtGdiDescribePixelFormat 4
+NtGdiDestroyOPMProtectedOutput 1
+NtGdiGetPerBandInfo 2
+NtGdiDoBanding 4
+NtGdiDoPalette 6
+NtGdiDrawEscape 4
+NtGdiEllipse 5
+NtGdiEnableEudc 1
+NtGdiEndDoc 1
+NtGdiEndPage 1
+NtGdiEndPath 1
+NtGdiEnumFontChunk 5
+NtGdiEnumFontClose 1
+NtGdiEnumFontOpen 7
+NtGdiEnumObjects 4
+NtGdiEqualRgn 2
+NtGdiEudcLoadUnloadLink 7
+NtGdiExcludeClipRect 5
+NtGdiExtCreatePen 11
+NtGdiExtCreateRegion 3
+NtGdiExtEscape 8
+NtGdiExtFloodFill 5
+NtGdiExtGetObjectW 3
+NtGdiExtSelectClipRgn 3
+NtGdiExtTextOutW 9
+NtGdiFillPath 1
+NtGdiFillRgn 3
+NtGdiFlattenPath 1
+NtGdiFlush 0
+NtGdiForceUFIMapping 2
+NtGdiFrameRgn 5
+NtGdiFullscreenControl 5
+NtGdiGetAndSetDCDword 4
+NtGdiGetAppClipBox 2
+NtGdiGetBitmapBits 3
+NtGdiGetBitmapDimension 2
+NtGdiGetBoundsRect 3
+NtGdiGetCertificate 4
+NtGdiGetCertificateSize 3
+NtGdiGetCharABCWidthsW 6
+NtGdiGetCharacterPlacementW 6
+NtGdiGetCharSet 1
+NtGdiGetCharWidthW 6
+NtGdiGetCharWidthInfo 2
+NtGdiGetColorAdjustment 2
+NtGdiGetColorSpaceforBitmap 1
+NtGdiGetCOPPCompatibleOPMInformation 3
+NtGdiGetDCDword 3
+NtGdiGetDCforBitmap 1
+NtGdiGetDCObject 2
+NtGdiGetDCPoint 3
+NtGdiGetDeviceCaps 2
+NtGdiGetDeviceGammaRamp 2
+NtGdiGetDeviceCapsAll 2
+NtGdiGetDIBitsInternal 9
+NtGdiGetETM 2
+NtGdiGetEudcTimeStampEx 3
+NtGdiGetFontData 5
+NtGdiGetFontResourceInfoInternalW 7
+NtGdiGetGlyphIndicesW 5
+NtGdiGetGlyphIndicesWInternal 6
+NtGdiGetGlyphOutline 8
+NtGdiGetOPMInformation 3
+NtGdiGetKerningPairs 3
+NtGdiGetLinkedUFIs 3
+NtGdiGetMiterLimit 2
+NtGdiGetMonitorID 3
+NtGdiGetNearestColor 2
+NtGdiGetNearestPaletteIndex 2
+NtGdiGetObjectBitmapHandle 2
+NtGdiGetOPMRandomNumber 2
+NtGdiGetOutlineTextMetricsInternalW 4
+NtGdiGetPath 4
+NtGdiGetPixel 3
+NtGdiGetRandomRgn 3
+NtGdiGetRasterizerCaps 2
+NtGdiGetRealizationInfo 3
+NtGdiGetRegionData 3
+NtGdiGetRgnBox 2
+NtGdiGetServerMetaFileBits 7
+NtGdiGetSpoolMessage 4
+NtGdiGetStats 5
+NtGdiGetStockObject 1
+NtGdiGetStringBitmapW 5
+NtGdiGetSuggestedOPMProtectedOutputArraySize 2
+NtGdiGetSystemPaletteUse 1
+NtGdiGetTextCharsetInfo 3
+NtGdiGetTextExtent 5
+NtGdiGetTextExtentExW 8
+NtGdiGetTextFaceW 4
+NtGdiGetTextMetricsW 3
+NtGdiGetTransform 3
+NtGdiGetUFI 6
+NtGdiGetEmbUFI 7
+NtGdiGetUFIPathname 10
+NtGdiGetEmbedFonts 0
+NtGdiChangeGhostFont 2
+NtGdiAddEmbFontToDC 2
+NtGdiGetFontUnicodeRanges 2
+NtGdiGetWidthTable 7
+NtGdiGradientFill 6
+NtGdiHfontCreate 5
+NtGdiIcmBrushInfo 8
+NtGdiInit 0
+NtGdiInitSpool 0
+NtGdiIntersectClipRect 5
+NtGdiInvertRgn 2
+NtGdiLineTo 3
+NtGdiMakeFontDir 5
+NtGdiMakeInfoDC 2
+NtGdiMaskBlt 13
+NtGdiModifyWorldTransform 3
+NtGdiMonoBitmap 1
+NtGdiMoveTo 4
+NtGdiOffsetClipRgn 3
+NtGdiOffsetRgn 3
+NtGdiOpenDCW 8
+NtGdiPatBlt 6
+NtGdiPolyPatBlt 5
+NtGdiPathToRegion 1
+NtGdiPlgBlt 11
+NtGdiPolyDraw 4
+NtGdiPolyPolyDraw 5
+NtGdiPolyTextOutW 4
+NtGdiPtInRegion 3
+NtGdiPtVisible 3
+NtGdiQueryFonts 3
+NtGdiQueryFontAssocInfo 1
+NtGdiRectangle 5
+NtGdiRectInRegion 2
+NtGdiRectVisible 2
+NtGdiRemoveFontResourceW 6
+NtGdiRemoveFontMemResourceEx 1
+NtGdiResetDC 5
+NtGdiResizePalette 2
+NtGdiRestoreDC 2
+NtGdiRoundRect 7
+NtGdiSaveDC 1
+NtGdiScaleViewportExtEx 6
+NtGdiScaleWindowExtEx 6
+NtGdiSelectBitmap 2
+NtGdiSelectBrush 2
+NtGdiSelectClipPath 2
+NtGdiSelectFont 2
+NtGdiSelectPen 2
+NtGdiSetBitmapAttributes 2
+NtGdiSetBitmapBits 3
+NtGdiSetBitmapDimension 4
+NtGdiSetBoundsRect 3
+NtGdiSetBrushAttributes 2
+NtGdiSetBrushOrg 4
+NtGdiSetColorAdjustment 2
+NtGdiSetColorSpace 2
+NtGdiSetDeviceGammaRamp 2
+NtGdiSetDIBitsToDeviceInternal 16
+NtGdiSetFontEnumeration 1
+NtGdiSetFontXform 3
+NtGdiSetIcmMode 3
+NtGdiSetLinkedUFIs 3
+NtGdiSetMagicColors 3
+NtGdiSetMetaRgn 1
+NtGdiSetMiterLimit 3
+NtGdiGetDeviceWidth 1
+NtGdiMirrorWindowOrg 1
+NtGdiSetLayout 3
+NtGdiSetOPMSigningKeyAndSequenceNumbers 2
+NtGdiSetPixel 4
+NtGdiSetPixelFormat 2
+NtGdiSetRectRgn 5
+NtGdiSetSystemPaletteUse 2
+NtGdiSetTextJustification 3
+NtGdiSetupPublicCFONT 3
+NtGdiSetVirtualResolution 5
+NtGdiSetSizeDevice 3
+NtGdiStartDoc 4
+NtGdiStartPage 1
+NtGdiStretchBlt 12
+NtGdiStretchDIBitsInternal 16
+NtGdiStrokeAndFillPath 1
+NtGdiStrokePath 1
+NtGdiSwapBuffers 1
+NtGdiTransformPoints 5
+NtGdiTransparentBlt 11
+NtGdiUnloadPrinterDriver 2
+NtGdiUnmapMemFont 1
+NtGdiUnrealizeObject 1
+NtGdiUpdateColors 1
+NtGdiWidenPath 1
+NtUserActivateKeyboardLayout 2
+NtUserAddClipboardFormatListener 1
+NtUserAlterWindowStyle 3
+NtUserAssociateInputContext 3
+NtUserAttachThreadInput 3
+NtUserBeginPaint 2
+NtUserBitBltSysBmp 8
+NtUserBlockInput 1
+NtUserBuildHimcList 4
+NtUserBuildHwndList 7
+NtUserBuildNameList 4
+NtUserBuildPropList 4
+NtUserCallHwnd 2
+NtUserCallHwndLock 2
+NtUserCallHwndOpt 2
+NtUserCallHwndParam 3
+NtUserCallHwndParamLock 3
+NtUserCallMsgFilter 2
+NtUserCallNextHookEx 4
+NtUserCallNoParam 1
+NtUserCallOneParam 2
+NtUserCallTwoParam 3
+NtUserChangeClipboardChain 2
+NtUserChangeDisplaySettings 4
+NtUserCheckAccessForIntegrityLevel 3
+NtUserCheckDesktopByThreadId 1
+NtUserCheckWindowThreadDesktop 3
+NtUserCheckImeHotKey 2
+NtUserCheckMenuItem 3
+NtUserChildWindowFromPointEx 4
+NtUserClipCursor 1
+NtUserCloseClipboard 0
+NtUserCloseDesktop 1
+NtUserCloseWindowStation 1
+NtUserConsoleControl 3
+NtUserConvertMemHandle 2
+NtUserCopyAcceleratorTable 3
+NtUserCountClipboardFormats 0
+NtUserCreateAcceleratorTable 2
+NtUserCreateCaret 4
+NtUserCreateDesktopEx 6
+NtUserCreateInputContext 1
+NtUserCreateLocalMemHandle 4
+NtUserCreateWindowEx 15
+NtUserCreateWindowStation 7
+NtUserDdeInitialize 5
+NtUserDeferWindowPos 8
+NtUserDefSetText 2
+NtUserDeleteMenu 3
+NtUserDestroyAcceleratorTable 1
+NtUserDestroyCursor 2
+NtUserDestroyInputContext 1
+NtUserDestroyMenu 1
+NtUserDestroyWindow 1
+NtUserDisableThreadIme 1
+NtUserDispatchMessage 1
+NtUserDoSoundConnect 0
+NtUserDoSoundDisconnect 0
+NtUserDragDetect 3
+NtUserDragObject 5
+NtUserDrawAnimatedRects 4
+NtUserDrawCaption 4
+NtUserDrawCaptionTemp 7
+NtUserDrawIconEx 11
+NtUserDrawMenuBarTemp 5
+NtUserEmptyClipboard 0
+NtUserEnableMenuItem 3
+NtUserEnableScrollBar 3
+NtUserEndDeferWindowPosEx 2
+NtUserEndMenu 0
+NtUserEndPaint 2
+NtUserEnumDisplayDevices 4
+NtUserEnumDisplayMonitors 4
+NtUserEnumDisplaySettings 4
+NtUserEvent 1
+NtUserExcludeUpdateRgn 2
+NtUserFillWindow 4
+NtUserFindExistingCursorIcon 3
+NtUserFindWindowEx 5
+NtUserFlashWindowEx 1
+NtUserFrostCrashedWindow 2
+NtUserGetAltTabInfo 6
+NtUserGetAncestor 2
+NtUserGetAppImeLevel 1
+NtUserGetAsyncKeyState 1
+NtUserGetAtomName 2
+NtUserGetCaretBlinkTime 0
+NtUserGetCaretPos 1
+NtUserGetClassInfoEx 5
+NtUserGetClassName 3
+NtUserGetClipboardData 2
+NtUserGetClipboardFormatName 3
+NtUserGetClipboardOwner 0
+NtUserGetClipboardSequenceNumber 0
+NtUserGetClipboardViewer 0
+NtUserGetClipCursor 1
+NtUserGetComboBoxInfo 2
+NtUserGetControlBrush 3
+NtUserGetControlColor 4
+NtUserGetCPD 3
+NtUserGetCursorFrameInfo 4
+NtUserGetCursorInfo 1
+NtUserGetDC 1
+NtUserGetDCEx 3
+NtUserGetDoubleClickTime 0
+NtUserGetForegroundWindow 0
+NtUserGetGuiResources 2
+NtUserGetGUIThreadInfo 2
+NtUserGetIconInfo 6
+NtUserGetIconSize 4
+NtUserGetImeHotKey 4
+NtUserGetImeInfoEx 2
+NtUserGetInternalWindowPos 3
+NtUserGetKeyboardLayoutList 2
+NtUserGetKeyboardLayoutName 1
+NtUserGetKeyboardState 1
+NtUserGetKeyNameText 3
+NtUserGetKeyState 1
+NtUserGetListBoxInfo 1
+NtUserGetMenuBarInfo 4
+NtUserGetMenuIndex 2
+NtUserGetMenuItemRect 4
+NtUserGetMessage 4
+NtUserGetMouseMovePointsEx 5
+NtUserGetObjectInformation 5
+NtUserGetOpenClipboardWindow 0
+NtUserGetPriorityClipboardFormat 2
+NtUserGetProcessWindowStation 0
+NtUserGetRawInputBuffer 3
+NtUserGetRawInputData 5
+NtUserGetRawInputDeviceInfo 4
+NtUserGetRawInputDeviceList 3
+NtUserGetRegisteredRawInputDevices 3
+NtUserGetScrollBarInfo 3
+NtUserGetSystemMenu 2
+NtUserGetThreadDesktop 2
+NtUserGetThreadState 1
+NtUserGetTitleBarInfo 2
+NtUserGetUpdatedClipboardFormats 3
+NtUserGetUpdateRect 3
+NtUserGetUpdateRgn 3
+NtUserGetWindowDC 1
+NtUserGetWindowPlacement 2
+NtUserGetWOWClass 2
+NtUserGhostWindowFromHungWindow 1
+NtUserHardErrorControl 3
+NtUserHideCaret 1
+NtUserHiliteMenuItem 4
+NtUserHungWindowFromGhostWindow 1
+NtUserImpersonateDdeClientWindow 2
+NtUserInitialize 2
+NtUserInitializeClientPfnArrays 4
+NtUserInitTask 12
+NtUserInternalGetWindowText 3
+NtUserInternalGetWindowIcon 2
+NtUserInvalidateRect 3
+NtUserInvalidateRgn 3
+NtUserIsClipboardFormatAvailable 1
+NtUserKillTimer 2
+NtUserLoadKeyboardLayoutEx 7
+NtUserLockWindowStation 1
+NtUserLockWindowUpdate 1
+NtUserLockWorkStation 0
+NtUserLogicalToPhysicalPoint 2
+NtUserMapVirtualKeyEx 4
+NtUserMenuItemFromPoint 4
+NtUserMessageCall 7
+NtUserMinMaximize 3
+NtUserMNDragLeave 0
+NtUserMNDragOver 2
+NtUserModifyUserStartupInfoFlags 2
+NtUserMoveWindow 6
+NtUserNotifyIMEStatus 3
+NtUserNotifyProcessCreate 4
+NtUserNotifyWinEvent 4
+NtUserOpenClipboard 2
+NtUserOpenDesktop 3
+NtUserOpenInputDesktop 3
+NtUserOpenThreadDesktop 5
+NtUserOpenWindowStation 2
+NtUserPaintDesktop 1
+NtUserPaintMonitor 3
+NtUserPeekMessage 5
+NtUserPhysicalToLogicalPoint 2
+NtUserPostMessage 4
+NtUserPostThreadMessage 4
+NtUserPrintWindow 3
+NtUserProcessConnect 2
+NtUserQueryInformationThread 4
+NtUserQueryInputContext 2
+NtUserQuerySendMessage 1
+NtUserQueryWindow 2
+NtUserRealChildWindowFromPoint 3
+NtUserRealInternalGetMessage 6
+NtUserRealWaitMessageEx 2
+NtUserRedrawWindow 4
+NtUserRegisterClassExWOW 7
+NtUserRegisterErrorReportingDialog 2
+NtUserRegisterUserApiHook 4
+NtUserRegisterHotKey 4
+NtUserRegisterRawInputDevices 3
+NtUserRegisterTasklist 1
+NtUserRegisterWindowMessage 1
+NtUserRemoveClipboardFormatListener 1
+NtUserRemoveMenu 3
+NtUserRemoveProp 2
+NtUserResolveDesktop 4
+NtUserResolveDesktopForWOW 1
+NtUserSBGetParms 4
+NtUserScrollDC 7
+NtUserScrollWindowEx 8
+NtUserSelectPalette 3
+NtUserSendInput 3
+NtUserSetActiveWindow 1
+NtUserSetAppImeLevel 2
+NtUserSetCapture 1
+NtUserSetClassLong 4
+NtUserSetClassWord 3
+NtUserSetClipboardData 3
+NtUserSetClipboardViewer 1
+NtUserSetConsoleReserveKeys 2
+NtUserSetCursor 1
+NtUserSetCursorContents 2
+NtUserSetCursorIconData 4
+NtUserSetFocus 1
+NtUserSetImeHotKey 5
+NtUserSetImeInfoEx 1
+NtUserSetImeOwnerWindow 2
+NtUserSetInformationProcess 4
+NtUserSetInformationThread 4
+NtUserSetInternalWindowPos 4
+NtUserSetKeyboardState 1
+NtUserSetMenu 3
+NtUserSetMenuContextHelpId 2
+NtUserSetMenuDefaultItem 3
+NtUserSetMenuFlagRtoL 1
+NtUserSetObjectInformation 4
+NtUserSetParent 2
+NtUserSetProcessWindowStation 1
+NtUserGetProp 2
+NtUserSetProp 3
+NtUserSetScrollInfo 4
+NtUserSetShellWindowEx 2
+NtUserSetSysColors 4
+NtUserSetSystemCursor 2
+NtUserSetSystemMenu 2
+NtUserSetSystemTimer 3
+NtUserSetThreadDesktop 1
+NtUserSetThreadLayoutHandles 2
+NtUserSetThreadState 2
+NtUserSetTimer 4
+NtUserSetProcessDPIAware 0
+NtUserSetWindowFNID 2
+NtUserSetWindowLong 4
+NtUserSetWindowPlacement 2
+NtUserSetWindowPos 7
+NtUserSetWindowRgn 3
+NtUserGetWindowRgnEx 3
+NtUserSetWindowRgnEx 3
+NtUserSetWindowsHookAW 3
+NtUserSetWindowsHookEx 6
+NtUserSetWindowStationUser 4
+NtUserSetWindowWord 3
+NtUserSetWinEventHook 8
+NtUserShowCaret 1
+NtUserShowScrollBar 3
+NtUserShowWindow 2
+NtUserShowWindowAsync 2
+NtUserSoundSentry 0
+NtUserSwitchDesktop 2
+NtUserSystemParametersInfo 4
+NtUserTestForInteractiveUser 1
+NtUserThunkedMenuInfo 2
+NtUserThunkedMenuItemInfo 6
+NtUserToUnicodeEx 7
+NtUserTrackMouseEvent 1
+NtUserTrackPopupMenuEx 6
+NtUserCalcMenuBar 5
+NtUserPaintMenuBar 6
+NtUserTranslateAccelerator 3
+NtUserTranslateMessage 2
+NtUserUnhookWindowsHookEx 1
+NtUserUnhookWinEvent 1
+NtUserUnloadKeyboardLayout 1
+NtUserUnlockWindowStation 1
+NtUserUnregisterClass 3
+NtUserUnregisterUserApiHook 0
+NtUserUnregisterHotKey 2
+NtUserUpdateInputContext 3
+NtUserUpdateInstance 3
+NtUserUpdateLayeredWindow 10
+NtUserGetLayeredWindowAttributes 4
+NtUserSetLayeredWindowAttributes 4
+NtUserUpdatePerUserSystemParameters 1
+NtUserUserHandleGrantAccess 3
+NtUserValidateHandleSecure 1
+NtUserValidateRect 2
+NtUserValidateTimerCallback 1
+NtUserVkKeyScanEx 3
+NtUserWaitForInputIdle 3
+NtUserWaitForMsgAndEvent 1
+NtUserWaitMessage 0
+NtUserWin32PoolAllocationStats 6
+NtUserWindowFromPhysicalPoint 2
+NtUserWindowFromPoint 2
+NtUserYieldTask 0
+NtUserRemoteConnect 3
+NtUserRemoteRedrawRectangle 4
+NtUserRemoteRedrawScreen 0
+NtUserRemoteStopScreenUpdates 0
+NtUserCtxDisplayIOCtl 3
+NtUserRegisterSessionPort 1
+NtUserUnregisterSessionPort 0
+NtUserUpdateWindowTransform 3
+NtUserDwmStartRedirection 1
+NtUserDwmStopRedirection 0
+NtUserDwmHintDxUpdate 2
+NtUserDwmGetDxRgn 3
+NtUserGetWindowMinimizeRect 2
+NtGdiEngAssociateSurface 3
+NtGdiEngCreateBitmap 6
+NtGdiEngCreateDeviceSurface 4
+NtGdiEngCreateDeviceBitmap 4
+NtGdiEngCreatePalette 6
+NtGdiEngComputeGlyphSet 3
+NtGdiEngCopyBits 6
+NtGdiEngDeletePalette 1
+NtGdiEngDeleteSurface 1
+NtGdiEngEraseSurface 3
+NtGdiEngUnlockSurface 1
+NtGdiEngLockSurface 1
+NtGdiEngBitBlt 11
+NtGdiEngStretchBlt 11
+NtGdiEngPlgBlt 11
+NtGdiEngMarkBandingSurface 1
+NtGdiEngStrokePath 8
+NtGdiEngFillPath 7
+NtGdiEngStrokeAndFillPath 10
+NtGdiEngPaint 5
+NtGdiEngLineTo 9
+NtGdiEngAlphaBlend 7
+NtGdiEngGradientFill 10
+NtGdiEngTransparentBlt 8
+NtGdiEngTextOut 10
+NtGdiEngStretchBltROP 13
+NtGdiXLATEOBJ_cGetPalette 4
+NtGdiXLATEOBJ_iXlate 2
+NtGdiXLATEOBJ_hGetColorTransform 1
+NtGdiCLIPOBJ_bEnum 3
+NtGdiCLIPOBJ_cEnumStart 5
+NtGdiCLIPOBJ_ppoGetPath 1
+NtGdiEngDeletePath 1
+NtGdiEngCreateClip 0
+NtGdiEngDeleteClip 1
+NtGdiBRUSHOBJ_ulGetBrushColor 1
+NtGdiBRUSHOBJ_pvAllocRbrush 2
+NtGdiBRUSHOBJ_pvGetRbrush 1
+NtGdiBRUSHOBJ_hGetColorTransform 1
+NtGdiXFORMOBJ_bApplyXform 5
+NtGdiXFORMOBJ_iGetXform 2
+NtGdiFONTOBJ_vGetInfo 3
+NtGdiFONTOBJ_pxoGetXform 1
+NtGdiFONTOBJ_cGetGlyphs 5
+NtGdiFONTOBJ_pifi 1
+NtGdiFONTOBJ_pfdg 1
+NtGdiFONTOBJ_pQueryGlyphAttrs 2
+NtGdiFONTOBJ_pvTrueTypeFontFile 2
+NtGdiFONTOBJ_cGetAllGlyphHandles 2
+NtGdiSTROBJ_bEnum 3
+NtGdiSTROBJ_bEnumPositionsOnly 3
+NtGdiSTROBJ_bGetAdvanceWidths 4
+NtGdiSTROBJ_vEnumStart 1
+NtGdiSTROBJ_dwGetCodePage 1
+NtGdiPATHOBJ_vGetBounds 2
+NtGdiPATHOBJ_bEnum 2
+NtGdiPATHOBJ_vEnumStart 1
+NtGdiPATHOBJ_vEnumStartClipLines 4
+NtGdiPATHOBJ_bEnumClipLines 3
+NtGdiGetDhpdev 1
+NtGdiEngCheckAbort 1
+NtGdiHT_Get8BPPFormatPalette 4
+NtGdiHT_Get8BPPMaskPalette 6
+NtGdiUpdateTransform 1
+NtGdiSetPUMPDOBJ 4
+NtGdiBRUSHOBJ_DeleteRbrush 2
+NtGdiUMPDEngFreeUserMem 1
+NtGdiDrawStream 3
+NtGdiDwmGetDirtyRgn 5
+NtGdiDwmGetSurfaceData 2
+NtGdiDdDDICreateAllocation 1
+NtGdiDdDDIQueryResourceInfo 1
+NtGdiDdDDIOpenResource 1
+NtGdiDdDDIDestroyAllocation 1
+NtGdiDdDDISetAllocationPriority 1
+NtGdiDdDDIQueryAllocationResidency 1
+NtGdiDdDDICreateDevice 1
+NtGdiDdDDIDestroyDevice 1
+NtGdiDdDDICreateContext 1
+NtGdiDdDDIDestroyContext 1
+NtGdiDdDDICreateSynchronizationObject 1
+NtGdiDdDDIDestroySynchronizationObject 1
+NtGdiDdDDIWaitForSynchronizationObject 1
+NtGdiDdDDISignalSynchronizationObject 1
+NtGdiDdDDIGetRuntimeData 1
+NtGdiDdDDIQueryAdapterInfo 1
+NtGdiDdDDILock 1
+NtGdiDdDDIUnlock 1
+NtGdiDdDDIGetDisplayModeList 1
+NtGdiDdDDISetDisplayMode 1
+NtGdiDdDDIGetMultisampleMethodList 1
+NtGdiDdDDIPresent 1
+NtGdiDdDDIRender 1
+NtGdiDdDDIOpenAdapterFromDeviceName 1
+NtGdiDdDDIOpenAdapterFromHdc 1
+NtGdiDdDDICloseAdapter 1
+NtGdiDdDDIGetSharedPrimaryHandle 1
+NtGdiDdDDIEscape 1
+NtGdiDdDDIQueryStatistics 1
+NtGdiDdDDISetVidPnSourceOwner 1
+NtGdiDdDDIGetPresentHistory 1
+NtGdiDdDDICreateOverlay 1
+NtGdiDdDDIUpdateOverlay 1
+NtGdiDdDDIFlipOverlay 1
+NtGdiDdDDIDestroyOverlay 1
+NtGdiDdDDIWaitForVerticalBlankEvent 1
+NtGdiDdDDISetGammaRamp 1
+NtGdiDdDDIGetDeviceState 1
+NtGdiDdDDICreateDCFromMemory 1
+NtGdiDdDDIDestroyDCFromMemory 1
+NtGdiDdDDISetContextSchedulingPriority 1
+NtGdiDdDDIGetContextSchedulingPriority 1
+NtGdiDdDDISetProcessSchedulingPriorityClass 2
+NtGdiDdDDIGetProcessSchedulingPriorityClass 2
+NtGdiDdDDIReleaseProcessVidPnSourceOwners 1
+NtGdiDdDDIGetScanLine 1
+NtGdiDdDDISetQueuedLimit 1
+NtGdiDdDDIPollDisplayChildren 1
+NtGdiDdDDIInvalidateActiveVidPn 1
+NtGdiDdDDICheckOcclusion 1
+NtGdiDdDDIWaitForIdle 1
+NtGdiDdDDICheckMonitorPowerState 1
+NtGdiDdDDICheckExclusiveOwnership 0
+NtGdiDdDDISetDisplayPrivateDriverFormat 1
+NtGdiDdDDISharedPrimaryLockNotification 1
+NtGdiDdDDISharedPrimaryUnLockNotification 1
+NtGdiMakeObjectXferable 2
+NtGdiMakeObjectUnXferable 1
+NtGdiGetNumberOfPhysicalMonitors 2
+NtGdiGetPhysicalMonitors 4
+NtGdiGetPhysicalMonitorDescription 3
+NtGdiDestroyPhysicalMonitor 1
+NtGdiDDCCIGetVCPFeature 5
+NtGdiDDCCISetVCPFeature 3
+NtGdiDDCCISaveCurrentSettings 1
+NtGdiDDCCIGetCapabilitiesStringLength 2
+NtGdiDDCCIGetCapabilitiesString 3
+NtGdiDDCCIGetTimingReport 2
+NtUserSetMirrorRendering 2
+NtUserShowSystemCursor 1
diff --git a/rostests/apitests/w32kdll/w32kdll_xpsp2/w32k_xpsp2-x86.db b/rostests/apitests/w32kdll/w32kdll_xpsp2/w32k_xpsp2-x86.db
new file mode 100644
index 00000000000..7db341886d9
--- /dev/null
+++ b/rostests/apitests/w32kdll/w32kdll_xpsp2/w32k_xpsp2-x86.db
@@ -0,0 +1,670 @@
+#
+# win32k systemcalls taken from Windows XP SP2 x86
+#
+NtGdiAbortDoc 1
+NtGdiAbortPath 1
+NtGdiAddFontResourceW 6
+NtGdiAddRemoteFontToDC 4
+NtGdiAddFontMemResourceEx 5
+NtGdiRemoveMergeFont 2
+NtGdiAddRemoteMMInstanceToDC 3
+NtGdiAlphaBlend 12
+NtGdiAngleArc 6
+NtGdiAnyLinkedFonts 0
+NtGdiFontIsLinked 1
+NtGdiArcInternal 10
+NtGdiBeginPath 1
+NtGdiBitBlt 11
+NtGdiCancelDC 1
+NtGdiCheckBitmapBits 8
+NtGdiCloseFigure 1
+NtGdiClearBitmapAttributes 2
+NtGdiClearBrushAttributes 2
+NtGdiColorCorrectPalette 6
+NtGdiCombineRgn 4
+NtGdiCombineTransform 3
+NtGdiComputeXformCoefficients 1
+NtGdiConsoleTextOut 4
+NtGdiConvertMetafileRect 2
+NtGdiCreateBitmap 5
+NtGdiCreateClientObj 1
+NtGdiCreateColorSpace 1
+NtGdiCreateColorTransform 8
+NtGdiCreateCompatibleBitmap 3
+NtGdiCreateCompatibleDC 1
+NtGdiCreateDIBBrush 6
+NtGdiCreateDIBitmapInternal 11
+NtGdiCreateDIBSection 9
+NtGdiCreateEllipticRgn 4
+NtGdiCreateHalftonePalette 1
+NtGdiCreateHatchBrushInternal 3
+NtGdiCreateMetafileDC 1
+NtGdiCreatePaletteInternal 2
+NtGdiCreatePatternBrushInternal 3
+NtGdiCreatePen 4
+NtGdiCreateRectRgn 4
+NtGdiCreateRoundRectRgn 6
+NtGdiCreateServerMetaFile 6
+NtGdiCreateSolidBrush 2
+NtGdiD3dContextCreate 4
+NtGdiD3dContextDestroy 1
+NtGdiD3dContextDestroyAll 1
+NtGdiD3dValidateTextureStageState 1
+NtGdiD3dDrawPrimitives2 7
+NtGdiDdGetDriverState 1
+NtGdiDdAddAttachedSurface 3
+NtGdiDdAlphaBlt 3
+NtGdiDdAttachSurface 2
+NtGdiDdBeginMoCompFrame 2
+NtGdiDdBlt 3
+NtGdiDdCanCreateSurface 2
+NtGdiDdCanCreateD3DBuffer 2
+NtGdiDdColorControl 2
+NtGdiDdCreateDirectDrawObject 1
+NtGdiDdCreateSurface 8
+NtGdiDdCreateD3DBuffer 8
+NtGdiDdCreateMoComp 2
+NtGdiDdCreateSurfaceObject 6
+NtGdiDdDeleteDirectDrawObject 1
+NtGdiDdDeleteSurfaceObject 1
+NtGdiDdDestroyMoComp 2
+NtGdiDdDestroySurface 2
+NtGdiDdDestroyD3DBuffer 1
+NtGdiDdEndMoCompFrame 2
+NtGdiDdFlip 5
+NtGdiDdFlipToGDISurface 2
+NtGdiDdGetAvailDriverMemory 2
+NtGdiDdGetBltStatus 2
+NtGdiDdGetDC 2
+NtGdiDdGetDriverInfo 2
+NtGdiDdGetDxHandle 3
+NtGdiDdGetFlipStatus 2
+NtGdiDdGetInternalMoCompInfo 2
+NtGdiDdGetMoCompBuffInfo 2
+NtGdiDdGetMoCompGuids 2
+NtGdiDdGetMoCompFormats 2
+NtGdiDdGetScanLine 2
+NtGdiDdLock 3
+NtGdiDdLockD3D 2
+NtGdiDdQueryDirectDrawObject 11
+NtGdiDdQueryMoCompStatus 2
+NtGdiDdReenableDirectDrawObject 2
+NtGdiDdReleaseDC 1
+NtGdiDdRenderMoComp 2
+NtGdiDdResetVisrgn 2
+NtGdiDdSetColorKey 2
+NtGdiDdSetExclusiveMode 2
+NtGdiDdSetGammaRamp 3
+NtGdiDdCreateSurfaceEx 3
+NtGdiDdSetOverlayPosition 3
+NtGdiDdUnattachSurface 2
+NtGdiDdUnlock 2
+NtGdiDdUnlockD3D 2
+NtGdiDdUpdateOverlay 3
+NtGdiDdWaitForVerticalBlank 2
+NtGdiDvpCanCreateVideoPort 2
+NtGdiDvpColorControl 2
+NtGdiDvpCreateVideoPort 2
+NtGdiDvpDestroyVideoPort 2
+NtGdiDvpFlipVideoPort 4
+NtGdiDvpGetVideoPortBandwidth 2
+NtGdiDvpGetVideoPortField 2
+NtGdiDvpGetVideoPortFlipStatus 2
+NtGdiDvpGetVideoPortInputFormats 2
+NtGdiDvpGetVideoPortLine 2
+NtGdiDvpGetVideoPortOutputFormats 2
+NtGdiDvpGetVideoPortConnectInfo 2
+NtGdiDvpGetVideoSignalStatus 2
+NtGdiDvpUpdateVideoPort 4
+NtGdiDvpWaitForVideoPortSync 2
+NtGdiDvpAcquireNotification 3
+NtGdiDvpReleaseNotification 2
+NtGdiDxgGenericThunk 6
+NtGdiDeleteClientObj 1
+NtGdiDeleteColorSpace 1
+NtGdiDeleteColorTransform 2
+NtGdiDeleteObjectApp 1
+NtGdiDescribePixelFormat 4
+NtGdiGetPerBandInfo 2
+NtGdiDoBanding 4
+NtGdiDoPalette 6
+NtGdiDrawEscape 4
+NtGdiEllipse 5
+NtGdiEnableEUDC 1
+NtGdiEndDoc 1
+NtGdiEndPage 1
+NtGdiEndPath 1
+NtGdiEnumFontChunk 5
+NtGdiEnumFontClose 1
+NtGdiEnumFontOpen 7
+NtGdiEnumObjects 4
+NtGdiEqualRgn 2
+NtGdiEudcLoadUnloadLink 7
+NtGdiExcludeClipRect 5
+NtGdiExtCreatePen 11
+NtGdiExtCreateRegion 3
+NtGdiExtEscape 8
+NtGdiExtFloodFill 5
+NtGdiExtGetObjectW 3
+NtGdiExtSelectClipRgn 3
+NtGdiExtTextOutW 9
+NtGdiFillPath 1
+NtGdiFillRgn 3
+NtGdiFlattenPath 1
+NtGdiFlushUserBatch 0
+NtGdiFlush 0
+NtGdiForceUFIMapping 2
+NtGdiFrameRgn 5
+NtGdiFullscreenControl 5
+NtGdiGetAndSetDCDword 4
+NtGdiGetAppClipBox 2
+NtGdiGetBitmapBits 3
+NtGdiGetBitmapDimension 2
+NtGdiGetBoundsRect 3
+NtGdiGetCharABCWidthsW 6
+NtGdiGetCharacterPlacementW 6
+NtGdiGetCharSet 1
+NtGdiGetCharWidthW 6
+NtGdiGetCharWidthInfo 2
+NtGdiGetColorAdjustment 2
+NtGdiGetColorSpaceforBitmap 1
+NtGdiGetDCDword 3
+NtGdiGetDCforBitmap 1
+NtGdiGetDCObject 2
+NtGdiGetDCPoint 3
+NtGdiGetDeviceCaps 2
+NtGdiGetDeviceGammaRamp 2
+NtGdiGetDeviceCapsAll 2
+NtGdiGetDIBitsInternal 9
+NtGdiGetETM 2
+NtGdiGetEudcTimeStampEx 3
+NtGdiGetFontData 5
+NtGdiGetFontResourceInfoInternalW 7
+NtGdiGetGlyphIndicesW 5
+NtGdiGetGlyphIndicesWInternal 6
+NtGdiGetGlyphOutline 8
+NtGdiGetKerningPairs 3
+NtGdiGetLinkedUFIs 3
+NtGdiGetMiterLimit 2
+NtGdiGetMonitorID 3
+NtGdiGetNearestColor 2
+NtGdiGetNearestPaletteIndex 2
+NtGdiGetObjectBitmapHandle 2
+NtGdiGetOutlineTextMetricsInternalW 4
+NtGdiGetPath 4
+NtGdiGetPixel 3
+NtGdiGetRandomRgn 3
+NtGdiGetRasterizerCaps 2
+NtGdiGetRealizationInfo 3
+NtGdiGetRegionData 3
+NtGdiGetRgnBox 2
+NtGdiGetServerMetaFileBits 7
+NtGdiGetSpoolMessage 4
+NtGdiGetStats 5
+NtGdiGetStockObject 1
+NtGdiGetStringBitmapW 5
+NtGdiGetSystemPaletteUse 1
+NtGdiGetTextCharsetInfo 3
+NtGdiGetTextExtent 5
+NtGdiGetTextExtentExW 8
+NtGdiGetTextFaceW 4
+NtGdiGetTextMetricsW 3
+NtGdiGetTransform 3
+NtGdiGetUFI 6
+NtGdiGetEmbUFI 7
+NtGdiGetUFIPathname 10
+NtGdiGetEmbedFonts 0
+NtGdiChangeGhostFont 2
+NtGdiAddEmbFontToDC 2
+NtGdiGetFontUnicodeRanges 2
+NtGdiGetWidthTable 7
+NtGdiGradientFill 6
+NtGdiHfontCreate 5
+NtGdiIcmBrushInfo 8
+NtGdiInit 0
+NtGdiInitSpool 0
+NtGdiIntersectClipRect 5
+NtGdiInvertRgn 2
+NtGdiLineTo 3
+NtGdiMakeFontDir 5
+NtGdiMakeInfoDC 2
+NtGdiMaskBlt 13
+NtGdiModifyWorldTransform 3
+NtGdiMonoBitmap 1
+NtGdiMoveTo 4
+NtGdiOffsetClipRgn 3
+NtGdiOffsetRgn 3
+NtGdiOpenDCW 7
+NtGdiPatBlt 6
+NtGdiPolyPatBlt 5
+NtGdiPathToRegion 1
+NtGdiPlgBlt 11
+NtGdiPolyDraw 4
+NtGdiPolyPolyDraw 5
+NtGdiPolyTextOutW 4
+NtGdiPtInRegion 3
+NtGdiPtVisible 3
+NtGdiQueryFonts 3
+NtGdiQueryFontAssocInfo 1
+NtGdiRectangle 5
+NtGdiRectInRegion 2
+NtGdiRectVisible 2
+NtGdiRemoveFontResourceW 6
+NtGdiRemoveFontMemResourceEx 1
+NtGdiResetDC 5
+NtGdiResizePalette 2
+NtGdiRestoreDC 2
+NtGdiRoundRect 7
+NtGdiSaveDC 1
+NtGdiScaleViewportExtEx 6
+NtGdiScaleWindowExtEx 6
+NtGdiSelectBitmap 2
+NtGdiSelectBrush 2
+NtGdiSelectClipPath 2
+NtGdiSelectFont 2
+NtGdiSelectPen 2
+NtGdiSetBitmapAttributes 2
+NtGdiSetBitmapBits 3
+NtGdiSetBitmapDimension 4
+NtGdiSetBoundsRect 3
+NtGdiSetBrushAttributes 2
+NtGdiSetBrushOrg 4
+NtGdiSetColorAdjustment 2
+NtGdiSetColorSpace 2
+NtGdiSetDeviceGammaRamp 2
+NtGdiSetDIBitsToDeviceInternal 16
+NtGdiSetFontEnumeration 1
+NtGdiSetFontXform 3
+NtGdiSetIcmMode 3
+NtGdiSetLinkedUFIs 3
+NtGdiSetMagicColors 3
+NtGdiSetMetaRgn 1
+NtGdiSetMiterLimit 3
+NtGdiGetDeviceWidth 1
+NtGdiMirrorWindowOrg 1
+NtGdiSetLayout 3
+NtGdiSetPixel 4
+NtGdiSetPixelFormat 2
+NtGdiSetRectRgn 5
+NtGdiSetSystemPaletteUse 2
+NtGdiSetTextJustification 3
+NtGdiSetupPublicCFONT 3
+NtGdiSetVirtualResolution 5
+NtGdiSetSizeDevice 3
+NtGdiStartDoc 4
+NtGdiStartPage 1
+NtGdiStretchBlt 12
+NtGdiStretchDIBitsInternal 16
+NtGdiStrokeAndFillPath 1
+NtGdiStrokePath 1
+NtGdiSwapBuffers 1
+NtGdiTransformPoints 5
+NtGdiTransparentBlt 11
+NtGdiUnloadPrinterDriver 2
+NtGdiUnmapMemFont 1
+NtGdiUnrealizeObject 1
+NtGdiUpdateColors 1
+NtGdiWidenPath 1
+NtUserActivateKeyboardLayout 2
+NtUserAlterWindowStyle 3
+NtUserAssociateInputContext 3
+NtUserAttachThreadInput 3
+NtUserBeginPaint 2
+NtUserBitBltSysBmp 8
+NtUserBlockInput 1
+NtUserBuildHimcList 4
+NtUserBuildHwndList 7
+NtUserBuildNameList 4
+NtUserBuildPropList 4
+NtUserCallHwnd 2
+NtUserCallHwndLock 2
+NtUserCallHwndOpt 2
+NtUserCallHwndParam 3
+NtUserCallHwndParamLock 3
+NtUserCallMsgFilter 2
+NtUserCallNextHookEx 4
+NtUserCallNoParam 1
+NtUserCallOneParam 2
+NtUserCallTwoParam 3
+NtUserChangeClipboardChain 2
+NtUserChangeDisplaySettings 5
+NtUserCheckImeHotKey 2
+NtUserCheckMenuItem 3
+NtUserChildWindowFromPointEx 4
+NtUserClipCursor 1
+NtUserCloseClipboard 0
+NtUserCloseDesktop 1
+NtUserCloseWindowStation 1
+NtUserConsoleControl 3
+NtUserConvertMemHandle 2
+NtUserCopyAcceleratorTable 3
+NtUserCountClipboardFormats 0
+NtUserCreateAcceleratorTable 2
+NtUserCreateCaret 4
+NtUserCreateDesktop 5
+NtUserCreateInputContext 1
+NtUserCreateLocalMemHandle 4
+NtUserCreateWindowEx 15
+NtUserCreateWindowStation 7
+NtUserDdeGetQualityOfService 3
+NtUserDdeInitialize 5
+NtUserDdeSetQualityOfService 3
+NtUserDeferWindowPos 8
+NtUserDefSetText 2
+NtUserDeleteMenu 3
+NtUserDestroyAcceleratorTable 1
+NtUserDestroyCursor 2
+NtUserDestroyInputContext 1
+NtUserDestroyMenu 1
+NtUserDestroyWindow 1
+NtUserDisableThreadIme 1
+NtUserDispatchMessage 1
+NtUserDragDetect 3
+NtUserDragObject 5
+NtUserDrawAnimatedRects 4
+NtUserDrawCaption 4
+NtUserDrawCaptionTemp 7
+NtUserDrawIconEx 11
+NtUserDrawMenuBarTemp 5
+NtUserEmptyClipboard 0
+NtUserEnableMenuItem 3
+NtUserEnableScrollBar 3
+NtUserEndDeferWindowPosEx 2
+NtUserEndMenu 0
+NtUserEndPaint 2
+NtUserEnumDisplayDevices 4
+NtUserEnumDisplayMonitors 4
+NtUserEnumDisplaySettings 4
+NtUserEvent 1
+NtUserExcludeUpdateRgn 2
+NtUserFillWindow 4
+NtUserFindExistingCursorIcon 3
+NtUserFindWindowEx 5
+NtUserFlashWindowEx 1
+NtUserGetAltTabInfo 6
+NtUserGetAncestor 2
+NtUserGetAppImeLevel 1
+NtUserGetAsyncKeyState 1
+NtUserGetAtomName 2
+NtUserGetCaretBlinkTime 0
+NtUserGetCaretPos 1
+NtUserGetClassInfo 5
+NtUserGetClassName 3
+NtUserGetClipboardData 2
+NtUserGetClipboardFormatName 3
+NtUserGetClipboardOwner 0
+NtUserGetClipboardSequenceNumber 0
+NtUserGetClipboardViewer 0
+NtUserGetClipCursor 1
+NtUserGetComboBoxInfo 2
+NtUserGetControlBrush 3
+NtUserGetControlColor 4
+NtUserGetCPD 3
+NtUserGetCursorFrameInfo 4
+NtUserGetCursorInfo 1
+NtUserGetDC 1
+NtUserGetDCEx 3
+NtUserGetDoubleClickTime 0
+NtUserGetForegroundWindow 0
+NtUserGetGuiResources 2
+NtUserGetGUIThreadInfo 2
+NtUserGetIconInfo 6
+NtUserGetIconSize 4
+NtUserGetImeHotKey 4
+NtUserGetImeInfoEx 2
+NtUserGetInternalWindowPos 3
+NtUserGetKeyboardLayoutList 2
+NtUserGetKeyboardLayoutName 1
+NtUserGetKeyboardState 1
+NtUserGetKeyNameText 3
+NtUserGetKeyState 1
+NtUserGetListBoxInfo 1
+NtUserGetMenuBarInfo 4
+NtUserGetMenuIndex 2
+NtUserGetMenuItemRect 4
+NtUserGetMessage 4
+NtUserGetMouseMovePointsEx 5
+NtUserGetObjectInformation 5
+NtUserGetOpenClipboardWindow 0
+NtUserGetPriorityClipboardFormat 2
+NtUserGetProcessWindowStation 0
+NtUserGetRawInputBuffer 3
+NtUserGetRawInputData 5
+NtUserGetRawInputDeviceInfo 4
+NtUserGetRawInputDeviceList 3
+NtUserGetRegisteredRawInputDevices 3
+NtUserGetScrollBarInfo 3
+NtUserGetSystemMenu 2
+NtUserGetThreadDesktop 2
+NtUserGetThreadState 1
+NtUserGetTitleBarInfo 2
+NtUserGetUpdateRect 3
+NtUserGetUpdateRgn 3
+NtUserGetWindowDC 1
+NtUserGetWindowPlacement 2
+NtUserGetWOWClass 2
+NtUserHardErrorControl 3
+NtUserHideCaret 1
+NtUserHiliteMenuItem 4
+NtUserImpersonateDdeClientWindow 2
+NtUserInitialize 3
+NtUserInitializeClientPfnArrays 4
+NtUserInitTask 12
+NtUserInternalGetWindowText 3
+NtUserInvalidateRect 3
+NtUserInvalidateRgn 3
+NtUserIsClipboardFormatAvailable 1
+NtUserKillTimer 2
+NtUserLoadKeyboardLayoutEx 7
+NtUserLockWindowStation 1
+NtUserLockWindowUpdate 1
+NtUserLockWorkStation 0
+NtUserMapVirtualKeyEx 4
+NtUserMenuItemFromPoint 4
+NtUserMessageCall 7
+NtUserMinMaximize 3
+NtUserMNDragLeave 0
+NtUserMNDragOver 2
+NtUserModifyUserStartupInfoFlags 2
+NtUserMoveWindow 6
+NtUserNotifyIMEStatus 3
+NtUserNotifyProcessCreate 4
+NtUserNotifyWinEvent 4
+NtUserOpenClipboard 2
+NtUserOpenDesktop 3
+NtUserOpenInputDesktop 3
+NtUserOpenWindowStation 2
+NtUserPaintDesktop 1
+NtUserPeekMessage 5
+NtUserPostMessage 4
+NtUserPostThreadMessage 4
+NtUserPrintWindow 3
+NtUserProcessConnect 3
+NtUserQueryInformationThread 5
+NtUserQueryInputContext 2
+NtUserQuerySendMessage 1
+NtUserQueryUserCounters 5
+NtUserQueryWindow 2
+NtUserRealChildWindowFromPoint 3
+NtUserRealInternalGetMessage 6
+NtUserRealWaitMessageEx 2
+NtUserRedrawWindow 4
+NtUserRegisterClassExWOW 7
+NtUserRegisterUserApiHook 2
+NtUserRegisterHotKey 4
+NtUserRegisterRawInputDevices 3
+NtUserRegisterTasklist 1
+NtUserRegisterWindowMessage 1
+NtUserRemoveMenu 3
+NtUserRemoveProp 2
+NtUserResolveDesktop 4
+NtUserResolveDesktopForWOW 1
+NtUserSBGetParms 4
+NtUserScrollDC 7
+NtUserScrollWindowEx 8
+NtUserSelectPalette 3
+NtUserSendInput 3
+NtUserSetActiveWindow 1
+NtUserSetAppImeLevel 2
+NtUserSetCapture 1
+NtUserSetClassLong 4
+NtUserSetClassWord 3
+NtUserSetClipboardData 3
+NtUserSetClipboardViewer 1
+NtUserSetConsoleReserveKeys 2
+NtUserSetCursor 1
+NtUserSetCursorContents 2
+NtUserSetCursorIconData 4
+NtUserSetDbgTag 2
+NtUserSetFocus 1
+NtUserSetImeHotKey 5
+NtUserSetImeInfoEx 1
+NtUserSetImeOwnerWindow 2
+NtUserSetInformationProcess 4
+NtUserSetInformationThread 4
+NtUserSetInternalWindowPos 4
+NtUserSetKeyboardState 1
+NtUserSetLogonNotifyWindow 1
+NtUserSetMenu 3
+NtUserSetMenuContextHelpId 2
+NtUserSetMenuDefaultItem 3
+NtUserSetMenuFlagRtoL 1
+NtUserSetObjectInformation 4
+NtUserSetParent 2
+NtUserSetProcessWindowStation 1
+NtUserSetProp 3
+NtUserSetRipFlags 2
+NtUserSetScrollInfo 4
+NtUserSetShellWindowEx 2
+NtUserSetSysColors 4
+NtUserSetSystemCursor 2
+NtUserSetSystemMenu 2
+NtUserSetSystemTimer 4
+NtUserSetThreadDesktop 1
+NtUserSetThreadLayoutHandles 2
+NtUserSetThreadState 2
+NtUserSetTimer 4
+NtUserSetWindowFNID 2
+NtUserSetWindowLong 4
+NtUserSetWindowPlacement 2
+NtUserSetWindowPos 7
+NtUserSetWindowRgn 3
+NtUserSetWindowsHookAW 3
+NtUserSetWindowsHookEx 6
+NtUserSetWindowStationUser 4
+NtUserSetWindowWord 3
+NtUserSetWinEventHook 8
+NtUserShowCaret 1
+NtUserShowScrollBar 3
+NtUserShowWindow 2
+NtUserShowWindowAsync 2
+NtUserSoundSentry 0
+NtUserSwitchDesktop 1
+NtUserSystemParametersInfo 4
+NtUserTestForInteractiveUser 1
+NtUserThunkedMenuInfo 2
+NtUserThunkedMenuItemInfo 6
+NtUserToUnicodeEx 7
+NtUserTrackMouseEvent 1
+NtUserTrackPopupMenuEx 6
+NtUserCalcMenuBar 5
+NtUserPaintMenuBar 6
+NtUserTranslateAccelerator 3
+NtUserTranslateMessage 2
+NtUserUnhookWindowsHookEx 1
+NtUserUnhookWinEvent 1
+NtUserUnloadKeyboardLayout 1
+NtUserUnlockWindowStation 1
+NtUserUnregisterClass 3
+NtUserUnregisterUserApiHook 0
+NtUserUnregisterHotKey 2
+NtUserUpdateInputContext 3
+NtUserUpdateInstance 3
+NtUserUpdateLayeredWindow 9
+NtUserGetLayeredWindowAttributes 4
+NtUserSetLayeredWindowAttributes 4
+NtUserUpdatePerUserSystemParameters 2
+NtUserUserHandleGrantAccess 3
+NtUserValidateHandleSecure 1
+NtUserValidateRect 2
+NtUserValidateTimerCallback 3
+NtUserVkKeyScanEx 3
+NtUserWaitForInputIdle 3
+NtUserWaitForMsgAndEvent 1
+NtUserWaitMessage 0
+NtUserWin32PoolAllocationStats 6
+NtUserWindowFromPoint 2
+NtUserYieldTask 0
+NtUserRemoteConnect 3
+NtUserRemoteRedrawRectangle 4
+NtUserRemoteRedrawScreen 0
+NtUserRemoteStopScreenUpdates 0
+NtUserCtxDisplayIOCtl 3
+NtGdiEngAssociateSurface 3
+NtGdiEngCreateBitmap 6
+NtGdiEngCreateDeviceSurface 4
+NtGdiEngCreateDeviceBitmap 4
+NtGdiEngCreatePalette 6
+NtGdiEngComputeGlyphSet 3
+NtGdiEngCopyBits 6
+NtGdiEngDeletePalette 1
+NtGdiEngDeleteSurface 1
+NtGdiEngEraseSurface 3
+NtGdiEngUnlockSurface 1
+NtGdiEngLockSurface 1
+NtGdiEngBitBlt 11
+NtGdiEngStretchBlt 11
+NtGdiEngPlgBlt 11
+NtGdiEngMarkBandingSurface 1
+NtGdiEngStrokePath 8
+NtGdiEngFillPath 7
+NtGdiEngStrokeAndFillPath 10
+NtGdiEngPaint 5
+NtGdiEngLineTo 9
+NtGdiEngAlphaBlend 7
+NtGdiEngGradientFill 10
+NtGdiEngTransparentBlt 8
+NtGdiEngTextOut 10
+NtGdiEngStretchBltROP 13
+NtGdiXLATEOBJ_cGetPalette 4
+NtGdiXLATEOBJ_iXlate 2
+NtGdiXLATEOBJ_hGetColorTransform 1
+NtGdiCLIPOBJ_bEnum 3
+NtGdiCLIPOBJ_cEnumStart 5
+NtGdiCLIPOBJ_ppoGetPath 1
+NtGdiEngDeletePath 1
+NtGdiEngCreateClip 0
+NtGdiEngDeleteClip 1
+NtGdiBRUSHOBJ_ulGetBrushColor 1
+NtGdiBRUSHOBJ_pvAllocRbrush 2
+NtGdiBRUSHOBJ_pvGetRbrush 1
+NtGdiBRUSHOBJ_hGetColorTransform 1
+NtGdiXFORMOBJ_bApplyXform 5
+NtGdiXFORMOBJ_iGetXform 2
+NtGdiFONTOBJ_vGetInfo 3
+NtGdiFONTOBJ_pxoGetXform 1
+NtGdiFONTOBJ_cGetGlyphs 5
+NtGdiFONTOBJ_pifi 1
+NtGdiFONTOBJ_pfdg 1
+NtGdiFONTOBJ_pQueryGlyphAttrs 2
+NtGdiFONTOBJ_pvTrueTypeFontFile 2
+NtGdiFONTOBJ_cGetAllGlyphHandles 2
+NtGdiSTROBJ_bEnum 3
+NtGdiSTROBJ_bEnumPositionsOnly 3
+NtGdiSTROBJ_bGetAdvanceWidths 4
+NtGdiSTROBJ_vEnumStart 1
+NtGdiSTROBJ_dwGetCodePage 1
+NtGdiPATHOBJ_vGetBounds 2
+NtGdiPATHOBJ_bEnum 2
+NtGdiPATHOBJ_vEnumStart 1
+NtGdiPATHOBJ_vEnumStartClipLines 4
+NtGdiPATHOBJ_bEnumClipLines 3
+NtGdiGetDhpdev 1
+NtGdiEngCheckAbort 1
+NtGdiHT_Get8BPPFormatPalette 4
+NtGdiHT_Get8BPPMaskPalette 6
+NtGdiUpdateTransform 1
+NtGdiSetPUMPDOBJ 4
+NtGdiBRUSHOBJ_DeleteRbrush 2
+NtGdiUMPDEngFreeUserMem 1
+NtGdiDrawStream 3
diff --git a/rostests/tests/directory.rbuild b/rostests/tests/directory.rbuild
index 24c0acc688a..eea7f430d1f 100644
--- a/rostests/tests/directory.rbuild
+++ b/rostests/tests/directory.rbuild
@@ -139,6 +139,10 @@
+
+
+
+
diff --git a/rostests/tests/mmixer_test/mmixer_test.rbuild b/rostests/tests/mmixer_test/mmixer_test.rbuild
new file mode 100644
index 00000000000..5829887158a
--- /dev/null
+++ b/rostests/tests/mmixer_test/mmixer_test.rbuild
@@ -0,0 +1,13 @@
+
+
+
+ include/reactos/libs/sound
+
+ advapi32
+ setupapi
+ kernel32
+ winmm
+ mmixer
+ ksuser
+ test.c
+
\ No newline at end of file
diff --git a/rostests/tests/mmixer_test/test.c b/rostests/tests/mmixer_test/test.c
new file mode 100644
index 00000000000..907b035e41e
--- /dev/null
+++ b/rostests/tests/mmixer_test/test.c
@@ -0,0 +1,386 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "mmixer.h"
+
+MIXER_CONTEXT MixerContext;
+GUID CategoryGuid = {STATIC_KSCATEGORY_AUDIO};
+
+PVOID Alloc(ULONG NumBytes)
+{
+ //printf("Alloc: %lu\n", NumBytes);
+ return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, NumBytes);
+}
+
+MIXER_STATUS
+Close(HANDLE hDevice)
+{
+ //printf("Close: Handle %p\n", hDevice);
+ if (CloseHandle(hDevice))
+ return MM_STATUS_SUCCESS;
+ else
+ return MM_STATUS_UNSUCCESSFUL;
+}
+
+VOID
+Free(PVOID Block)
+{
+ //printf("Free: %p\n", Block);
+ HeapFree(GetProcessHeap(), 0, Block);
+}
+
+VOID
+Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
+{
+ //printf("Copy: Src %p Dst %p NumBytes %lu\n", Src, Dst, NumBytes);
+ CopyMemory(Src, Dst, NumBytes);
+}
+
+MIXER_STATUS
+Open(
+ IN LPWSTR DevicePath,
+ OUT PHANDLE hDevice)
+{
+ DevicePath[1] = L'\\';
+ *hDevice = CreateFileW(DevicePath,
+ GENERIC_READ | GENERIC_WRITE,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED,
+ NULL);
+ if (*hDevice == INVALID_HANDLE_VALUE)
+ {
+ //wprintf(L" Failed to open %s Error %lu\n", DevicePath, GetLastError());
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+ wprintf(L"Open: %s hDevice %p\n", DevicePath, *hDevice);
+
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+Control(
+ IN HANDLE hMixer,
+ IN ULONG dwIoControlCode,
+ IN PVOID lpInBuffer,
+ IN ULONG nInBufferSize,
+ OUT PVOID lpOutBuffer,
+ ULONG nOutBufferSize,
+ PULONG lpBytesReturned)
+{
+ OVERLAPPED Overlapped;
+ BOOLEAN IoResult;
+ DWORD Transferred = 0;
+
+ //printf("hMixer %p dwIoControlCode %lx lpInBuffer %p nInBufferSize %lu lpOutBuffer %p nOutBufferSize %lu lpBytesReturned %p\n",
+ // hMixer, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned);
+
+ /* Overlapped I/O is done here - this is used for waiting for completion */
+ ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
+ Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+
+ if ( ! Overlapped.hEvent )
+ return MM_STATUS_NO_MEMORY;
+
+ /* Talk to the device */
+ IoResult = DeviceIoControl(hMixer,
+ dwIoControlCode,
+ lpInBuffer,
+ nInBufferSize,
+ lpOutBuffer,
+ nOutBufferSize,
+ &Transferred,
+ &Overlapped);
+
+ /* If failure occurs, make sure it's not just due to the overlapped I/O */
+ if ( ! IoResult )
+ {
+ if ( GetLastError() != ERROR_IO_PENDING )
+ {
+ CloseHandle(Overlapped.hEvent);
+
+ //printf("Control: Failed with %lu Transferred %lu\n", GetLastError(), Transferred);
+
+ if (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ if ( lpBytesReturned )
+ *lpBytesReturned = Transferred;
+ return MM_STATUS_MORE_ENTRIES;
+ }
+
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+ }
+
+ /* Wait for the I/O to complete */
+ IoResult = GetOverlappedResult(hMixer,
+ &Overlapped,
+ &Transferred,
+ TRUE);
+
+ /* Don't need this any more */
+ CloseHandle(Overlapped.hEvent);
+
+ if ( ! IoResult )
+ return MM_STATUS_UNSUCCESSFUL;
+
+ //printf("Transferred %lu bytes in Sync overlapped I/O\n", Transferred);
+
+ if ( lpBytesReturned )
+ *lpBytesReturned = Transferred;
+
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+Enum(
+ IN PVOID EnumContext,
+ IN ULONG DeviceIndex,
+ OUT LPWSTR * DeviceName,
+ OUT PHANDLE OutHandle,
+ OUT PHANDLE OutKey)
+{
+ SP_DEVICE_INTERFACE_DATA InterfaceData;
+ SP_DEVINFO_DATA DeviceData;
+ PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
+ BOOL Result;
+ DWORD Length;
+ MIXER_STATUS Status;
+
+ //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);
+
+ InterfaceData.cbSize = sizeof(InterfaceData);
+ InterfaceData.Reserved = 0;
+
+ Result = SetupDiEnumDeviceInterfaces(EnumContext,
+ NULL,
+ &CategoryGuid,
+ DeviceIndex,
+ &InterfaceData);
+
+ if (!Result)
+ {
+ if (GetLastError() == ERROR_NO_MORE_ITEMS)
+ {
+ printf("LastDevice\n");
+ return MM_STATUS_NO_MORE_DEVICES;
+ }
+ printf("SetupDiEnumDeviceInterfaces failed with %lu\n", GetLastError());
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+ Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
+ DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
+ 0,
+ Length);
+ DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
+ DeviceData.cbSize = sizeof(DeviceData);
+ DeviceData.Reserved = 0;
+
+ Result = SetupDiGetDeviceInterfaceDetailW(EnumContext,
+ &InterfaceData,
+ DetailData,
+ Length,
+ NULL,
+ &DeviceData);
+
+ if (!Result)
+ {
+ printf("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+
+ *OutKey = SetupDiOpenDeviceInterfaceRegKey(EnumContext, &InterfaceData, 0, KEY_READ);
+ if ((HKEY)*OutKey == INVALID_HANDLE_VALUE)
+ {
+ printf("SetupDiOpenDeviceInterfaceRegKey failed with %lx\n", GetLastError());
+ HeapFree(GetProcessHeap(), 0, DetailData);
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+ Status = Open(DetailData->DevicePath, OutHandle);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ RegCloseKey((HKEY)*OutKey);
+ HeapFree(GetProcessHeap(), 0, DetailData);
+ return Status;
+ }
+
+ *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR));
+ if (*DeviceName == NULL)
+ {
+ CloseHandle(*OutHandle);
+ RegCloseKey((HKEY)*OutKey);
+ HeapFree(GetProcessHeap(), 0, DetailData);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ wcscpy(*DeviceName, DetailData->DevicePath);
+ HeapFree(GetProcessHeap(), 0, DetailData);
+
+ return Status;
+}
+
+MIXER_STATUS
+QueryKeyValue(
+ IN HANDLE hKey,
+ IN LPWSTR KeyName,
+ OUT PVOID * ResultBuffer,
+ OUT PULONG ResultLength,
+ OUT PULONG KeyType)
+{
+ if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, NULL, ResultLength) == ERROR_FILE_NOT_FOUND)
+ return MM_STATUS_UNSUCCESSFUL;
+
+ *ResultBuffer = HeapAlloc(GetProcessHeap(), 0, *ResultLength);
+ if (*ResultBuffer == NULL)
+ return MM_STATUS_NO_MEMORY;
+
+ if (RegQueryValueExW((HKEY)hKey, KeyName, NULL, KeyType, *ResultBuffer, ResultLength) != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, *ResultBuffer);
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+OpenKey(
+ IN HANDLE hKey,
+ IN LPWSTR SubKey,
+ IN ULONG DesiredAccess,
+ OUT PHANDLE OutKey)
+{
+ if (RegOpenKeyExW((HKEY)hKey, SubKey, 0, DesiredAccess, (PHKEY)OutKey) == ERROR_SUCCESS)
+ return MM_STATUS_SUCCESS;
+
+ return MM_STATUS_UNSUCCESSFUL;
+}
+
+MIXER_STATUS
+CloseKey(
+ IN HANDLE hKey)
+{
+ RegCloseKey((HKEY)hKey);
+ return MM_STATUS_SUCCESS;
+}
+
+
+int main(int argc, char**argv)
+{
+ MIXER_STATUS Status;
+ HDEVINFO DeviceHandle;
+ MIXERCAPSW MixCaps1, MixCaps2;
+ ULONG Index, SubIndex;
+ HANDLE hMixer2;
+ HMIXER hMixer1;
+ MIXERLINEW MixerLine1, MixerLine2;
+ MIXERLINECONTROLSW Controls1, Controls2;
+
+ ZeroMemory(&MixerContext, sizeof(MIXER_CONTEXT));
+
+ DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
+ NULL,
+ NULL,
+ DIGCF_DEVICEINTERFACE/*|DIGCF_PRESENT */);
+ if (DeviceHandle == INVALID_HANDLE_VALUE)
+ {
+ printf("SetupDiGetClassDevs failed with %lx\n", GetLastError());
+ return 0;
+ }
+
+ printf("DeviceHandle %p\n", DeviceHandle);
+
+ MixerContext.SizeOfStruct = sizeof(MIXER_CONTEXT);
+ MixerContext.Alloc = Alloc;
+ MixerContext.Close = Close;
+ MixerContext.Control = Control;
+ MixerContext.Copy = Copy;
+ MixerContext.Free = Free;
+ MixerContext.Open = Open;
+ MixerContext.OpenKey = OpenKey;
+ MixerContext.CloseKey = CloseKey;
+ MixerContext.QueryKeyValue = QueryKeyValue;
+
+ Status = MMixerInitialize(&MixerContext, Enum, (PVOID)DeviceHandle);
+
+ printf("Status %x\n", Status);
+ printf("NumberOfMixers %lu mixerGetNumDevs %u\n", MMixerGetCount(&MixerContext), mixerGetNumDevs());
+
+ for(Index = 0; Index < MMixerGetCount(&MixerContext); Index++)
+ {
+ mixerGetDevCapsW(Index, &MixCaps1, sizeof(MIXERCAPSW));
+ wprintf(L"WINM: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps1.cDestinations, MixCaps1.fdwSupport, MixCaps1.szPname, MixCaps1.vDriverVersion, MixCaps1.wMid, MixCaps1.wPid);
+ MMixerGetCapabilities(&MixerContext, Index, &MixCaps2);
+ wprintf(L"MMIX: cDestination %u fdwSupport %lx szPname %s vDriverVersion %u wMid %x wPid %x\n", MixCaps2.cDestinations, MixCaps2.fdwSupport, MixCaps2.szPname, MixCaps2.vDriverVersion, MixCaps2.wMid, MixCaps2.wPid);
+
+ mixerOpen(&hMixer1, Index, 0, 0, MIXER_OBJECTF_HMIXER);
+ MMixerOpen(&MixerContext, Index, NULL, NULL, &hMixer2);
+
+ ZeroMemory(&MixerLine1, sizeof(MIXERLINEW));
+ ZeroMemory(&MixerLine2, sizeof(MIXERLINEW));
+ MixerLine1.cbStruct = sizeof(MIXERLINEW);
+ MixerLine2.cbStruct = sizeof(MIXERLINEW);
+ mixerGetLineInfoW((HMIXEROBJ)hMixer1, &MixerLine1, MIXER_GETLINEINFOF_DESTINATION);
+ MMixerGetLineInfo(&MixerContext, hMixer2, MIXER_GETLINEINFOF_DESTINATION, &MixerLine2);
+
+ wprintf(L"WINM: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
+ MixerLine1.dwDestination, MixerLine1.dwSource, MixerLine1.dwLineID, MixerLine1.dwUser, MixerLine1.dwComponentType, MixerLine1.cChannels, MixerLine1.cConnections, MixerLine1.cControls, MixerLine1.szShortName, MixerLine1.szName);
+
+ wprintf(L"MMIX: dwDestination %lx dwSource %lx dwLineID %lx dwUser %lx dwComponentType %lx cChannels %lx cConnections %lx cControls %lx szShortName %s szName %s\n\n",
+ MixerLine2.dwDestination, MixerLine2.dwSource, MixerLine2.dwLineID, MixerLine2.dwUser, MixerLine2.dwComponentType, MixerLine2.cChannels, MixerLine2.cConnections, MixerLine2.cControls, MixerLine2.szShortName, MixerLine2.szName);
+
+ Controls1.cbStruct = sizeof(MIXERLINECONTROLSW);
+ Controls2.cbStruct = sizeof(MIXERLINECONTROLSW);
+
+ Controls1.cbmxctrl = sizeof(MIXERCONTROL);
+ Controls2.cbmxctrl = sizeof(MIXERCONTROL);
+
+ Controls1.cControls = MixerLine1.cControls;
+ Controls2.cControls = MixerLine2.cControls;
+
+ Controls1.dwLineID = MixerLine1.dwLineID;
+ Controls2.dwLineID = MixerLine2.dwLineID;
+
+
+
+ Controls1.pamxctrl = (LPMIXERCONTROLW)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROLW) * Controls1.cControls);
+ Controls2.pamxctrl = (LPMIXERCONTROLW)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MIXERCONTROLW) * Controls2.cControls);
+
+ for(SubIndex = 0; SubIndex < Controls1.cControls; SubIndex++)
+ Controls1.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROLW);
+
+ for(SubIndex = 0; SubIndex < Controls2.cControls; SubIndex++)
+ Controls2.pamxctrl[SubIndex].cbStruct = sizeof(MIXERCONTROLW);
+
+ mixerGetLineControlsW((HMIXEROBJ)hMixer1, &Controls1, MIXER_GETLINECONTROLSF_ALL);
+ MMixerGetLineControls(&MixerContext, hMixer2, MIXER_GETLINECONTROLSF_ALL, &Controls2);
+
+ wprintf(L"----------------------------------------\n");
+ for(SubIndex = 0; SubIndex < Controls1.cControls || SubIndex < Controls2.cControls; SubIndex++)
+ {
+ if (SubIndex < Controls1.cControls)
+ {
+ wprintf(L"WINM: Index %d dwControlID %lx dwControlType %lx fdwControl %lx cMultipleItems %lx szName %s szShortName %s \n", SubIndex, Controls1.pamxctrl[SubIndex].dwControlID, Controls1.pamxctrl[SubIndex].dwControlType, Controls1.pamxctrl[SubIndex].fdwControl, Controls1.pamxctrl[SubIndex].cMultipleItems, Controls1.pamxctrl[SubIndex].szName, Controls1.pamxctrl[SubIndex].szShortName);
+ }
+
+ if (SubIndex < Controls2.cControls)
+ {
+ wprintf(L"MMIX: Index %d dwControlID %lx dwControlType %lx fdwControl %lx cMultipleItems %lx szName %s szShortName %s \n", SubIndex, Controls2.pamxctrl[SubIndex].dwControlID, Controls2.pamxctrl[SubIndex].dwControlType, Controls2.pamxctrl[SubIndex].fdwControl, Controls2.pamxctrl[SubIndex].cMultipleItems, Controls2.pamxctrl[SubIndex].szName, Controls2.pamxctrl[SubIndex].szShortName);
+ }
+
+ }
+ wprintf(L"----------------------------------------\n");
+
+
+ wprintf(L"=======================\n");
+ }
+ return 0;
+}
diff --git a/rostests/winetests/advapi32/advapi32.rbuild b/rostests/winetests/advapi32/advapi32.rbuild
index 2b5b5df8e54..09bb15038b2 100644
--- a/rostests/winetests/advapi32/advapi32.rbuild
+++ b/rostests/winetests/advapi32/advapi32.rbuild
@@ -1,21 +1,22 @@
- .
+ .
- advapi32
- ntdll
- uuid
- ole32
- cred.c
- crypt.c
- crypt_lmhash.c
- crypt_md4.c
- crypt_md5.c
- crypt_sha.c
- lsa.c
- registry.c
- security.c
- service.c
- testlist.c
+ advapi32
+ ntdll
+ uuid
+ ole32
+ cred.c
+ crypt.c
+ crypt_lmhash.c
+ crypt_md4.c
+ crypt_md5.c
+ crypt_sha.c
+ eventlog.c
+ lsa.c
+ registry.c
+ security.c
+ service.c
+ testlist.c
diff --git a/rostests/winetests/advapi32/crypt.c b/rostests/winetests/advapi32/crypt.c
index f291ae51a0b..2d7235bffc4 100644
--- a/rostests/winetests/advapi32/crypt.c
+++ b/rostests/winetests/advapi32/crypt.c
@@ -234,6 +234,7 @@ static void test_incorrect_api_usage(void)
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 @@ static void test_enum_providers(void)
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 @@ static void test_get_default_provider(void)
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 @@ static void test_machine_guid(void)
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();
diff --git a/rostests/winetests/advapi32/eventlog.c b/rostests/winetests/advapi32/eventlog.c
new file mode 100644
index 00000000000..c0f516acd6f
--- /dev/null
+++ b/rostests/winetests/advapi32/eventlog.c
@@ -0,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
+
+#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();
+}
diff --git a/rostests/winetests/advapi32/registry.c b/rostests/winetests/advapi32/registry.c
index abc2eb4aeb6..dee7664ce27 100644
--- a/rostests/winetests/advapi32/registry.c
+++ b/rostests/winetests/advapi32/registry.c
@@ -956,6 +956,28 @@ static void test_reg_create_key(void)
/* 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 @@ static void test_reg_create_key(void)
else {
ok(!ret, "RegCreateKeyExA failed with error %d\n", ret);
RegDeleteKey(hkey1, NULL);
+ RegCloseKey(hkey1);
}
/* WOW64 flags - open an existing key */
diff --git a/rostests/winetests/advapi32/security.c b/rostests/winetests/advapi32/security.c
index 7d91ebe7de2..33f0188a7ac 100644
--- a/rostests/winetests/advapi32/security.c
+++ b/rostests/winetests/advapi32/security.c
@@ -79,6 +79,7 @@ typedef LPSTR (WINAPI *fnGetTrusteeNameA)( PTRUSTEEA pTrustee );
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 @@ static void init(void)
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 @@ static void test_sid(void)
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 @@ static void test_token_attr(void)
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 @@ static void test_token_attr(void)
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 @@ static void test_CreateWellKnownSid(void)
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 @@ static void test_LookupAccountName(void)
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 @@ static void test_SetEntriesInAcl(void)
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 @@ static void test_ConvertStringSecurityDescriptor(void)
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 @@ static void test_ConvertStringSecurityDescriptor(void)
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());
+ for (i = 0; i < sizeof(cssd)/sizeof(cssd[0]); i++)
+ {
+ DWORD GLE;
- /* 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());
+ 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);
@@ -2766,29 +2772,11 @@ static void test_ConvertStringSecurityDescriptor(void)
GetLastError());
/* 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 @@ static void test_ConvertSecurityDescriptorToString(void)
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 @@ static void test_GetSecurityInfo(void)
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 @@ static void test_GetSecurityInfo(void)
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,11 +3215,140 @@ static void test_GetSidSubAuthority(void)
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)
{
init();
@@ -3255,4 +3379,6 @@ START_TEST(security)
test_acls();
test_GetSecurityInfo();
test_GetSidSubAuthority();
+ test_CheckTokenMembership();
+ test_EqualSid();
}
diff --git a/rostests/winetests/advapi32/service.c b/rostests/winetests/advapi32/service.c
index 0851384b70b..17f89d182a3 100644
--- a/rostests/winetests/advapi32/service.c
+++ b/rostests/winetests/advapi32/service.c
@@ -38,6 +38,9 @@ static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
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 @@ static void init_function_pointers(void)
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 @@ static void test_enum_svc(void)
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;
@@ -1160,6 +1165,12 @@ static void test_enum_svc(void)
"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;
@@ -1506,6 +1517,12 @@ static void test_enum_svc(void)
"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;
diff --git a/rostests/winetests/advapi32/testlist.c b/rostests/winetests/advapi32/testlist.c
index c7fbee87c66..9722479c9be 100644
--- a/rostests/winetests/advapi32/testlist.c
+++ b/rostests/winetests/advapi32/testlist.c
@@ -12,6 +12,7 @@ extern void func_crypt_lmhash(void);
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 @@ const struct test winetest_testlist[] =
{ "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 },
diff --git a/rostests/winetests/fusion/asmenum.c b/rostests/winetests/fusion/asmenum.c
index 48f7b2a97b1..cb6ea3dfdeb 100644
--- a/rostests/winetests/fusion/asmenum.c
+++ b/rostests/winetests/fusion/asmenum.c
@@ -209,6 +209,8 @@ static void test_CreateAssemblyEnum(void)
ok(hr == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n", hr);
ok(asmenum == (IAssemblyEnum *)0xdeadbeef,
"Expected asmenum to be unchanged, got %p\n", asmenum);
+
+ IAssemblyName_Release(asmname);
}
typedef struct _tagASMNAME
diff --git a/rostests/winetests/fusion/asmname.c b/rostests/winetests/fusion/asmname.c
index 442f00f7c45..824837b25fc 100644
--- a/rostests/winetests/fusion/asmname.c
+++ b/rostests/winetests/fusion/asmname.c
@@ -726,6 +726,7 @@ static void test_CreateAssemblyNameObject(void)
ok(name != NULL, "Expected non-NULL name\n");
size = MAX_PATH;
+ str[0] = '\0';
hr = IAssemblyName_GetDisplayName(name, str, &size, ASM_DISPLAYF_FULL);
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
todo_wine
@@ -786,6 +787,7 @@ static void test_CreateAssemblyNameObject(void)
"Expected FUSION_E_INVALID_NAME, got %08x\n", hr);
ok(name == (IAssemblyName *)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", name);
}
+ if(SUCCEEDED(hr)) IAssemblyName_Release(name);
/* no '=' */
to_widechar(namestr, "wine, PublicKeyToken");
diff --git a/rostests/winetests/hlink/hlink.c b/rostests/winetests/hlink/hlink.c
index 5e07359fdf5..1a7536fee93 100644
--- a/rostests/winetests/hlink/hlink.c
+++ b/rostests/winetests/hlink/hlink.c
@@ -57,15 +57,6 @@ DEFINE_EXPECT(IsSystemMoniker);
DEFINE_EXPECT(BindToStorage);
DEFINE_EXPECT(GetDisplayName);
-static const char *debugstr_w(LPCWSTR str)
-{
- static char buf[1024];
- if(!str)
- return "(null)";
- WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
- return buf;
-}
-
static const char *debugstr_guid(REFIID riid)
{
static char buf[50];
@@ -80,7 +71,7 @@ static const char *debugstr_guid(REFIID riid)
static void test_HlinkIsShortcut(void)
{
- int i;
+ UINT i;
HRESULT hres;
static const WCHAR file0[] = {'f','i','l','e',0};
@@ -597,13 +588,13 @@ static void test_HlinkCreateExtensionServices(void)
hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
0, &headers);
ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
- ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
+ ok(!lstrcmpW(headers, headersexW), "unexpected headers %s\n", wine_dbgstr_w(headers));
CoTaskMemFree(headers);
headers = (void*)0xdeadbeef;
hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
- ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
+ ok(headers == NULL, "unexpected headers %s\n", wine_dbgstr_w(headers));
IHttpNegotiate_Release(http_negotiate);
IAuthenticate_Release(authenticate);
@@ -635,7 +626,7 @@ static void test_HlinkParseDisplayName(void)
hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
- ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name));
+ ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
CoTaskMemFree(name);
hres = IMoniker_IsSystemMoniker(mon, &issys);
@@ -662,13 +653,14 @@ static void test_HlinkParseDisplayName(void)
hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
- ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name));
+ ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
CoTaskMemFree(name);
hres = IMoniker_IsSystemMoniker(mon, &issys);
ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
+ IMoniker_Release(mon);
IBindCtx_Release(bctx);
}
@@ -1025,6 +1017,110 @@ static void test_HlinkResolveMonikerForData(void)
IBindCtx_Release(bctx);
}
+static void test_HlinkGetSetMonikerReference(void)
+{
+ IMoniker *found_trgt, *dummy, *dummy2;
+ IHlink *hlink;
+ HRESULT hres;
+ const WCHAR one[] = {'1',0};
+ const WCHAR two[] = {'2',0};
+ const WCHAR name[] = {'a',0};
+ WCHAR *found_loc;
+
+ /* create two dummy monikers to use as targets */
+ hres = CreateItemMoniker(one, one, &dummy);
+ ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
+
+ hres = CreateItemMoniker(two, two, &dummy2);
+ ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
+
+ /* create a new hlink: target => dummy, location => one */
+ hres = HlinkCreateFromMoniker(dummy, one, name, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
+ ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
+
+ /* validate the target and location */
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
+ ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
+ ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* set location => two */
+ hres = IHlink_SetMonikerReference(hlink, HLINKSETF_LOCATION, dummy2, two);
+ ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
+ ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* set target => dummy2 */
+ hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, dummy2, one);
+ ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
+ ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* set target => dummy, location => one */
+ hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, dummy, one);
+ ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
+ ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* no HLINKSETF flags */
+ hres = IHlink_SetMonikerReference(hlink, 0, dummy2, two);
+ ok(hres == E_INVALIDARG, "IHlink_SetMonikerReference should've failed with E_INVALIDARG (0x%08x), failed with 0x%08x\n", E_INVALIDARG, hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
+ ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* invalid HLINKSETF flags */
+ hres = IHlink_SetMonikerReference(hlink, 12, dummy2, two);
+ ok(hres == 12, "IHlink_SetMonikerReference should've failed with 0x%08x, failed with 0x%08x\n", 12, hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
+ ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* valid & invalid HLINKSETF flags */
+ hres = IHlink_SetMonikerReference(hlink, 12 | HLINKSETF_TARGET, dummy2, two);
+ ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
+ ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
+ IMoniker_Release(found_trgt);
+ CoTaskMemFree(found_loc);
+
+ /* NULL args */
+ hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, NULL, NULL);
+ ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
+
+ hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
+ ok(found_trgt == NULL, "Found target should've been %p, was: %p\n", NULL, found_trgt);
+ ok(found_loc == NULL, "Found location should've been %s, was: %s\n", wine_dbgstr_w(NULL), wine_dbgstr_w(found_loc));
+ if(found_trgt)
+ IMoniker_Release(found_trgt);
+
+ IHlink_Release(hlink);
+ IMoniker_Release(dummy2);
+ IMoniker_Release(dummy);
+}
+
START_TEST(hlink)
{
CoInitialize(NULL);
@@ -1036,6 +1132,7 @@ START_TEST(hlink)
test_HlinkCreateExtensionServices();
test_HlinkParseDisplayName();
test_HlinkResolveMonikerForData();
+ test_HlinkGetSetMonikerReference();
CoUninitialize();
}
diff --git a/rostests/winetests/kernel32/actctx.c b/rostests/winetests/kernel32/actctx.c
index 8a8d03e224e..8f51dfb1d96 100644
--- a/rostests/winetests/kernel32/actctx.c
+++ b/rostests/winetests/kernel32/actctx.c
@@ -869,7 +869,7 @@ static void test_basic_info(HANDLE handle)
SIZE_T size;
BOOL b;
- b = pQueryActCtxW(0, handle, NULL,
+ b = pQueryActCtxW(QUERY_ACTCTX_FLAG_NO_ADDREF, handle, NULL,
ActivationContextBasicInformation, &basic,
sizeof(basic), &size);
@@ -878,7 +878,8 @@ static void test_basic_info(HANDLE handle)
ok (basic.dwFlags == 0, "unexpected flags %x\n",basic.dwFlags);
ok (basic.hActCtx == handle, "unexpected handle\n");
- b = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX, handle, NULL,
+ b = pQueryActCtxW(QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX |
+ QUERY_ACTCTX_FLAG_NO_ADDREF, handle, NULL,
ActivationContextBasicInformation, &basic,
sizeof(basic), &size);
if (handle)
@@ -960,15 +961,15 @@ static void test_actctx(void)
pReleaseActCtx(handle);
}
- if(!create_manifest_file("test3.manifest", manifest2, -1, "testdep.manifest", testdep_manifest2)) {
+ if(!create_manifest_file("test2-2.manifest", manifest2, -1, "testdep.manifest", testdep_manifest2)) {
skip("Could not create manifest file\n");
return;
}
trace("manifest2 depmanifest2\n");
- handle = test_create("test3.manifest", manifest2);
- DeleteFileA("test3.manifest");
+ handle = test_create("test2-2.manifest", manifest2);
+ DeleteFileA("test2-2.manifest");
DeleteFileA("testdep.manifest");
if(handle != INVALID_HANDLE_VALUE) {
test_basic_info(handle);
diff --git a/rostests/winetests/kernel32/environ.c b/rostests/winetests/kernel32/environ.c
index b3526675b20..19d11b599a2 100755
--- a/rostests/winetests/kernel32/environ.c
+++ b/rostests/winetests/kernel32/environ.c
@@ -395,7 +395,11 @@ static void test_GetComputerNameExA(void)
ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
/* size is not set in win2k */
- size = MAX_COMP_NAME;
+ if (size == 0)
+ {
+ win_skip("Win2k doesn't set the size\n");
+ size = MAX_COMP_NAME;
+ }
name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
ret = pGetComputerNameExA(ComputerNameDnsDomain, name, &size);
@@ -410,7 +414,8 @@ static void test_GetComputerNameExA(void)
ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
/* size is not set in win2k */
- size = MAX_COMP_NAME;
+ if (size == 0)
+ size = MAX_COMP_NAME;
name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
ret = pGetComputerNameExA(ComputerNameDnsFullyQualified, name, &size);
@@ -425,7 +430,8 @@ static void test_GetComputerNameExA(void)
ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
/* size is not set in win2k */
- size = MAX_COMP_NAME;
+ if (size == 0)
+ size = MAX_COMP_NAME;
name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
ret = pGetComputerNameExA(ComputerNameDnsHostname, name, &size);
@@ -440,7 +446,8 @@ static void test_GetComputerNameExA(void)
ok(error == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", error);
/* size is not set in win2k */
- size = MAX_COMP_NAME;
+ if (size == 0)
+ size = MAX_COMP_NAME;
name = HeapAlloc(GetProcessHeap(), 0, size * sizeof(name[0]));
ok(name != NULL, "HeapAlloc failed with error %d\n", GetLastError());
ret = pGetComputerNameExA(ComputerNameNetBIOS, name, &size);
diff --git a/rostests/winetests/kernel32/file.c b/rostests/winetests/kernel32/file.c
index f53e65df4b8..8b1d667fa78 100755
--- a/rostests/winetests/kernel32/file.c
+++ b/rostests/winetests/kernel32/file.c
@@ -649,12 +649,10 @@ static void test_CopyFileA(void)
ok(hmapfile != NULL, "CreateFileMapping: error %d\n", GetLastError());
ret = CopyFileA(source, dest, FALSE);
- todo_wine {
- ok(!ret, "CopyFileA: expected failure\n");
- ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
- broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x and WinMe */
- "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
- }
+ ok(!ret, "CopyFileA: expected failure\n");
+ ok(GetLastError() == ERROR_USER_MAPPED_FILE ||
+ broken(GetLastError() == ERROR_SHARING_VIOLATION), /* Win9x */
+ "CopyFileA with mapped dest file: expected ERROR_USER_MAPPED_FILE, got %d\n", GetLastError());
CloseHandle(hmapfile);
CloseHandle(hfile);
@@ -1616,7 +1614,80 @@ static void test_LockFile(void)
DeleteFileA( filename );
}
-static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2, BOOL is_win9x )
+static BOOL create_fake_dll( LPCSTR filename )
+{
+ IMAGE_DOS_HEADER *dos;
+ IMAGE_NT_HEADERS *nt;
+ IMAGE_SECTION_HEADER *sec;
+ BYTE *buffer;
+ DWORD lfanew = sizeof(*dos);
+ DWORD size = lfanew + sizeof(*nt) + sizeof(*sec);
+ DWORD written;
+ BOOL ret;
+
+ HANDLE file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+ if (file == INVALID_HANDLE_VALUE) return FALSE;
+
+ buffer = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
+
+ dos = (IMAGE_DOS_HEADER *)buffer;
+ dos->e_magic = IMAGE_DOS_SIGNATURE;
+ dos->e_cblp = sizeof(*dos);
+ dos->e_cp = 1;
+ dos->e_cparhdr = lfanew / 16;
+ dos->e_minalloc = 0;
+ dos->e_maxalloc = 0xffff;
+ dos->e_ss = 0x0000;
+ dos->e_sp = 0x00b8;
+ dos->e_lfarlc = lfanew;
+ dos->e_lfanew = lfanew;
+
+ nt = (IMAGE_NT_HEADERS *)(buffer + lfanew);
+ nt->Signature = IMAGE_NT_SIGNATURE;
+#if defined __i386__
+ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_I386;
+#elif defined __x86_64__
+ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_AMD64;
+#elif defined __powerpc__
+ nt->FileHeader.Machine = IMAGE_FILE_MACHINE_POWERPC;
+#else
+# error You must specify the machine type
+#endif
+ nt->FileHeader.NumberOfSections = 1;
+ nt->FileHeader.SizeOfOptionalHeader = IMAGE_SIZEOF_NT_OPTIONAL_HEADER;
+ nt->FileHeader.Characteristics = IMAGE_FILE_DLL | IMAGE_FILE_EXECUTABLE_IMAGE;
+ nt->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR_MAGIC;
+ nt->OptionalHeader.MajorLinkerVersion = 1;
+ nt->OptionalHeader.MinorLinkerVersion = 0;
+ nt->OptionalHeader.ImageBase = 0x10000000;
+ nt->OptionalHeader.SectionAlignment = 0x1000;
+ nt->OptionalHeader.FileAlignment = 0x1000;
+ nt->OptionalHeader.MajorOperatingSystemVersion = 1;
+ nt->OptionalHeader.MinorOperatingSystemVersion = 0;
+ nt->OptionalHeader.MajorImageVersion = 1;
+ nt->OptionalHeader.MinorImageVersion = 0;
+ nt->OptionalHeader.MajorSubsystemVersion = 4;
+ nt->OptionalHeader.MinorSubsystemVersion = 0;
+ nt->OptionalHeader.SizeOfImage = 0x2000;
+ nt->OptionalHeader.SizeOfHeaders = size;
+ nt->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
+ nt->OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
+
+ sec = (IMAGE_SECTION_HEADER *)(nt + 1);
+ memcpy( sec->Name, ".rodata", sizeof(".rodata") );
+ sec->Misc.VirtualSize = 0x1000;
+ sec->VirtualAddress = 0x1000;
+ sec->SizeOfRawData = 0;
+ sec->PointerToRawData = 0;
+ sec->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
+
+ ret = WriteFile( file, buffer, size, &written, NULL ) && written == size;
+ HeapFree( GetProcessHeap(), 0, buffer );
+ CloseHandle( file );
+ return ret;
+}
+
+static int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2, BOOL is_win9x )
{
if (!is_win9x)
{
@@ -1641,6 +1712,14 @@ static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD ac
return 1;
}
+static int is_sharing_map_compatible( DWORD map_access, DWORD access2, DWORD sharing2 )
+{
+ if ((map_access == PAGE_READWRITE || map_access == PAGE_EXECUTE_READWRITE) &&
+ !(sharing2 & FILE_SHARE_WRITE)) return 0;
+ if ((map_access & SEC_IMAGE) && (access2 & GENERIC_WRITE)) return 0;
+ return 1;
+}
+
static void test_file_sharing(void)
{
static const DWORD access_modes[] =
@@ -1651,20 +1730,20 @@ static void test_file_sharing(void)
FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_DELETE,
FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE };
+ static const DWORD mapping_modes[] =
+ { PAGE_READONLY, PAGE_WRITECOPY, PAGE_READWRITE, SEC_IMAGE | PAGE_WRITECOPY };
int a1, s1, a2, s2;
int ret;
HANDLE h, h2;
BOOL is_win9x = FALSE;
/* make sure the file exists */
- h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
- if (h == INVALID_HANDLE_VALUE)
+ if (!create_fake_dll( filename ))
{
ok(0, "couldn't create file \"%s\" (err=%d)\n", filename, GetLastError());
return;
}
is_win9x = GetFileAttributesW(filenameW) == INVALID_FILE_ATTRIBUTES;
- CloseHandle( h );
for (a1 = 0; a1 < sizeof(access_modes)/sizeof(access_modes[0]); a1++)
{
@@ -1693,12 +1772,10 @@ static void test_file_sharing(void)
SetLastError(0xdeadbeef);
h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
NULL, OPEN_EXISTING, 0, 0 );
-
+ ret = GetLastError();
if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
access_modes[a2], sharing_modes[s2], is_win9x ))
{
- ret = GetLastError();
-
ok( h2 != INVALID_HANDLE_VALUE,
"open failed for modes %x/%x/%x/%x\n",
access_modes[a1], sharing_modes[s1],
@@ -1706,13 +1783,9 @@ static void test_file_sharing(void)
ok( ret == 0xdeadbeef /* Win9x */ ||
ret == 0, /* XP */
"wrong error code %d\n", ret );
-
- CloseHandle( h2 );
}
else
{
- ret = GetLastError();
-
ok( h2 == INVALID_HANDLE_VALUE,
"open succeeded for modes %x/%x/%x/%x\n",
access_modes[a1], sharing_modes[s1],
@@ -1720,12 +1793,107 @@ static void test_file_sharing(void)
ok( ret == ERROR_SHARING_VIOLATION,
"wrong error code %d\n", ret );
}
+ if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
}
}
CloseHandle( h );
}
}
+ for (a1 = 0; a1 < sizeof(mapping_modes)/sizeof(mapping_modes[0]); a1++)
+ {
+ HANDLE m;
+
+ create_fake_dll( filename );
+ SetLastError(0xdeadbeef);
+ h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
+ if (h == INVALID_HANDLE_VALUE)
+ {
+ ok(0,"couldn't create file \"%s\" (err=%d)\n",filename,GetLastError());
+ return;
+ }
+ m = CreateFileMappingA( h, NULL, mapping_modes[a1], 0, 0, NULL );
+ ok( m != 0, "failed to create mapping %x err %u\n", mapping_modes[a1], GetLastError() );
+ CloseHandle( h );
+ if (!m) continue;
+
+ for (a2 = 0; a2 < sizeof(access_modes)/sizeof(access_modes[0]); a2++)
+ {
+ for (s2 = 0; s2 < sizeof(sharing_modes)/sizeof(sharing_modes[0]); s2++)
+ {
+ /* Win9x doesn't support FILE_SHARE_DELETE */
+ if (is_win9x && (sharing_modes[s2] & FILE_SHARE_DELETE))
+ continue;
+
+ SetLastError(0xdeadbeef);
+ h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
+ NULL, OPEN_EXISTING, 0, 0 );
+
+ ret = GetLastError();
+ if (h2 == INVALID_HANDLE_VALUE)
+ {
+ if (is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
+ ok( is_win9x, /* there's no sharing at all with a mapping on win9x */
+ "open failed for modes map %x/%x/%x\n",
+ mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
+ ok( ret == ERROR_SHARING_VIOLATION,
+ "wrong error code %d\n", ret );
+ }
+ else
+ {
+ if (!is_sharing_map_compatible(mapping_modes[a1], access_modes[a2], sharing_modes[s2]))
+ ok( broken(1), /* no checking on nt4 */
+ "open succeeded for modes map %x/%x/%x\n",
+ mapping_modes[a1], access_modes[a2], sharing_modes[s2] );
+ ok( ret == 0xdeadbeef /* Win9x */ ||
+ ret == 0, /* XP */
+ "wrong error code %d\n", ret );
+ CloseHandle( h2 );
+ }
+ }
+ }
+
+ /* try CREATE_ALWAYS over an existing mapping */
+ SetLastError(0xdeadbeef);
+ h2 = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, 0, 0 );
+ ret = GetLastError();
+ if ((mapping_modes[a1] & SEC_IMAGE) || is_win9x)
+ {
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
+ ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ }
+ else
+ {
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
+ ok( ret == ERROR_USER_MAPPED_FILE, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ }
+ if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
+
+ /* try DELETE_ON_CLOSE over an existing mapping */
+ SetLastError(0xdeadbeef);
+ h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0 );
+ ret = GetLastError();
+ if (is_win9x)
+ {
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
+ ok( ret == ERROR_SHARING_VIOLATION, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ }
+ else if (mapping_modes[a1] & SEC_IMAGE)
+ {
+ ok( h2 == INVALID_HANDLE_VALUE, "create succeeded for map %x\n", mapping_modes[a1] );
+ ok( ret == ERROR_ACCESS_DENIED, "wrong error code %d for %x\n", ret, mapping_modes[a1] );
+ }
+ else
+ {
+ ok( h2 != INVALID_HANDLE_VALUE, "open failed for map %x err %u\n", mapping_modes[a1], ret );
+ }
+ if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
+
+ CloseHandle( m );
+ }
+
SetLastError(0xdeadbeef);
h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 );
ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %d\n", GetLastError() );
diff --git a/rostests/winetests/kernel32/locale.c b/rostests/winetests/kernel32/locale.c
index a5b7173aa85..4fdb222c96e 100755
--- a/rostests/winetests/kernel32/locale.c
+++ b/rostests/winetests/kernel32/locale.c
@@ -28,6 +28,7 @@
#include
#include
#include
+#include
#include "wine/test.h"
#include "windef.h"
@@ -466,7 +467,10 @@ static void test_GetDateFormatA(void)
int ret;
SYSTEMTIME curtime;
LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
char buffer[BUFFER_SIZE], input[BUFFER_SIZE], Expected[BUFFER_SIZE];
+ char Broken[BUFFER_SIZE];
+ char short_day[10], month[10], genitive_month[10];
memset(&curtime, 2, sizeof(SYSTEMTIME)); /* Invalid time */
STRINGSA("ddd',' MMM dd yy","");
@@ -542,7 +546,85 @@ static void test_GetDateFormatA(void)
&curtime, input, buffer, COUNTOF(buffer));
ok(!ret && GetLastError() == ERROR_INVALID_FLAGS,
"Expected ERROR_INVALID_FLAGS, got %d\n", GetLastError());
+
+ ret = GetDateFormat(lcid_ru, 0, &curtime, "ddMMMM", buffer, COUNTOF(buffer));
+ if (!ret)
+ {
+ win_skip("LANG_RUSSIAN locale data unavailable\n");
+ return;
+ }
+
+ /* month part should be in genitive form */
+ strcpy(genitive_month, buffer + 2);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, "MMMM", buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ strcpy(month, buffer);
+ ok(strcmp(genitive_month, month) != 0, "Expected different month forms\n");
+
+ ret = GetDateFormat(lcid_ru, 0, &curtime, "ddd", buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ strcpy(short_day, buffer);
+
+ STRINGSA("dd MMMMddd dd", "");
+ sprintf(Expected, "04 %s%s 04", genitive_month, short_day);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
EXPECT_EQA;
+
+ STRINGSA("MMMMddd dd", "");
+ sprintf(Expected, "%s%s 04", month, short_day);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ EXPECT_EQA;
+
+ STRINGSA("MMMMddd", "");
+ sprintf(Expected, "%s%s", month, short_day);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ EXPECT_EQA;
+
+ STRINGSA("MMMMdd", "");
+ sprintf(Expected, "%s04", genitive_month);
+ sprintf(Broken, "%s04", month);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
+ broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
+ "Expected '%s', got '%s'\n", Expected, buffer);
+
+ STRINGSA("MMMMdd ddd", "");
+ sprintf(Expected, "%s04 %s", genitive_month, short_day);
+ sprintf(Broken, "%s04 %s", month, short_day);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
+ broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
+ "Expected '%s', got '%s'\n", Expected, buffer);
+
+ STRINGSA("dd dddMMMM", "");
+ sprintf(Expected, "04 %s%s", short_day, month);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ EXPECT_EQA;
+
+ STRINGSA("dd dddMMMM ddd MMMMdd", "");
+ sprintf(Expected, "04 %s%s %s %s04", short_day, month, short_day, genitive_month);
+ sprintf(Broken, "04 %s%s %s %s04", short_day, month, short_day, month);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
+ broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
+ "Expected '%s', got '%s'\n", Expected, buffer);
+
+ /* with literal part */
+ STRINGSA("ddd',' MMMM dd", "");
+ sprintf(Expected, "%s, %s 04", short_day, genitive_month);
+ sprintf(Broken, "%s, %s 04", short_day, month);
+ ret = GetDateFormat(lcid_ru, 0, &curtime, input, buffer, COUNTOF(buffer));
+ ok(ret, "Expected ret != 0, got %d, error %d\n", ret, GetLastError());
+ ok(strncmp(buffer, Expected, strlen(Expected)) == 0 ||
+ broken(strncmp(buffer, Broken, strlen(Broken)) == 0) /* nt4 */,
+ "Expected '%s', got '%s'\n", Expected, buffer);
}
static void test_GetDateFormatW(void)
diff --git a/rostests/winetests/kernel32/path.c b/rostests/winetests/kernel32/path.c
index dfe889f26c8..6acb740f27e 100755
--- a/rostests/winetests/kernel32/path.c
+++ b/rostests/winetests/kernel32/path.c
@@ -952,14 +952,133 @@ static void test_GetTempPath(void)
SetEnvironmentVariableA("TMP", save_TMP);
}
+static void test_GetLongPathNameA(void)
+{
+ DWORD length, explength, hostsize;
+ char tempfile[MAX_PATH];
+ char longpath[MAX_PATH];
+ char unc_prefix[MAX_PATH];
+ char unc_short[MAX_PATH], unc_long[MAX_PATH];
+ char temppath[MAX_PATH], temppath2[MAX_PATH];
+ HANDLE file;
+
+ if (!pGetLongPathNameA)
+ return;
+
+ GetTempPathA(MAX_PATH, tempfile);
+ lstrcatA(tempfile, "longfilename.longext");
+
+ file = CreateFileA(tempfile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ CloseHandle(file);
+
+ /* Test a normal path with a small buffer size */
+ memset(temppath, 0, MAX_PATH);
+ length = pGetLongPathNameA(tempfile, temppath, 4);
+ /* We have a failure so length should be the minumum plus the terminating '0' */
+ ok(length >= lstrlen(tempfile) + 1, "Wrong length\n");
+ ok(temppath[0] == 0, "Buffer should not have been touched\n");
+
+ /* Some UNC syntax tests */
+
+ memset(temppath, 0, MAX_PATH);
+ memset(temppath2, 0, MAX_PATH);
+ lstrcpyA(temppath2, "\\\\?\\");
+ lstrcatA(temppath2, tempfile);
+ explength = length + 4;
+
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameA(temppath2, NULL, 0);
+ if (length == 0 && GetLastError() == ERROR_BAD_NET_NAME)
+ {
+ win_skip("UNC syntax tests don't work on Win98/WinMe\n");
+ DeleteFileA(tempfile);
+ return;
+ }
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+ length = pGetLongPathNameA(temppath2, NULL, MAX_PATH);
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+ length = pGetLongPathNameA(temppath2, temppath, 4);
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+ ok(temppath[0] == 0, "Buffer should not have been touched\n");
+
+ /* Now an UNC path with the computername */
+ lstrcpyA(unc_prefix, "\\\\");
+ hostsize = sizeof(unc_prefix) - 2;
+ GetComputerName(unc_prefix + 2, &hostsize);
+ lstrcatA(unc_prefix, "\\");
+
+ /* Create a short syntax for the whole unc path */
+ memset(unc_short, 0, MAX_PATH);
+ GetShortPathNameA(tempfile, temppath, MAX_PATH);
+ lstrcpyA(unc_short, unc_prefix);
+ unc_short[lstrlenA(unc_short)] = temppath[0];
+ lstrcatA(unc_short, "$\\");
+ lstrcatA(unc_short, strchr(temppath, '\\') + 1);
+
+ /* Create a long syntax for reference */
+ memset(longpath, 0, MAX_PATH);
+ pGetLongPathNameA(tempfile, temppath, MAX_PATH);
+ lstrcpyA(longpath, unc_prefix);
+ longpath[lstrlenA(longpath)] = temppath[0];
+ lstrcatA(longpath, "$\\");
+ lstrcatA(longpath, strchr(temppath, '\\') + 1);
+
+ /* NULL test */
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameA(unc_short, NULL, 0);
+ if (length == 0 && GetLastError() == ERROR_BAD_NETPATH)
+ {
+ /* Seen on Window XP Home */
+ win_skip("UNC with computername is not supported\n");
+ DeleteFileA(tempfile);
+ return;
+ }
+ explength = lstrlenA(longpath) + 1;
+ todo_wine
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+ length = pGetLongPathNameA(unc_short, NULL, MAX_PATH);
+ todo_wine
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+
+ memset(unc_long, 0, MAX_PATH);
+ length = pGetLongPathNameA(unc_short, unc_long, lstrlenA(unc_short));
+ /* length will include terminating '0' on failure */
+ todo_wine
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+ ok(unc_long[0] == 0, "Buffer should not have been touched\n");
+
+ memset(unc_long, 0, MAX_PATH);
+ length = pGetLongPathNameA(unc_short, unc_long, length);
+ /* length doesn't include terminating '0' on success */
+ explength--;
+ todo_wine
+ {
+ ok(length == explength, "Wrong length %d, expected %d\n", length, explength);
+ ok(!lstrcmpiA(unc_long, longpath), "Expected (%s), got (%s)\n", longpath, unc_long);
+ }
+
+ DeleteFileA(tempfile);
+}
+
static void test_GetLongPathNameW(void)
{
- DWORD length;
+ DWORD length, expanded;
+ BOOL ret;
+ HANDLE file;
WCHAR empty[MAX_PATH];
+ WCHAR tempdir[MAX_PATH], name[200];
+ WCHAR dirpath[4 + MAX_PATH + 200]; /* To ease removal */
+ WCHAR shortpath[4 + MAX_PATH + 200 + 1 + 200];
+ static const WCHAR prefix[] = { '\\','\\','?','\\', 0};
+ static const WCHAR backslash[] = { '\\', 0};
+ static const WCHAR letterX[] = { 'X', 0};
+
+ if (!pGetLongPathNameW)
+ return;
- /* Not present in all windows versions */
- if(pGetLongPathNameW)
- {
SetLastError(0xdeadbeef);
length = pGetLongPathNameW(NULL,NULL,0);
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
@@ -975,7 +1094,73 @@ static void test_GetLongPathNameW(void)
length = pGetLongPathNameW(empty,NULL,0);
ok(0==length,"GetLongPathNameW returned %d but expected 0\n",length);
ok(GetLastError()==ERROR_PATH_NOT_FOUND,"GetLastError returned %d but expected ERROR_PATH_NOT_FOUND\n",GetLastError());
+
+ /* Create a long path name. The path needs to exist for these tests to
+ * succeed so we need the "\\?\" prefix when creating directories and
+ * files.
+ */
+ name[0] = 0;
+ while (lstrlenW(name) < (sizeof(name)/sizeof(WCHAR) - 1))
+ lstrcatW(name, letterX);
+
+ GetTempPathW(MAX_PATH, tempdir);
+
+ lstrcpyW(shortpath, prefix);
+ lstrcatW(shortpath, tempdir);
+ lstrcatW(shortpath, name);
+ lstrcpyW(dirpath, shortpath);
+ ret = CreateDirectoryW(shortpath, NULL);
+ ok(ret, "Could not create the temporary directory : %d\n", GetLastError());
+ lstrcatW(shortpath, backslash);
+ lstrcatW(shortpath, name);
+
+ /* Path does not exist yet and we know it overruns MAX_PATH */
+
+ /* No prefix */
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameW(shortpath + 4, NULL, 0);
+ ok(length == 0, "Expected 0, got %d\n", length);
+ todo_wine
+ ok(GetLastError() == ERROR_PATH_NOT_FOUND,
+ "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
+ /* With prefix */
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameW(shortpath, NULL, 0);
+ todo_wine
+ {
+ ok(length == 0, "Expected 0, got %d\n", length);
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND,
+ "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
}
+
+ file = CreateFileW(shortpath, GENERIC_READ|GENERIC_WRITE, 0, NULL,
+ CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE,
+ "Could not create the temporary file : %d.\n", GetLastError());
+ CloseHandle(file);
+
+ /* Path exists */
+
+ /* No prefix */
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameW(shortpath + 4, NULL, 0);
+ todo_wine
+ {
+ ok(length == 0, "Expected 0, got %d\n", length);
+ ok(GetLastError() == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
+ }
+ /* With prefix */
+ expanded = 4 + (pGetLongPathNameW(tempdir, NULL, 0) - 1) + lstrlenW(name) + 1 + lstrlenW(name) + 1;
+ SetLastError(0xdeadbeef);
+ length = pGetLongPathNameW(shortpath, NULL, 0);
+ ok(length == expanded, "Expected %d, got %d\n", expanded, length);
+
+ /* NULL buffer with length crashes on Windows */
+ if (0)
+ length = pGetLongPathNameW(shortpath, NULL, 20);
+
+ ok(DeleteFileW(shortpath), "Could not delete temporary file\n");
+ ok(RemoveDirectoryW(dirpath), "Could not delete temporary directory\n");
}
static void test_GetShortPathNameW(void)
@@ -1273,11 +1458,18 @@ START_TEST(path)
(void*)GetProcAddress( GetModuleHandleA("kernel32.dll"),
"NeedCurrentDirectoryForExePathW" );
+ /* Report only once */
+ if (!pGetLongPathNameA)
+ win_skip("GetLongPathNameA is not available\n");
+ if (!pGetLongPathNameW)
+ win_skip("GetLongPathNameW is not available\n");
+
test_InitPathA(curdir, &curDrive, &otherDrive);
test_CurrentDirectoryA(origdir,curdir);
test_PathNameA(curdir, curDrive, otherDrive);
test_CleanupPathA(origdir,curdir);
test_GetTempPath();
+ test_GetLongPathNameA();
test_GetLongPathNameW();
test_GetShortPathNameW();
test_GetSystemDirectory();
diff --git a/rostests/winetests/kernel32/volume.c b/rostests/winetests/kernel32/volume.c
index 42142e82707..6199d7cf9da 100644
--- a/rostests/winetests/kernel32/volume.c
+++ b/rostests/winetests/kernel32/volume.c
@@ -155,8 +155,11 @@ static void test_GetVolumeNameForVolumeMountPointA(void)
GetLastError());
/* Try on a arbitrary directory */
+ /* On FAT filesystems it seems that GetLastError() is set to
+ ERROR_INVALID_FUNCTION. */
ret = pGetVolumeNameForVolumeMountPointA(temp_path, volume, len);
- ok(ret == FALSE && GetLastError() == ERROR_NOT_A_REPARSE_POINT,
+ ok(ret == FALSE && (GetLastError() == ERROR_NOT_A_REPARSE_POINT ||
+ GetLastError() == ERROR_INVALID_FUNCTION),
"GetVolumeNameForVolumeMountPointA failed on %s, last=%d\n",
temp_path, GetLastError());
diff --git a/rostests/winetests/lz32/lzexpand_main.c b/rostests/winetests/lz32/lzexpand_main.c
index 91fd6873e3f..3e46fb0a47c 100644
--- a/rostests/winetests/lz32/lzexpand_main.c
+++ b/rostests/winetests/lz32/lzexpand_main.c
@@ -881,10 +881,10 @@ static void test_LZOpenFileW(void)
START_TEST(lzexpand_main)
{
- buf = malloc(uncompressed_data_size * 2);
+ buf = HeapAlloc(GetProcessHeap(), 0, uncompressed_data_size * 2);
test_LZOpenFileA();
test_LZOpenFileW();
test_LZRead();
test_LZCopy();
- free(buf);
+ HeapFree(GetProcessHeap(), 0, buf);
}
diff --git a/rostests/winetests/msacm32/msacm.c b/rostests/winetests/msacm32/msacm.c
index 26eeb478b63..c7cab5d6605 100644
--- a/rostests/winetests/msacm32/msacm.c
+++ b/rostests/winetests/msacm32/msacm.c
@@ -94,7 +94,7 @@ static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,
/* MSDN says this should fail but it doesn't in practice */
dd.cbStruct = 4;
rc = acmDriverDetails(hadid, &dd, 0);
- ok(rc == MMSYSERR_NOERROR,
+ ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED,
"acmDriverDetails(): rc = %08x, should be %08x\n",
rc, MMSYSERR_NOERROR);
@@ -119,17 +119,16 @@ static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,
/* try valid parameters */
rc = acmDriverDetails(hadid, &dd, 0);
- ok(rc == MMSYSERR_NOERROR,
+ ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NOTSUPPORTED,
"acmDriverDetails(): rc = %08x, should be %08x\n",
rc, MMSYSERR_NOERROR);
/* cbStruct should contain size of returned data (at most sizeof(dd))
TODO: should it be *exactly* sizeof(dd), as tested here?
*/
- if (rc == MMSYSERR_NOERROR) {
+ if (rc == MMSYSERR_NOERROR) {
ok(dd.cbStruct == sizeof(dd),
- "acmDriverDetails(): cbStruct = %08x, should be %08lx\n",
- dd.cbStruct, (unsigned long)sizeof(dd));
+ "acmDriverDetails(): cbStruct = %08x\n", dd.cbStruct);
}
if (rc == MMSYSERR_NOERROR && winetest_interactive) {
@@ -210,7 +209,7 @@ static BOOL CALLBACK DriverEnumProc(HACMDRIVERID hadid,
/* try valid parameters */
rc = acmDriverOpen(&had, hadid, 0);
- ok(rc == MMSYSERR_NOERROR,
+ ok(rc == MMSYSERR_NOERROR || rc == MMSYSERR_NODRIVER,
"acmDriverOpen(): rc = %08x, should be %08x\n",
rc, MMSYSERR_NOERROR);
diff --git a/rostests/winetests/msi/automation.c b/rostests/winetests/msi/automation.c
index b792fa722bd..8a0eede3066 100644
--- a/rostests/winetests/msi/automation.c
+++ b/rostests/winetests/msi/automation.c
@@ -34,8 +34,8 @@
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
-static const char *msifile = "winetest.msi";
-static const WCHAR szMsifile[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
+static const char *msifile = "winetest-automation.msi";
+static const WCHAR szMsifile[] = {'w','i','n','e','t','e','s','t','-','a','u','t','o','m','a','t','i','o','n','.','m','s','i',0};
static const WCHAR szMSITEST[] = { 'M','S','I','T','E','S','T',0 };
static const WCHAR szProductCode[] = { '{','F','1','C','3','A','F','5','0','-','8','B','5','6','-','4','A','6','9','-','A','0','0','C','-','0','0','7','7','3','F','E','4','2','F','3','0','}',0 };
static const WCHAR szUpgradeCode[] = { '{','C','E','0','6','7','E','8','D','-','2','E','1','A','-','4','3','6','7','-','B','7','3','4','-','4','E','B','2','B','D','A','D','6','5','6','5','}',0 };
@@ -271,6 +271,27 @@ static void create_database(const CHAR *name, const msi_table *tables, int num_t
MsiCloseHandle(db);
}
+static BOOL create_package(LPWSTR path)
+{
+ DWORD len;
+
+ /* Prepare package */
+ create_database(msifile, tables,
+ sizeof(tables) / sizeof(msi_table), summary_info,
+ sizeof(summary_info) / sizeof(msi_summary_info));
+
+ len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,
+ CURR_DIR, -1, path, MAX_PATH);
+ ok(len, "MultiByteToWideChar returned error %d\n", GetLastError());
+ if (!len)
+ return FALSE;
+
+ /* lstrcatW does not work on win95 */
+ path[len - 1] = '\\';
+ memcpy(&path[len], szMsifile, sizeof(szMsifile));
+ return TRUE;
+}
+
/*
* Installation helpers
*/
@@ -456,35 +477,32 @@ static void test_dispid(void)
ok(dispid == 1, "Expected 1, got %d\n", dispid);
dispid = get_dispid(pInstaller, "OpenPackage");
ok(dispid == 2, "Expected 2, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "OpenProduct");
+ ok(dispid == 3, "Expected 3, got %d\n", dispid);
dispid = get_dispid(pInstaller, "OpenDatabase");
ok(dispid == 4, "Expected 4, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "SummaryInformation");
+ ok(dispid == 5, "Expected 5, got %d\n", dispid);
dispid = get_dispid( pInstaller, "UILevel" );
ok(dispid == 6, "Expected 6, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "EnableLog");
+ ok(dispid == 7, "Expected 7, got %d\n", dispid);
dispid = get_dispid(pInstaller, "InstallProduct");
ok(dispid == 8, "Expected 8, got %d\n", dispid);
dispid = get_dispid(pInstaller, "Version");
ok(dispid == 9, "Expected 9, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "LastErrorRecord");
+ ok(dispid == 10, "Expected 10, got %d\n", dispid);
dispid = get_dispid(pInstaller, "RegistryValue");
ok(dispid == 11, "Expected 11, got %d\n", dispid);
- todo_wine
- {
- dispid = get_dispid(pInstaller, "OpenProduct");
- ok(dispid == 3, "Expected 3, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "SummaryInformation");
- ok(dispid == 5, "Expected 5, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "EnableLog");
- ok(dispid == 7, "Expected 7, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "LastErrorRecord");
- ok(dispid == 10, "Expected 10, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "Environment");
- ok(dispid == 12, "Expected 12, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "FileAttributes");
- ok(dispid == 13, "Expected 13, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "FileSize");
- ok(dispid == 15, "Expected 15, got %d\n", dispid);
- dispid = get_dispid(pInstaller, "FileVersion");
- ok(dispid == 16, "Expected 16, got %d\n", dispid);
- }
+ dispid = get_dispid(pInstaller, "Environment");
+ ok(dispid == 12, "Expected 12, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "FileAttributes");
+ ok(dispid == 13, "Expected 13, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "FileSize");
+ ok(dispid == 15, "Expected 15, got %d\n", dispid);
+ dispid = get_dispid(pInstaller, "FileVersion");
+ ok(dispid == 16, "Expected 16, got %d\n", dispid);
dispid = get_dispid(pInstaller, "ProductState");
ok(dispid == 17, "Expected 17, got %d\n", dispid);
dispid = get_dispid(pInstaller, "ProductInfo");
@@ -592,7 +610,8 @@ static void test_dispatch(void)
DISPID dispid;
OLECHAR *name;
VARIANT varresult;
- VARIANTARG vararg[2];
+ VARIANTARG vararg[3];
+ WCHAR path[MAX_PATH];
DISPPARAMS dispparams = {NULL, NULL, 0, 0};
/* Test getting ID of a function name that does not exist */
@@ -620,24 +639,159 @@ static void test_dispatch(void)
/* Try with NULL params */
hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
- todo_wine ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
+ ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
/* Try one empty parameter */
dispparams.rgvarg = vararg;
dispparams.cArgs = 1;
VariantInit(&vararg[0]);
hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
- todo_wine ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
+ ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
- /* Try one parameter, function requires two */
+ /* Try two empty parameters */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[0]);
+ VariantInit(&vararg[1]);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
+
+ /* Try one parameter, the required BSTR. Second parameter is optional.
+ * NOTE: The specified package does not exist, which is why the call fails.
+ */
+ dispparams.cArgs = 1;
VariantInit(&vararg[0]);
V_VT(&vararg[0]) = VT_BSTR;
V_BSTR(&vararg[0]) = SysAllocString(szMsifile);
hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
- VariantClear(&vararg[0]);
-
ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned 0x%08x\n", hr);
ok_exception(hr, szOpenPackageException);
+ VariantClear(&vararg[0]);
+
+ /* Provide the required BSTR and an empty second parameter.
+ * NOTE: The specified package does not exist, which is why the call fails.
+ */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[1]);
+ V_VT(&vararg[1]) = VT_BSTR;
+ V_BSTR(&vararg[1]) = SysAllocString(szMsifile);
+ VariantInit(&vararg[0]);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned 0x%08x\n", hr);
+ ok_exception(hr, szOpenPackageException);
+ VariantClear(&vararg[1]);
+
+ /* Provide the required BSTR and two empty parameters.
+ * NOTE: The specified package does not exist, which is why the call fails.
+ */
+ dispparams.cArgs = 3;
+ VariantInit(&vararg[2]);
+ V_VT(&vararg[2]) = VT_BSTR;
+ V_BSTR(&vararg[2]) = SysAllocString(szMsifile);
+ VariantInit(&vararg[1]);
+ VariantInit(&vararg[0]);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned 0x%08x\n", hr);
+ ok_exception(hr, szOpenPackageException);
+ VariantClear(&vararg[2]);
+
+ /* Provide the required BSTR and a second parameter with the wrong type. */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[1]);
+ V_VT(&vararg[1]) = VT_BSTR;
+ V_BSTR(&vararg[1]) = SysAllocString(szMsifile);
+ VariantInit(&vararg[0]);
+ V_VT(&vararg[0]) = VT_BSTR;
+ V_BSTR(&vararg[0]) = SysAllocString(szMsifile);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[0]);
+ VariantClear(&vararg[1]);
+
+ /* Create a proper installer package. */
+ create_package(path);
+
+ /* Try one parameter, the required BSTR. Second parameter is optional.
+ * Proper installer package exists. Path to the package is relative.
+ */
+ dispparams.cArgs = 1;
+ VariantInit(&vararg[0]);
+ V_VT(&vararg[0]) = VT_BSTR;
+ V_BSTR(&vararg[0]) = SysAllocString(szMsifile);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ todo_wine ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned 0x%08x\n", hr);
+ ok_exception(hr, szOpenPackageException);
+ VariantClear(&vararg[0]);
+ if (hr != DISP_E_EXCEPTION)
+ VariantClear(&varresult);
+
+ /* Try one parameter, the required BSTR. Second parameter is optional.
+ * Proper installer package exists. Path to the package is absolute.
+ */
+ dispparams.cArgs = 1;
+ VariantInit(&vararg[0]);
+ V_VT(&vararg[0]) = VT_BSTR;
+ V_BSTR(&vararg[0]) = SysAllocString(path);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == S_OK, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[0]);
+ VariantClear(&varresult);
+
+ /* Provide the required BSTR and an empty second parameter. Proper
+ * installation package exists.
+ */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[1]);
+ V_VT(&vararg[1]) = VT_BSTR;
+ V_BSTR(&vararg[1]) = SysAllocString(path);
+ VariantInit(&vararg[0]);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == S_OK, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[1]);
+ VariantClear(&varresult);
+
+ /* Provide the required BSTR and two empty parameters. Proper
+ * installation package exists.
+ */
+ dispparams.cArgs = 3;
+ VariantInit(&vararg[2]);
+ V_VT(&vararg[2]) = VT_BSTR;
+ V_BSTR(&vararg[2]) = SysAllocString(path);
+ VariantInit(&vararg[1]);
+ VariantInit(&vararg[0]);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == S_OK, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[2]);
+ VariantClear(&varresult);
+
+ /* Provide the required BSTR and a second parameter with the wrong type. */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[1]);
+ V_VT(&vararg[1]) = VT_BSTR;
+ V_BSTR(&vararg[1]) = SysAllocString(path);
+ VariantInit(&vararg[0]);
+ V_VT(&vararg[0]) = VT_BSTR;
+ V_BSTR(&vararg[0]) = SysAllocString(path);
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[0]);
+ VariantClear(&vararg[1]);
+
+ /* Provide the required BSTR and a second parameter that can be coerced to
+ * VT_I4.
+ */
+ dispparams.cArgs = 2;
+ VariantInit(&vararg[1]);
+ V_VT(&vararg[1]) = VT_BSTR;
+ V_BSTR(&vararg[1]) = SysAllocString(path);
+ VariantInit(&vararg[0]);
+ V_VT(&vararg[0]) = VT_I2;
+ V_BSTR(&vararg[0]) = 0;
+ hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
+ ok(hr == S_OK, "IDispatch::Invoke returned 0x%08x\n", hr);
+ VariantClear(&vararg[1]);
+ VariantClear(&varresult);
+
+ DeleteFileW(path);
/* Test invoking a method as a DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT */
VariantInit(&vararg[0]);
@@ -2353,7 +2507,6 @@ static void test_Installer(void)
static WCHAR szIntegerDataException[] = { 'I','n','t','e','g','e','r','D','a','t','a',',','F','i','e','l','d',0 };
WCHAR szPath[MAX_PATH];
HRESULT hr;
- UINT len;
IDispatch *pSession = NULL, *pDatabase = NULL, *pRecord = NULL, *pStringList = NULL;
int iValue, iCount;
@@ -2404,17 +2557,7 @@ static void test_Installer(void)
IDispatch_Release(pRecord);
}
- /* Prepare package */
- create_database(msifile, tables, sizeof(tables) / sizeof(msi_table),
- summary_info, sizeof(summary_info) / sizeof(msi_summary_info));
-
- len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, CURR_DIR, -1, szPath, MAX_PATH);
- ok(len, "MultiByteToWideChar returned error %d\n", GetLastError());
- if (!len) return;
-
- /* lstrcatW does not work on win95 */
- szPath[len - 1] = '\\';
- memcpy(&szPath[len], szMsifile, sizeof(szMsifile));
+ create_package(szPath);
/* Installer::OpenPackage */
hr = Installer_OpenPackage(szPath, 0, &pSession);
diff --git a/rostests/winetests/msi/db.c b/rostests/winetests/msi/db.c
index 3af113518f8..399ce585f63 100644
--- a/rostests/winetests/msi/db.c
+++ b/rostests/winetests/msi/db.c
@@ -31,9 +31,10 @@
#include "wine/test.h"
-static const char *msifile = "winetest.msi";
-static const char *msifile2 = "winetst2.msi";
-static const char *mstfile = "winetst.mst";
+static const char *msifile = "winetest-db.msi";
+static const char *msifile2 = "winetst2-db.msi";
+static const char *mstfile = "winetst-db.mst";
+static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','-','d','b','.','m','s','i',0};
static void test_msidatabase(void)
{
@@ -921,6 +922,8 @@ static void test_viewmodify(void)
r = MsiViewModify(hview, MSIMODIFY_INSERT_TEMPORARY, hrec );
ok(r == ERROR_SUCCESS, "MsiViewModify failed\n");
+ r = MsiCloseHandle(hrec);
+ ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
r = MsiViewClose(hview);
ok(r == ERROR_SUCCESS, "MsiViewClose failed\n");
r = MsiCloseHandle(hview);
@@ -1760,6 +1763,30 @@ static void test_where(void)
ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
MsiCloseHandle( rec );
+ rec = 0;
+ query = "SELECT * FROM `Media` WHERE `DiskPrompt` < 'Cabinet'";
+ r = do_query(hdb, query, &rec);
+ ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
+ MsiCloseHandle( rec );
+
+ rec = 0;
+ query = "SELECT * FROM `Media` WHERE `DiskPrompt` > 'Cabinet'";
+ r = do_query(hdb, query, &rec);
+ ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %d\n", r );
+ MsiCloseHandle( rec );
+
+ rec = 0;
+ query = "SELECT * FROM `Media` WHERE `DiskPrompt` <> 'Cabinet'";
+ r = do_query(hdb, query, &rec);
+ todo_wine ok( r == ERROR_SUCCESS, "query failed: %d\n", r );
+ MsiCloseHandle( rec );
+
+ rec = 0;
+ query = "SELECT * FROM `Media` WHERE `DiskPrompt` = 'Cabinet'";
+ r = do_query(hdb, query, &rec);
+ ok( r == ERROR_NO_MORE_ITEMS, "query failed: %d\n", r );
+ MsiCloseHandle( rec );
+
rec = MsiCreateRecord(1);
MsiRecordSetString(rec, 1, "");
@@ -5539,6 +5566,8 @@ static void enum_stream_names(IStorage *stg)
ok(hr == S_OK, "Expected S_OK, got %08x\n", hr);
ok(stm != NULL, "Expected non-NULL stream\n");
+ CoTaskMemFree(stat.pwcsName);
+
sz = MAX_PATH;
memset(data, 'a', MAX_PATH);
hr = IStream_Read(stm, data, sz, &count);
@@ -5569,8 +5598,6 @@ static void test_defaultdatabase(void)
MSIHANDLE hdb;
IStorage *stg = NULL;
- static const WCHAR msifileW[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
-
DeleteFile(msifile);
r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb);
diff --git a/rostests/winetests/msi/format.c b/rostests/winetests/msi/format.c
index 2d949e358e6..4827a209f46 100644
--- a/rostests/winetests/msi/format.c
+++ b/rostests/winetests/msi/format.c
@@ -27,7 +27,7 @@
#include "wine/test.h"
-static const char msifile[] = "winetest.msi";
+static const char msifile[] = "winetest-format.msi";
static UINT run_query( MSIHANDLE hdb, const char *query )
{
@@ -315,17 +315,16 @@ static MSIHANDLE helper_createpackage( const char *szName )
static void test_createpackage(void)
{
- static const CHAR filename[] = "winetest.msi";
MSIHANDLE hPackage = 0;
UINT res;
- hPackage = helper_createpackage( filename );
+ hPackage = helper_createpackage( msifile );
ok ( hPackage != 0, " Failed to create package\n");
res = MsiCloseHandle( hPackage);
ok( res == ERROR_SUCCESS , "Failed to close package\n" );
- DeleteFile( filename );
+ DeleteFile( msifile );
}
static void test_formatrecord(void)
@@ -1620,14 +1619,13 @@ static void test_formatrecord(void)
static void test_formatrecord_package(void)
{
- static const CHAR filename[] = "winetest.msi";
char buffer[100];
MSIHANDLE hrec;
MSIHANDLE package;
UINT r;
DWORD sz=100;
- package = helper_createpackage( filename );
+ package = helper_createpackage( msifile );
ok(package!=0, "Unable to create package\n");
hrec = MsiCreateRecord(12);
@@ -2117,7 +2115,7 @@ static void test_formatrecord_package(void)
r = MsiCloseHandle(package);
ok(r==ERROR_SUCCESS, "Unable to close package\n");
- DeleteFile( filename );
+ DeleteFile( msifile );
}
static void test_formatrecord_tables(void)
@@ -2383,12 +2381,11 @@ static void test_formatrecord_tables(void)
static void test_processmessage(void)
{
- static const CHAR filename[] = "winetest.msi";
MSIHANDLE hrec;
MSIHANDLE package;
int r;
- package = helper_createpackage( filename );
+ package = helper_createpackage( msifile );
ok(package!=0, "Unable to create package\n");
hrec = MsiCreateRecord(3);
@@ -2403,7 +2400,7 @@ static void test_processmessage(void)
MsiCloseHandle(hrec);
MsiCloseHandle(package);
- DeleteFile(filename);
+ DeleteFile(msifile);
}
START_TEST(format)
diff --git a/rostests/winetests/msi/install.c b/rostests/winetests/msi/install.c
index 9c5d777d13f..438be6ca884 100644
--- a/rostests/winetests/msi/install.c
+++ b/rostests/winetests/msi/install.c
@@ -163,6 +163,52 @@ static const CHAR property_dat[] = "Property\tValue\n"
"SERVNAME\tTestService\n"
"SERVDISP\tTestServiceDisp\n";
+static const CHAR aup_property_dat[] = "Property\tValue\n"
+ "s72\tl0\n"
+ "Property\tProperty\n"
+ "DefaultUIFont\tDlgFont8\n"
+ "HASUIRUN\t0\n"
+ "ALLUSERS\t1\n"
+ "INSTALLLEVEL\t3\n"
+ "InstallMode\tTypical\n"
+ "Manufacturer\tWine\n"
+ "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
+ "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
+ "ProductID\tnone\n"
+ "ProductLanguage\t1033\n"
+ "ProductName\tMSITEST\n"
+ "ProductVersion\t1.1.1\n"
+ "PROMPTROLLBACKCOST\tP\n"
+ "Setup\tSetup\n"
+ "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
+ "AdminProperties\tPOSTADMIN\n"
+ "ROOTDRIVE\tC:\\\n"
+ "SERVNAME\tTestService\n"
+ "SERVDISP\tTestServiceDisp\n";
+
+static const CHAR aup2_property_dat[] = "Property\tValue\n"
+ "s72\tl0\n"
+ "Property\tProperty\n"
+ "DefaultUIFont\tDlgFont8\n"
+ "HASUIRUN\t0\n"
+ "ALLUSERS\t2\n"
+ "INSTALLLEVEL\t3\n"
+ "InstallMode\tTypical\n"
+ "Manufacturer\tWine\n"
+ "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
+ "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
+ "ProductID\tnone\n"
+ "ProductLanguage\t1033\n"
+ "ProductName\tMSITEST\n"
+ "ProductVersion\t1.1.1\n"
+ "PROMPTROLLBACKCOST\tP\n"
+ "Setup\tSetup\n"
+ "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
+ "AdminProperties\tPOSTADMIN\n"
+ "ROOTDRIVE\tC:\\\n"
+ "SERVNAME\tTestService\n"
+ "SERVDISP\tTestServiceDisp\n";
+
static const CHAR shortcut_dat[] = "Shortcut\tDirectory_\tName\tComponent_\tTarget\tArguments\tDescription\tHotkey\tIcon_\tIconIndex\tShowCmd\tWkDir\n"
"s72\ts72\tl128\ts72\ts72\tS255\tL255\tI2\tS72\tI2\tI2\tS72\n"
"Shortcut\tShortcut\n"
@@ -941,6 +987,48 @@ static const CHAR aup_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
"LaunchConditions\t\t100\n"
"TestAllUsersProp\tALLUSERS AND NOT REMOVE\t50\n";
+static const CHAR aup2_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
+ "s72\tS255\tI2\n"
+ "InstallExecuteSequence\tAction\n"
+ "CostFinalize\t\t1000\n"
+ "ValidateProductID\t\t700\n"
+ "CostInitialize\t\t800\n"
+ "FileCost\t\t900\n"
+ "RemoveFiles\t\t3500\n"
+ "InstallFiles\t\t4000\n"
+ "RegisterUser\t\t6000\n"
+ "RegisterProduct\t\t6100\n"
+ "PublishFeatures\t\t6300\n"
+ "PublishProduct\t\t6400\n"
+ "InstallFinalize\t\t6600\n"
+ "InstallInitialize\t\t1500\n"
+ "ProcessComponents\t\t1600\n"
+ "UnpublishFeatures\t\t1800\n"
+ "InstallValidate\t\t1400\n"
+ "LaunchConditions\t\t100\n"
+ "TestAllUsersProp\tALLUSERS=2 AND NOT REMOVE\t50\n";
+
+static const CHAR aup3_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
+ "s72\tS255\tI2\n"
+ "InstallExecuteSequence\tAction\n"
+ "CostFinalize\t\t1000\n"
+ "ValidateProductID\t\t700\n"
+ "CostInitialize\t\t800\n"
+ "FileCost\t\t900\n"
+ "RemoveFiles\t\t3500\n"
+ "InstallFiles\t\t4000\n"
+ "RegisterUser\t\t6000\n"
+ "RegisterProduct\t\t6100\n"
+ "PublishFeatures\t\t6300\n"
+ "PublishProduct\t\t6400\n"
+ "InstallFinalize\t\t6600\n"
+ "InstallInitialize\t\t1500\n"
+ "ProcessComponents\t\t1600\n"
+ "UnpublishFeatures\t\t1800\n"
+ "InstallValidate\t\t1400\n"
+ "LaunchConditions\t\t100\n"
+ "TestAllUsersProp\tALLUSERS=1 AND NOT REMOVE\t50\n";
+
static const CHAR aup_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
"s72\ti2\tS64\tS0\tS255\n"
"CustomAction\tAction\n"
@@ -1586,6 +1674,45 @@ static const msi_table aup_tables[] =
ADD_TABLE(property)
};
+static const msi_table aup2_tables[] =
+{
+ ADD_TABLE(component),
+ ADD_TABLE(directory),
+ ADD_TABLE(feature),
+ ADD_TABLE(feature_comp),
+ ADD_TABLE(file),
+ ADD_TABLE(aup2_install_exec_seq),
+ ADD_TABLE(aup_custom_action),
+ ADD_TABLE(media),
+ ADD_TABLE(aup_property)
+};
+
+static const msi_table aup3_tables[] =
+{
+ ADD_TABLE(component),
+ ADD_TABLE(directory),
+ ADD_TABLE(feature),
+ ADD_TABLE(feature_comp),
+ ADD_TABLE(file),
+ ADD_TABLE(aup2_install_exec_seq),
+ ADD_TABLE(aup_custom_action),
+ ADD_TABLE(media),
+ ADD_TABLE(aup2_property)
+};
+
+static const msi_table aup4_tables[] =
+{
+ ADD_TABLE(component),
+ ADD_TABLE(directory),
+ ADD_TABLE(feature),
+ ADD_TABLE(feature_comp),
+ ADD_TABLE(file),
+ ADD_TABLE(aup3_install_exec_seq),
+ ADD_TABLE(aup_custom_action),
+ ADD_TABLE(media),
+ ADD_TABLE(aup2_property)
+};
+
static const msi_table fiu_tables[] =
{
ADD_TABLE(rof_component),
@@ -6778,6 +6905,7 @@ static void test_allusers_prop(void)
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+ /* ALLUSERS property unset */
r = MsiInstallProductA(msifile, "FULL=1");
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
@@ -6798,6 +6926,69 @@ static void test_allusers_prop(void)
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
delete_test_files();
+
+ create_test_files();
+ create_database(msifile, aup2_tables, sizeof(aup2_tables) / sizeof(msi_table));
+
+ MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+
+ /* ALLUSERS property set to 1 */
+ r = MsiInstallProductA(msifile, "FULL=1");
+ ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+ ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
+ ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
+ ok(delete_pf("msitest", FALSE), "File not installed\n");
+
+ r = MsiInstallProductA(msifile, "REMOVE=ALL");
+ ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+ delete_test_files();
+
+ create_test_files();
+ create_database(msifile, aup3_tables, sizeof(aup3_tables) / sizeof(msi_table));
+
+ MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+
+ /* ALLUSERS property set to 2 */
+ r = MsiInstallProductA(msifile, "FULL=1");
+ ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+ ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
+ ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
+ ok(delete_pf("msitest\\one.txt", TRUE), "File installed\n");
+ ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
+ ok(delete_pf("msitest", FALSE), "File not installed\n");
+
+ r = MsiInstallProductA(msifile, "REMOVE=ALL");
+ ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
+
+ delete_test_files();
+
+ create_test_files();
+ create_database(msifile, aup4_tables, sizeof(aup4_tables) / sizeof(msi_table));
+
+ MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+
+ /* ALLUSERS property set to 2, conditioned on ALLUSERS = 1 */
+ r = MsiInstallProductA(msifile, "FULL=1");
+ ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
}
static char session_manager[] = "System\\CurrentControlSet\\Control\\Session Manager";
diff --git a/rostests/winetests/msi/msi.c b/rostests/winetests/msi/msi.c
index 28ffb583dda..d5602039abf 100644
--- a/rostests/winetests/msi/msi.c
+++ b/rostests/winetests/msi/msi.c
@@ -2517,8 +2517,7 @@ static void test_MsiGetFileVersion(void)
r = MsiGetFileVersionA(path, version, &versz, lang, &langsz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
ok(versz == verchecksz, "Expected %d, got %d\n", verchecksz, versz);
- ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang);
- ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
+ ok(strstr(lang, langcheck) != NULL, "Expected %s in %s\n", langcheck, lang);
ok(!lstrcmpA(version, vercheck),
"Expected %s, got %s\n", vercheck, version);
@@ -2536,8 +2535,7 @@ static void test_MsiGetFileVersion(void)
lstrcpyA(lang, "lang");
r = MsiGetFileVersionA(path, NULL, NULL, lang, &langsz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
- ok(!lstrcmpA(lang, langcheck), "Expected %s, got %s\n", langcheck, lang);
- ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
+ ok(strstr(lang, langcheck) != NULL, "Expected %s in %s\n", langcheck, lang);
/* check neither version nor language */
r = MsiGetFileVersionA(path, NULL, NULL, NULL, NULL);
@@ -2553,7 +2551,7 @@ static void test_MsiGetFileVersion(void)
langsz = MAX_PATH;
r = MsiGetFileVersionA(path, NULL, NULL, NULL, &langsz);
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
- ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
+ ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
/* pcchVersionBuf not big enough */
versz = 5;
@@ -2571,7 +2569,7 @@ static void test_MsiGetFileVersion(void)
ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
ok(!strncmp(lang, langcheck, 2),
"Expected first character of %s, got %s\n", langcheck, lang);
- ok(langsz == langchecksz, "Expected %d, got %d\n", langchecksz, langsz);
+ ok(langsz >= langchecksz, "Expected %d >= %d\n", langsz, langchecksz);
HeapFree(GetProcessHeap(), 0, vercheck);
HeapFree(GetProcessHeap(), 0, langcheck);
@@ -2781,7 +2779,7 @@ static void test_MsiGetProductInfo(void)
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
ok(sz == 4, "Expected 4, got %d\n", sz);
- /* lpValueBuf is NULL, pcchValueBuf is too small */
+ /* lpValueBuf is non-NULL, pcchValueBuf is too small */
sz = 2;
lstrcpyA(buf, "apple");
r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
@@ -2789,7 +2787,7 @@ static void test_MsiGetProductInfo(void)
ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
ok(sz == 4, "Expected 4, got %d\n", sz);
- /* lpValueBuf is NULL, pcchValueBuf is exactly 4 */
+ /* lpValueBuf is non-NULL, pcchValueBuf is exactly 4 */
sz = 4;
lstrcpyA(buf, "apple");
r = MsiGetProductInfoA(prodcode, INSTALLPROPERTY_HELPLINK, buf, &sz);
diff --git a/rostests/winetests/msi/package.c b/rostests/winetests/msi/package.c
index 95a2587bf3b..3c3e403fa83 100644
--- a/rostests/winetests/msi/package.c
+++ b/rostests/winetests/msi/package.c
@@ -30,7 +30,7 @@
#include "wine/test.h"
-static const char msifile[] = "winetest.msi";
+static const char msifile[] = "winetest-package.msi";
char CURR_DIR[MAX_PATH];
static UINT (WINAPI *pMsiApplyMultiplePatchesA)(LPCSTR, LPCSTR, LPCSTR);
@@ -2341,9 +2341,9 @@ static void test_states(void)
MSIHANDLE hdb;
INSTALLSTATE state, action;
- static const CHAR msifile2[] = "winetest2.msi";
- static const CHAR msifile3[] = "winetest3.msi";
- static const CHAR msifile4[] = "winetest4.msi";
+ static const CHAR msifile2[] = "winetest2-package.msi";
+ static const CHAR msifile3[] = "winetest3-package.msi";
+ static const CHAR msifile4[] = "winetest4-package.msi";
hdb = create_package_db();
ok ( hdb, "failed to create package database\n" );
@@ -11601,7 +11601,8 @@ static void test_MsiGetProductProperty(void)
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
lstrcpyA(val, path);
- lstrcatA(val, "\\winetest.msi");
+ lstrcatA(val, "\\");
+ lstrcatA(val, msifile);
res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
(const BYTE *)val, lstrlenA(val) + 1);
ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
diff --git a/rostests/winetests/msi/record.c b/rostests/winetests/msi/record.c
index e8dd6f55596..369c855bb4b 100644
--- a/rostests/winetests/msi/record.c
+++ b/rostests/winetests/msi/record.c
@@ -24,7 +24,7 @@
#include "wine/test.h"
-static const char *msifile = "winetest.msi";
+static const char *msifile = "winetest-record.msi";
static BOOL create_temp_file(char *name)
{
@@ -604,6 +604,9 @@ static void test_fieldzero(void)
r = MsiRecordIsNull(rec, 0);
ok(r == FALSE, "Expected FALSE, got %d\n", r);
+ r = MsiCloseHandle(hview);
+ ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n");
+ MsiCloseHandle(rec);
MsiCloseHandle(hdb);
DeleteFileA(msifile);
}
diff --git a/rostests/winetests/msi/suminfo.c b/rostests/winetests/msi/suminfo.c
index f0e7fddc8d2..a0b225b6bd9 100644
--- a/rostests/winetests/msi/suminfo.c
+++ b/rostests/winetests/msi/suminfo.c
@@ -63,9 +63,12 @@
#define PID_MSISOURCE PID_WORDCOUNT
#define PID_MSIRESTRICT PID_CHARCOUNT
+const char *msifile = "winetest-suminfo.msi";
+static const WCHAR msifileW[] = {
+ 'w','i','n','e','t','e','s','t','-','s','u','m','i','n','f','o','.','m','s','i',0 };
+
static void test_suminfo(void)
{
- const char *msifile = "winetest.msi";
MSIHANDLE hdb = 0, hsuminfo;
UINT r, count, type;
DWORD sz;
@@ -284,8 +287,6 @@ static void test_create_database_binary(void)
static const CLSID FMTID_SummaryInformation =
{ 0xf29f85e0, 0x4ff9, 0x1068, {0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9}};
DWORD mode = STGM_CREATE | STGM_READWRITE | STGM_DIRECT | STGM_SHARE_EXCLUSIVE;
- static const WCHAR msifile[] = {
- 'w','i','n','e','t','e','s','t','.','m','s','i',0 };
IPropertySetStorage *pss = NULL;
IPropertyStorage *ps = NULL;
IStorage *stg = NULL;
@@ -295,7 +296,7 @@ static void test_create_database_binary(void)
PROPVARIANT propvar[10];
USHORT data[2] = { 0, 0 };
- r = StgCreateDocfile( msifile, mode, 0, &stg );
+ r = StgCreateDocfile( msifileW, mode, 0, &stg );
ok( r == S_OK, "failed to create database\n");
r = IStorage_SetClass( stg, &CLSID_MsiDatabase );
@@ -386,7 +387,6 @@ static void test_create_database_binary(void)
static void test_summary_binary(void)
{
- const char *msifile = "winetest.msi";
MSIHANDLE hdb = 0, hsuminfo = 0;
UINT r, type, count;
INT ival;
diff --git a/rostests/winetests/mstask/task.c b/rostests/winetests/mstask/task.c
index 328dd76958a..b9dee3536cc 100644
--- a/rostests/winetests/mstask/task.c
+++ b/rostests/winetests/mstask/task.c
@@ -28,33 +28,6 @@ static ITaskScheduler *test_task_scheduler;
static ITask *test_task;
static const WCHAR empty[] = {0};
-/* allocate some tmp string space */
-/* FIXME: this is not 100% thread-safe */
-static char *get_tmp_space(int size)
-{
- static char *list[16];
- static long pos;
- char *ret;
- int idx;
-
- idx = ++pos % (sizeof(list)/sizeof(list[0]));
- if ((ret = realloc(list[idx], size)))
- list[idx] = ret;
- return ret;
-}
-
-static const char *dbgstr_w(LPCWSTR str)
-{
- char *buf;
- int len;
- if(!str)
- return "(null)";
- len = lstrlenW(str) + 1;
- buf = get_tmp_space(len);
- WideCharToMultiByte(CP_ACP, 0, str, -1, buf, len, NULL, NULL);
- return buf;
-}
-
static BOOL setup_task(void)
{
HRESULT hres;
@@ -122,7 +95,7 @@ static void test_SetApplicationName_GetApplicationName(void)
if (hres == S_OK)
{
ok(!lstrcmpiW(stored_name, empty),
- "Got %s, expected empty string\n", dbgstr_w(stored_name));
+ "Got %s, expected empty string\n", wine_dbgstr_w(stored_name));
CoTaskMemFree(stored_name);
}
@@ -130,14 +103,14 @@ static void test_SetApplicationName_GetApplicationName(void)
* the application name that is actually stored */
hres = ITask_SetApplicationName(test_task, non_application_name);
ok(hres == S_OK, "Failed setting name %s: %08x\n",
- dbgstr_w(non_application_name), hres);
+ wine_dbgstr_w(non_application_name), hres);
hres = ITask_GetApplicationName(test_task, &stored_name);
ok(hres == S_OK, "GetApplicationName failed: %08x\n", hres);
if (hres == S_OK)
{
full_name = path_resolve_name(non_application_name);
ok(!lstrcmpiW(stored_name, full_name), "Got %s, expected %s\n",
- dbgstr_w(stored_name), dbgstr_w(full_name));
+ wine_dbgstr_w(stored_name), wine_dbgstr_w(full_name));
CoTaskMemFree(stored_name);
}
@@ -145,21 +118,21 @@ static void test_SetApplicationName_GetApplicationName(void)
* get the stored name */
hres = ITask_SetApplicationName(test_task, notepad_exe);
ok(hres == S_OK, "Failed setting name %s: %08x\n",
- dbgstr_w(notepad_exe), hres);
+ wine_dbgstr_w(notepad_exe), hres);
hres = ITask_GetApplicationName(test_task, &stored_name);
ok(hres == S_OK, "GetApplicationName failed: %08x\n", hres);
if (hres == S_OK)
{
full_name = path_resolve_name(notepad_exe);
ok(!lstrcmpiW(stored_name, full_name), "Got %s, expected %s\n",
- dbgstr_w(stored_name), dbgstr_w(full_name));
+ wine_dbgstr_w(stored_name), wine_dbgstr_w(full_name));
CoTaskMemFree(stored_name);
}
/* Set a valid application name without program type extension and
* then get the stored name */
hres = ITask_SetApplicationName(test_task, notepad);
- ok(hres == S_OK, "Failed setting name %s: %08x\n", dbgstr_w(notepad), hres);
+ ok(hres == S_OK, "Failed setting name %s: %08x\n", wine_dbgstr_w(notepad), hres);
hres = ITask_GetApplicationName(test_task, &stored_name);
ok(hres == S_OK, "GetApplicationName failed: %08x\n", hres);
if (hres == S_OK)
@@ -169,7 +142,7 @@ static void test_SetApplicationName_GetApplicationName(void)
{
full_name = path_resolve_name(notepad);
ok(!lstrcmpiW(stored_name, full_name), "Got %s, expected %s\n",
- dbgstr_w(stored_name), dbgstr_w(full_name));
+ wine_dbgstr_w(stored_name), wine_dbgstr_w(full_name));
}
CoTaskMemFree(stored_name);
}
@@ -179,26 +152,26 @@ static void test_SetApplicationName_GetApplicationName(void)
* actually stored */
hres = ITask_SetApplicationName(test_task, non_application_name);
ok(hres == S_OK, "Failed setting name %s: %08x\n",
- dbgstr_w(non_application_name), hres);
+ wine_dbgstr_w(non_application_name), hres);
hres = ITask_GetApplicationName(test_task, &stored_name);
ok(hres == S_OK, "GetApplicationName failed: %08x\n", hres);
if (hres == S_OK)
{
full_name = path_resolve_name(non_application_name);
ok(!lstrcmpiW(stored_name, full_name), "Got %s, expected %s\n",
- dbgstr_w(stored_name), dbgstr_w(full_name));
+ wine_dbgstr_w(stored_name), wine_dbgstr_w(full_name));
CoTaskMemFree(stored_name);
}
/* Clear application name */
hres = ITask_SetApplicationName(test_task, empty);
- ok(hres == S_OK, "Failed setting name %s: %08x\n", dbgstr_w(empty), hres);
+ ok(hres == S_OK, "Failed setting name %s: %08x\n", wine_dbgstr_w(empty), hres);
hres = ITask_GetApplicationName(test_task, &stored_name);
ok(hres == S_OK, "GetApplicationName failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpiW(stored_name, empty),
- "Got %s, expected empty string\n", dbgstr_w(stored_name));
+ "Got %s, expected empty string\n", wine_dbgstr_w(stored_name));
CoTaskMemFree(stored_name);
}
@@ -257,46 +230,46 @@ static void test_SetParameters_GetParameters(void)
if (hres == S_OK)
{
ok(!lstrcmpW(parameters, empty),
- "Got %s, expected empty string\n", dbgstr_w(parameters));
+ "Got %s, expected empty string\n", wine_dbgstr_w(parameters));
CoTaskMemFree(parameters);
}
/* Set parameters to a simple string */
hres = ITask_SetParameters(test_task, parameters_a);
ok(hres == S_OK, "Failed setting parameters %s: %08x\n",
- dbgstr_w(parameters_a), hres);
+ wine_dbgstr_w(parameters_a), hres);
hres = ITask_GetParameters(test_task, ¶meters);
ok(hres == S_OK, "GetParameters failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(parameters, parameters_a), "Got %s, expected %s\n",
- dbgstr_w(parameters), dbgstr_w(parameters_a));
+ wine_dbgstr_w(parameters), wine_dbgstr_w(parameters_a));
CoTaskMemFree(parameters);
}
/* Update parameters to a different simple string */
hres = ITask_SetParameters(test_task, parameters_b);
ok(hres == S_OK, "Failed setting parameters %s: %08x\n",
- dbgstr_w(parameters_b), hres);
+ wine_dbgstr_w(parameters_b), hres);
hres = ITask_GetParameters(test_task, ¶meters);
ok(hres == S_OK, "GetParameters failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(parameters, parameters_b), "Got %s, expected %s\n",
- dbgstr_w(parameters), dbgstr_w(parameters_b));
+ wine_dbgstr_w(parameters), wine_dbgstr_w(parameters_b));
CoTaskMemFree(parameters);
}
/* Clear parameters */
hres = ITask_SetParameters(test_task, empty);
ok(hres == S_OK, "Failed setting parameters %s: %08x\n",
- dbgstr_w(empty), hres);
+ wine_dbgstr_w(empty), hres);
hres = ITask_GetParameters(test_task, ¶meters);
ok(hres == S_OK, "GetParameters failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(parameters, empty),
- "Got %s, expected empty string\n", dbgstr_w(parameters));
+ "Got %s, expected empty string\n", wine_dbgstr_w(parameters));
CoTaskMemFree(parameters);
}
@@ -327,46 +300,46 @@ static void test_SetComment_GetComment(void)
if (hres == S_OK)
{
ok(!lstrcmpW(comment, empty),
- "Got %s, expected empty string\n", dbgstr_w(comment));
+ "Got %s, expected empty string\n", wine_dbgstr_w(comment));
CoTaskMemFree(comment);
}
/* Set comment to a simple string */
hres = ITask_SetComment(test_task, comment_a);
ok(hres == S_OK, "Failed setting comment %s: %08x\n",
- dbgstr_w(comment_a), hres);
+ wine_dbgstr_w(comment_a), hres);
hres = ITask_GetComment(test_task, &comment);
ok(hres == S_OK, "GetComment failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(comment, comment_a), "Got %s, expected %s\n",
- dbgstr_w(comment), dbgstr_w(comment_a));
+ wine_dbgstr_w(comment), wine_dbgstr_w(comment_a));
CoTaskMemFree(comment);
}
/* Update comment to a different simple string */
hres = ITask_SetComment(test_task, comment_b);
ok(hres == S_OK, "Failed setting comment %s: %08x\n",
- dbgstr_w(comment_b), hres);
+ wine_dbgstr_w(comment_b), hres);
hres = ITask_GetComment(test_task, &comment);
ok(hres == S_OK, "GetComment failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(comment, comment_b), "Got %s, expected %s\n",
- dbgstr_w(comment), dbgstr_w(comment_b));
+ wine_dbgstr_w(comment), wine_dbgstr_w(comment_b));
CoTaskMemFree(comment);
}
/* Clear comment */
hres = ITask_SetComment(test_task, empty);
ok(hres == S_OK, "Failed setting comment %s: %08x\n",
- dbgstr_w(empty), hres);
+ wine_dbgstr_w(empty), hres);
hres = ITask_GetComment(test_task, &comment);
ok(hres == S_OK, "GetComment failed: %08x\n", hres);
if (hres == S_OK)
{
ok(!lstrcmpW(comment, empty),
- "Got %s, expected empty string\n", dbgstr_w(comment));
+ "Got %s, expected empty string\n", wine_dbgstr_w(comment));
CoTaskMemFree(comment);
}
@@ -477,8 +450,8 @@ static void test_SetAccountInformation_GetAccountInformation(void)
if (hres == S_OK)
{
ok(!lstrcmpW(account_name, dummy_account_name),
- "Got %s, expected %s\n", dbgstr_w(account_name),
- dbgstr_w(dummy_account_name));
+ "Got %s, expected %s\n", wine_dbgstr_w(account_name),
+ wine_dbgstr_w(dummy_account_name));
CoTaskMemFree(account_name);
}
@@ -496,8 +469,8 @@ static void test_SetAccountInformation_GetAccountInformation(void)
if (hres == S_OK)
{
ok(!lstrcmpW(account_name, dummy_account_name_b),
- "Got %s, expected %s\n", dbgstr_w(account_name),
- dbgstr_w(dummy_account_name_b));
+ "Got %s, expected %s\n", wine_dbgstr_w(account_name),
+ wine_dbgstr_w(dummy_account_name_b));
CoTaskMemFree(account_name);
}
@@ -512,7 +485,7 @@ static void test_SetAccountInformation_GetAccountInformation(void)
if (hres == S_OK)
{
ok(!lstrcmpW(account_name, empty),
- "Got %s, expected empty string\n", dbgstr_w(account_name));
+ "Got %s, expected empty string\n", wine_dbgstr_w(account_name));
CoTaskMemFree(account_name);
}
diff --git a/rostests/winetests/msvcrt/cpp.c b/rostests/winetests/msvcrt/cpp.c
index d640d674e3e..106ef73ce27 100644
--- a/rostests/winetests/msvcrt/cpp.c
+++ b/rostests/winetests/msvcrt/cpp.c
@@ -1032,6 +1032,8 @@ static void test_demangle(void)
/* 111 */ {"?f@T@@QAEHQCY1BE@BO@D@Z", "public: int __thiscall T::f(char (volatile * const)[20][30])"},
/* 112 */ {"?f@T@@QAEHQAY2BE@BO@CI@D@Z", "public: int __thiscall T::f(char (* const)[20][30][40])"},
/* 113 */ {"?f@T@@QAEHQAY1BE@BO@$$CBD@Z", "public: int __thiscall T::f(char const (* const)[20][30])"},
+/* 114 */ {"??0?$Foo@U?$vector_c@H$00$01$0?1$0A@$0A@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@$0HPPPPPPP@@mpl@boost@@@@QAE@XZ",
+ "public: __thiscall Foo >::Foo >(void)"},
};
int i, num_test = (sizeof(test)/sizeof(test[0]));
diff --git a/rostests/winetests/msvcrt/file.c b/rostests/winetests/msvcrt/file.c
index 8afc0e1f593..3159fdc6d40 100644
--- a/rostests/winetests/msvcrt/file.c
+++ b/rostests/winetests/msvcrt/file.c
@@ -439,6 +439,7 @@ static void test_fgetc( void )
ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_fputc( void )
@@ -463,6 +464,7 @@ static void test_fputc( void )
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_flsbuf( void )
@@ -517,6 +519,7 @@ static void test_flsbuf( void )
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_fgetwc( void )
@@ -634,6 +637,7 @@ static void test_fgetwc( void )
free(mytextW);
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_ctrlz( void )
@@ -681,6 +685,7 @@ static void test_ctrlz( void )
ok(feof(tempfh), "did not get EOF\n");
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_file_put_get( void )
@@ -730,6 +735,7 @@ static void test_file_put_get( void )
free(mytextW);
fclose(tempfh);
unlink(tempf);
+ free(tempf);
}
static void test_file_write_read( void )
@@ -806,6 +812,7 @@ static void test_file_write_read( void )
ret = unlink(tempf);
ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
+ free(tempf);
tempf=_tempnam(".","wne");
tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,0);
@@ -833,6 +840,7 @@ static void test_file_write_read( void )
"Can't chmod '%s' to read-write: %d\n", tempf, errno);
ret = unlink(tempf);
ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
+ free(tempf);
}
static void test_file_inherit_child(const char* fd_s)
@@ -1080,6 +1088,7 @@ static void test_chsize( void )
_close( fd );
_unlink( tempfile );
+ free( tempfile );
}
static void test_fopen_fclose_fcloseall( void )
diff --git a/rostests/winetests/msvcrt/msvcrt.rbuild b/rostests/winetests/msvcrt/msvcrt.rbuild
index ca047facb44..1657252b945 100644
--- a/rostests/winetests/msvcrt/msvcrt.rbuild
+++ b/rostests/winetests/msvcrt/msvcrt.rbuild
@@ -29,6 +29,7 @@
heap.c
printf.c
scanf.c
+ signal.c
string.c
testlist.c
time.c
diff --git a/rostests/winetests/msvcrt/signal.c b/rostests/winetests/msvcrt/signal.c
new file mode 100644
index 00000000000..d33498bd537
--- /dev/null
+++ b/rostests/winetests/msvcrt/signal.c
@@ -0,0 +1,48 @@
+/*
+ * Unit test suite for signal function.
+ *
+ * Copyright 2009 Peter Rosin
+ *
+ * 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 "wine/test.h"
+#include
+#include
+
+static int test_value = 0;
+
+static void __cdecl sighandler(int signum)
+{
+ ++test_value;
+}
+
+static void test_signal(void)
+{
+ void (__cdecl *old)(int);
+ int res;
+
+ old = signal(SIGBREAK, sighandler);
+ ok(old != SIG_ERR, "Failed to install signal handler for SIGBREAK\n");
+ test_value = 0;
+ res = raise(SIGBREAK);
+ ok(res == 0, "Failed to raise SIGBREAK\n");
+ ok(test_value == 1, "SIGBREAK handler not invoked\n");
+}
+
+START_TEST(signal)
+{
+ test_signal();
+}
diff --git a/rostests/winetests/msvcrt/string.c b/rostests/winetests/msvcrt/string.c
index 7d4eb88effb..585930760a2 100644
--- a/rostests/winetests/msvcrt/string.c
+++ b/rostests/winetests/msvcrt/string.c
@@ -51,6 +51,7 @@ static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src);
static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src);
static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count);
static int (__cdecl *p_wcscpy_s)(wchar_t *wcDest, size_t size, const wchar_t *wcSrc);
+static int (__cdecl *p_wcsupr_s)(wchar_t *str, size_t size);
static int *p__mb_cur_max;
static unsigned char *p_mbctype;
@@ -597,6 +598,93 @@ static void test_wcscpy_s(void)
ok(szDestShort[0] == 0, "szDestShort[0] not 0\n");
}
+static void test__wcsupr_s(void)
+{
+ static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
+ 'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
+ static const WCHAR expectedString[] = {'M', 'I', 'X', 'E', 'D', 'L', 'O',
+ 'W', 'E', 'R', 'U', 'P', 'P', 'E',
+ 'R', 0};
+ WCHAR testBuffer[2*sizeof(mixedString)/sizeof(WCHAR)];
+ int ret;
+
+ if (!p_wcsupr_s)
+ {
+ win_skip("_wcsupr_s not found\n");
+ return;
+ }
+
+ /* Test NULL input string and invalid size. */
+ errno = EBADF;
+ ret = p_wcsupr_s(NULL, 0);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+ /* Test NULL input string and valid size. */
+ errno = EBADF;
+ ret = p_wcsupr_s(NULL, sizeof(testBuffer)/sizeof(WCHAR));
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+ /* Test empty string with zero size. */
+ errno = EBADF;
+ testBuffer[0] = '\0';
+ ret = p_wcsupr_s(testBuffer, 0);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
+
+ /* Test empty string with size of one. */
+ testBuffer[0] = '\0';
+ ret = p_wcsupr_s(testBuffer, 1);
+ ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
+ ok(testBuffer[0] == '\0', "Expected the buffer to be unchanged\n");
+
+ /* Test one-byte buffer with zero size. */
+ errno = EBADF;
+ testBuffer[0] = 'x';
+ ret = p_wcsupr_s(testBuffer, 0);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
+
+ /* Test one-byte buffer with size of one. */
+ errno = EBADF;
+ testBuffer[0] = 'x';
+ ret = p_wcsupr_s(testBuffer, 1);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
+
+ /* Test invalid size. */
+ wcscpy(testBuffer, mixedString);
+ errno = EBADF;
+ ret = p_wcsupr_s(testBuffer, 0);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
+
+ /* Test normal string uppercasing. */
+ wcscpy(testBuffer, mixedString);
+ ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR));
+ ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
+ ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
+
+ /* Test uppercasing with a shorter buffer size count. */
+ wcscpy(testBuffer, mixedString);
+ errno = EBADF;
+ ret = p_wcsupr_s(testBuffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
+ ok(ret == EINVAL, "Expected _wcsupr_s to fail with EINVAL, got %d\n", ret);
+ ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+ ok(testBuffer[0] == '\0', "Expected the first buffer character to be null\n");
+
+ /* Test uppercasing with a longer buffer size count. */
+ wcscpy(testBuffer, mixedString);
+ ret = p_wcsupr_s(testBuffer, sizeof(testBuffer)/sizeof(WCHAR));
+ ok(ret == 0, "Expected _wcsupr_s to succeed, got %d\n", ret);
+ ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
+}
+
static void test_mbcjisjms(void)
{
/* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
@@ -721,6 +809,7 @@ START_TEST(string)
pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" );
p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" );
p_wcscpy_s = (void *)GetProcAddress( hMsvcrt,"wcscpy_s" );
+ p_wcsupr_s = (void *)GetProcAddress( hMsvcrt,"_wcsupr_s" );
/* MSVCRT memcpy behaves like memmove for overlapping moves,
MFC42 CString::Insert seems to rely on that behaviour */
@@ -746,5 +835,6 @@ START_TEST(string)
test_mbcjisjms();
test_strtok();
test_wcscpy_s();
+ test__wcsupr_s();
test_strtol();
}
diff --git a/rostests/winetests/msvcrt/testlist.c b/rostests/winetests/msvcrt/testlist.c
index db41945d89d..4bd436d9dea 100644
--- a/rostests/winetests/msvcrt/testlist.c
+++ b/rostests/winetests/msvcrt/testlist.c
@@ -15,6 +15,7 @@ extern void func_headers(void);
extern void func_heap(void);
extern void func_printf(void);
extern void func_scanf(void);
+extern void func_signal(void);
extern void func_string(void);
extern void func_time(void);
@@ -29,6 +30,7 @@ const struct test winetest_testlist[] =
{ "heap", func_heap },
{ "printf", func_printf },
{ "scanf", func_scanf },
+ { "signal", func_signal },
{ "string", func_string },
{ "time", func_time },
{ 0, 0 }
diff --git a/rostests/winetests/msvcrtd/debug.c b/rostests/winetests/msvcrtd/debug.c
index fbfcdc5ea4d..71f6e4c3966 100644
--- a/rostests/winetests/msvcrtd/debug.c
+++ b/rostests/winetests/msvcrtd/debug.c
@@ -30,7 +30,7 @@
/**********************************************************************/
-static void * (*pMSVCRTD_operator_new_dbg)(unsigned long, int, const char *, int) = NULL;
+static void * (__cdecl *pMSVCRTD_operator_new_dbg)(size_t, int, const char *, int) = NULL;
/* Some exports are only available in later versions */
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(hModule,y)
diff --git a/rostests/winetests/msxml3/domdoc.c b/rostests/winetests/msxml3/domdoc.c
index de78b6550ce..87ad9b563d6 100644
--- a/rostests/winetests/msxml3/domdoc.c
+++ b/rostests/winetests/msxml3/domdoc.c
@@ -3085,6 +3085,8 @@ static void test_xmlTypes(void)
IXMLDOMNode *pNextChild = (IXMLDOMNode *)0x1;
VARIANT var;
+ VariantInit(&var);
+
hr = IXMLDOMCDATASection_QueryInterface(pCDataSec, &IID_IXMLDOMElement, (LPVOID*)&pElement);
ok(hr == E_NOINTERFACE, "ret %08x\n", hr);
@@ -3155,7 +3157,8 @@ static void test_xmlTypes(void)
/* test get nodeValue */
hr = IXMLDOMCDATASection_get_nodeValue(pCDataSec, &var);
ok(hr == S_OK, "ret %08x\n", hr );
- ok( !lstrcmpW( str, _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
+ ok(V_VT(&var) == VT_BSTR, "got vt %04x\n", V_VT(&var));
+ ok( !lstrcmpW( V_BSTR(&var), _bstr_("This &is a ; test <>\\") ), "incorrect text string\n");
VariantClear(&var);
/* test get data */
diff --git a/rostests/winetests/netapi32/apibuf.c b/rostests/winetests/netapi32/apibuf.c
index de8613b8fb3..28a1e339ee3 100644
--- a/rostests/winetests/netapi32/apibuf.c
+++ b/rostests/winetests/netapi32/apibuf.c
@@ -59,6 +59,8 @@ static void run_apibuf_tests(void)
/* border reallocate cases */
ok(pNetApiBufferReallocate(0, 1500, &p) == NERR_Success, "Reallocate with OldBuffer = NULL failed\n");
ok(p != NULL, "No memory got allocated\n");
+ ok(pNetApiBufferFree(p) == NERR_Success, "NetApiBufferFree failed\n");
+
ok(pNetApiBufferAllocate(1024, &p) == NERR_Success, "Memory not reserved\n");
ok(pNetApiBufferReallocate(p, 0, &p) == NERR_Success, "Not freed\n");
ok(p == NULL, "Pointer not cleared\n");
diff --git a/rostests/winetests/ntdll/om.c b/rostests/winetests/ntdll/om.c
index 033013b8c78..489d1f23427 100644
--- a/rostests/winetests/ntdll/om.c
+++ b/rostests/winetests/ntdll/om.c
@@ -63,8 +63,8 @@ static void test_case_sensitive (void)
ok(status == STATUS_SUCCESS, "Failed to create Mutant(%08x)\n", status);
status = pNtCreateEvent(&Event, GENERIC_ALL, &attr, FALSE, FALSE);
- ok(status == STATUS_OBJECT_NAME_COLLISION,
- "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
+ ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
+ "NtCreateEvent should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
pRtlInitUnicodeString(&str, buffer2);
InitializeObjectAttributes(&attr, &str, 0, 0, NULL);
@@ -82,8 +82,8 @@ static void test_case_sensitive (void)
pRtlInitUnicodeString(&str, buffer4);
InitializeObjectAttributes(&attr, &str, OBJ_CASE_INSENSITIVE, 0, NULL);
status = pNtCreateMutant(&Mutant, GENERIC_ALL, &attr, FALSE);
- ok(status == STATUS_OBJECT_NAME_COLLISION,
- "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION got(%08x)\n", status);
+ ok(status == STATUS_OBJECT_NAME_COLLISION || status == STATUS_OBJECT_TYPE_MISMATCH,
+ "NtCreateMutant should have failed with STATUS_OBJECT_NAME_COLLISION or STATUS_OBJECT_TYPE_MISMATCH got (%08x)\n", status);
status = pNtCreateEvent(&h, GENERIC_ALL, &attr, FALSE, FALSE);
ok(status == STATUS_OBJECT_NAME_COLLISION,
diff --git a/rostests/winetests/ntdll/rtlbitmap.c b/rostests/winetests/ntdll/rtlbitmap.c
index fc7f6c55fc9..d24f0af8be6 100755
--- a/rostests/winetests/ntdll/rtlbitmap.c
+++ b/rostests/winetests/ntdll/rtlbitmap.c
@@ -413,7 +413,7 @@ static void test_RtlFindClearBitsAndSet(void)
static void test_RtlFindMostSignificantBit(void)
{
int i;
- CCHAR cPos;
+ signed char cPos;
ULONGLONG ulLong;
if (!pRtlFindMostSignificantBit)
@@ -442,7 +442,7 @@ static void test_RtlFindMostSignificantBit(void)
static void test_RtlFindLeastSignificantBit(void)
{
int i;
- CCHAR cPos;
+ signed char cPos;
ULONGLONG ulLong;
if (!pRtlFindLeastSignificantBit)
diff --git a/rostests/winetests/ntdll/rtlstr.c b/rostests/winetests/ntdll/rtlstr.c
index df01cf314d0..ba7f663b6c9 100755
--- a/rostests/winetests/ntdll/rtlstr.c
+++ b/rostests/winetests/ntdll/rtlstr.c
@@ -46,6 +46,7 @@ static NTSTATUS (WINAPI *pRtlDuplicateUnicodeString)(long, UNICODE_STRING *, UNI
static BOOLEAN (WINAPI *pRtlEqualUnicodeString)(const UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
static NTSTATUS (WINAPI *pRtlFindCharInUnicodeString)(int, const UNICODE_STRING *, const UNICODE_STRING *, USHORT *);
static VOID (WINAPI *pRtlFreeAnsiString)(PSTRING);
+static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);
static VOID (WINAPI *pRtlInitAnsiString)(PSTRING, LPCSTR);
static VOID (WINAPI *pRtlInitString)(PSTRING, LPCSTR);
static VOID (WINAPI *pRtlInitUnicodeString)(PUNICODE_STRING, LPCWSTR);
@@ -65,7 +66,6 @@ static NTSTATUS (WINAPI *pRtlStringFromGUID)(const GUID*, UNICODE_STRING*);
static BOOLEAN (WINAPI *pRtlIsTextUnicode)(LPVOID, INT, INT *);
/*static VOID (WINAPI *pRtlFreeOemString)(PSTRING);*/
-/*static VOID (WINAPI *pRtlFreeUnicodeString)(PUNICODE_STRING);*/
/*static VOID (WINAPI *pRtlCopyUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *);*/
/*static VOID (WINAPI *pRtlEraseUnicodeString)(UNICODE_STRING *);*/
/*static LONG (WINAPI *pRtlCompareString)(const STRING *,const STRING *,BOOLEAN);*/
@@ -114,6 +114,7 @@ static void InitFunctionPtrs(void)
pRtlEqualUnicodeString = (void *)GetProcAddress(hntdll, "RtlEqualUnicodeString");
pRtlFindCharInUnicodeString = (void *)GetProcAddress(hntdll, "RtlFindCharInUnicodeString");
pRtlFreeAnsiString = (void *)GetProcAddress(hntdll, "RtlFreeAnsiString");
+ pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString");
pRtlInitAnsiString = (void *)GetProcAddress(hntdll, "RtlInitAnsiString");
pRtlInitString = (void *)GetProcAddress(hntdll, "RtlInitString");
pRtlInitUnicodeString = (void *)GetProcAddress(hntdll, "RtlInitUnicodeString");
@@ -467,6 +468,7 @@ static void test_RtlDuplicateUnicodeString(void)
ok(memcmp(dest_str.Buffer, res_str.Buffer, dupl_ustr[test_num].res_buf_size) == 0,
"(test %d): RtlDuplicateUnicodeString(%d, source, dest) has destination \"%s\" expected \"%s\"\n",
test_num, dupl_ustr[test_num].add_nul, dest_ansi_str.Buffer, dupl_ustr[test_num].res_buf);
+ if(result == STATUS_SUCCESS) pRtlFreeUnicodeString(&dest_str);
} else {
ok(dest_str.Buffer == NULL && dupl_ustr[test_num].res_buf == NULL,
"(test %d): RtlDuplicateUnicodeString(%d, source, dest) has destination %p expected %p\n",
@@ -794,6 +796,8 @@ static void test_RtlUnicodeStringToAnsiString(void)
ok(memcmp(ansi_str.Buffer, ustr2astr[test_num].res_buf, ustr2astr[test_num].res_buf_size) == 0,
"(test %d): RtlUnicodeStringToAnsiString(ansi, uni, %d) has ansi \"%s\" expected \"%s\"\n",
test_num, ustr2astr[test_num].doalloc, ansi_str.Buffer, ustr2astr[test_num].res_buf);
+ if(result == STATUS_SUCCESS && ustr2astr[test_num].doalloc)
+ pRtlFreeAnsiString(&ansi_str);
}
}
@@ -1850,6 +1854,7 @@ static void test_RtlStringFromGUID(void)
ret = pRtlStringFromGUID(&IID_Endianess, &str);
ok(ret == 0, "expected ret=0, got 0x%0x\n", ret);
ok(str.Buffer && !lstrcmpiW(str.Buffer, szGuid), "Endianess broken\n");
+ pRtlFreeUnicodeString(&str);
}
START_TEST(rtlstr)
diff --git a/rostests/winetests/rsaenh/rsaenh.c b/rostests/winetests/rsaenh/rsaenh.c
index 5a3fafd2fbc..a78eec58f49 100644
--- a/rostests/winetests/rsaenh/rsaenh.c
+++ b/rostests/winetests/rsaenh/rsaenh.c
@@ -2093,6 +2093,7 @@ static void test_rsa_round_trip(void)
ok(dataLen == sizeof(test_string), "unexpected size %d\n", dataLen);
ok(!memcmp(data, test_string, sizeof(test_string)), "unexpected value\n");
}
+ CryptDestroyKey(keyExchangeKey);
CryptReleaseContext(prov, 0);
CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
@@ -2334,6 +2335,7 @@ static void test_null_provider(void)
ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
result = CryptGenKey(prov, CALG_RSA_SIGN, 0, &key);
ok(result, "CryptGenKey with CALG_RSA_SIGN failed with error %08x\n", GetLastError());
+ CryptDestroyKey(key);
result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
ok(!result, "expected CryptGetUserKey to fail\n");
result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
@@ -2350,11 +2352,12 @@ static void test_null_provider(void)
ok(result, "CryptAcquireContext failed: %08x\n", GetLastError());
result = CryptGenKey(prov, CALG_RSA_KEYX, 0, &key);
ok(result, "CryptGenKey with CALG_RSA_KEYX failed with error %08x\n", GetLastError());
+ CryptDestroyKey(key);
result = CryptGetUserKey(prov, AT_KEYEXCHANGE, &key);
ok(result, "CryptGetUserKey with AT_KEYEXCHANGE failed: %08x\n", GetLastError());
+ CryptDestroyKey(key);
result = CryptGetUserKey(prov, AT_SIGNATURE, &key);
ok(!result, "expected CryptGetUserKey to fail\n");
- CryptDestroyKey(key);
CryptReleaseContext(prov, 0);
CryptAcquireContext(&prov, szContainer, NULL, PROV_RSA_FULL,
diff --git a/rostests/winetests/setupapi/install.c b/rostests/winetests/setupapi/install.c
index 5361238fb3b..668b2c2565b 100644
--- a/rostests/winetests/setupapi/install.c
+++ b/rostests/winetests/setupapi/install.c
@@ -35,6 +35,7 @@
#include "wine/test.h"
static const char inffile[] = "test.inf";
+static const WCHAR inffileW[] = {'t','e','s','t','.','i','n','f',0};
static char CURR_DIR[MAX_PATH];
/* Notes on InstallHinfSectionA/W:
@@ -52,6 +53,7 @@ static char CURR_DIR[MAX_PATH];
static void (WINAPI *pInstallHinfSectionA)(HWND, HINSTANCE, LPCSTR, INT);
static void (WINAPI *pInstallHinfSectionW)(HWND, HINSTANCE, LPCWSTR, INT);
+static BOOL (WINAPI *pSetupGetInfFileListW)(PCWSTR, DWORD, PWSTR, DWORD, PDWORD);
/*
* Helpers
@@ -466,6 +468,177 @@ cleanup:
DeleteFile(inffile);
}
+static void test_inffilelist(void)
+{
+ static const char inffile2[] = "test2.inf";
+ static const WCHAR inffile2W[] = {'t','e','s','t','2','.','i','n','f',0};
+ static const char invalid_inf[] = "invalid.inf";
+ static const WCHAR invalid_infW[] = {'i','n','v','a','l','i','d','.','i','n','f',0};
+ static const char *inf =
+ "[Version]\n"
+ "Signature=\"$Chicago$\"";
+ static const char *inf2 =
+ "[Version]\n"
+ "Signature=\"$CHICAGO$\"";
+ static const char *infNT =
+ "[Version]\n"
+ "Signature=\"$WINDOWS NT$\"";
+
+ WCHAR *p, *ptr;
+ char dirA[MAX_PATH];
+ WCHAR dir[MAX_PATH] = { 0 };
+ WCHAR buffer[MAX_PATH] = { 0 };
+ DWORD expected, outsize;
+ BOOL ret;
+
+ if(!pSetupGetInfFileListW)
+ {
+ win_skip("SetupGetInfFileListW not present\n");
+ return;
+ }
+
+ /* NULL means %windir%\\inf
+ * get the value as reference
+ */
+ expected = 0;
+ SetLastError(0xdeadbeef);
+ ret = pSetupGetInfFileListW(NULL, INF_STYLE_WIN4, NULL, 0, &expected);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ win_skip("SetupGetInfFileListW not implemented\n");
+ return;
+ }
+ ok(ret, "expected SetupGetInfFileListW to succeed! Error: %d\n", GetLastError());
+ ok(expected > 0, "expected required buffersize to be at least 1\n");
+
+ /* check if an empty string doesn't behaves like NULL */
+ outsize = 0;
+ SetLastError(0xdeadbeef);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
+ ok(!ret, "expected SetupGetInfFileListW to fail!\n");
+
+ /* create a private directory, the temp directory may contain some
+ * inf files left over from old installations
+ */
+ if (!GetTempFileNameA(CURR_DIR, "inftest", 1, dirA))
+ {
+ win_skip("GetTempFileNameA failed with error %d\n", GetLastError());
+ return;
+ }
+ if (!CreateDirectoryA(dirA, NULL ))
+ {
+ win_skip("CreateDirectoryA(%s) failed with error %d\n", dirA, GetLastError());
+ return;
+ }
+ if (!SetCurrentDirectoryA(dirA))
+ {
+ win_skip("SetCurrentDirectoryA failed with error %d\n", GetLastError());
+ RemoveDirectoryA(dirA);
+ return;
+ }
+
+ MultiByteToWideChar(CP_ACP, 0, dirA, -1, dir, MAX_PATH);
+ /* check a not existing directory
+ */
+ ptr = dir + lstrlenW(dir);
+ MultiByteToWideChar(CP_ACP, 0, "\\not_existent", -1, ptr, MAX_PATH - lstrlenW(dir));
+ outsize = 0xffffffff;
+ SetLastError(0xdeadbeef);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(outsize == 1, "expected required buffersize to be 1, got %d\n", outsize);
+ ok(ERROR_PATH_NOT_FOUND == GetLastError(),
+ "expected error ERROR_PATH_NOT_FOUND, got %d\n", GetLastError());
+
+ create_inf_file(inffile, inf);
+ create_inf_file(inffile2, inf);
+ create_inf_file(invalid_inf, "This content does not match the inf file format");
+
+ /* pass a filename instead of a directory
+ */
+ *ptr = '\\';
+ MultiByteToWideChar(CP_ACP, 0, invalid_inf, -1, ptr+1, MAX_PATH - lstrlenW(dir));
+ outsize = 0xffffffff;
+ SetLastError(0xdeadbeef);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
+ ok(!ret, "expected SetupGetInfFileListW to fail!\n");
+ ok(ERROR_DIRECTORY == GetLastError(),
+ "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
+
+ /* make the filename look like directory
+ */
+ dir[1 + lstrlenW(dir)] = 0;
+ dir[lstrlenW(dir)] = '\\';
+ SetLastError(0xdeadbeef);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, NULL, 0, &outsize);
+ ok(!ret, "expected SetupGetInfFileListW to fail!\n");
+ ok(ERROR_DIRECTORY == GetLastError(),
+ "expected error ERROR_DIRECTORY, got %d\n", GetLastError());
+
+ /* now check the buffer content of a vaild call
+ */
+ *ptr = 0;
+ expected = 3 + strlen(inffile) + strlen(inffile2);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
+ expected, outsize);
+ for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
+ ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
+ "unexpected filename %s\n",wine_dbgstr_w(p));
+
+ /* upper case value
+ */
+ create_inf_file(inffile2, inf2);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
+ expected, outsize);
+ for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
+ ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
+ "unexpected filename %s\n",wine_dbgstr_w(p));
+
+ /* signature Windows NT is also inf style win4
+ */
+ create_inf_file(inffile2, infNT);
+ expected = 3 + strlen(inffile) + strlen(inffile2);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_WIN4, buffer, MAX_PATH, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
+ expected, outsize);
+ for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
+ ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW),
+ "unexpected filename %s\n",wine_dbgstr_w(p));
+
+ /* old style
+ */
+ expected = 2 + strlen(invalid_inf);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_OLDNT, buffer, MAX_PATH, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
+ expected, outsize);
+ for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
+ ok(!lstrcmpW(p,invalid_infW), "unexpected filename %s\n",wine_dbgstr_w(p));
+
+ /* mixed style
+ */
+ expected = 4 + strlen(inffile) + strlen(inffile2) + strlen(invalid_inf);
+ ret = pSetupGetInfFileListW(dir, INF_STYLE_OLDNT | INF_STYLE_WIN4, buffer,
+ MAX_PATH, &outsize);
+ ok(ret, "expected SetupGetInfFileListW to succeed!\n");
+ ok(expected == outsize, "expected required buffersize to be %d, got %d\n",
+ expected, outsize);
+ for(p = buffer; lstrlenW(p) && (outsize > (p - buffer)); p+=lstrlenW(p) + 1)
+ ok(!lstrcmpW(p,inffile2W) || !lstrcmpW(p,inffileW) || !lstrcmpW(p,invalid_infW),
+ "unexpected filename %s\n",wine_dbgstr_w(p));
+
+ DeleteFile(inffile);
+ DeleteFile(inffile2);
+ DeleteFile(invalid_inf);
+ SetCurrentDirectoryA(CURR_DIR);
+ RemoveDirectoryA(dirA);
+}
+
START_TEST(install)
{
HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
@@ -483,6 +656,8 @@ START_TEST(install)
pInstallHinfSectionA = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionA");
pInstallHinfSectionW = (void *)GetProcAddress(hsetupapi, "InstallHinfSectionW");
+ pSetupGetInfFileListW = (void *)GetProcAddress(hsetupapi, "SetupGetInfFileListW");
+
if (pInstallHinfSectionA)
{
/* Check if pInstallHinfSectionA sets last error or is a stub (as on WinXP) */
@@ -519,5 +694,7 @@ START_TEST(install)
test_profile_items();
}
+ test_inffilelist();
+
SetCurrentDirectory(prev_path);
}
diff --git a/rostests/winetests/setupapi/misc.c b/rostests/winetests/setupapi/misc.c
index e110e221e8b..a3abde46746 100644
--- a/rostests/winetests/setupapi/misc.c
+++ b/rostests/winetests/setupapi/misc.c
@@ -46,6 +46,7 @@ static CHAR CURR_DIR[MAX_PATH];
static BOOL (WINAPI *pSetupGetFileCompressionInfoExA)(PCSTR, PSTR, DWORD, PDWORD, PDWORD, PDWORD, PUINT);
static BOOL (WINAPI *pSetupCopyOEMInfA)(PCSTR, PCSTR, DWORD, DWORD, PSTR, DWORD, PDWORD, PSTR *);
static BOOL (WINAPI *pSetupQueryInfOriginalFileInformationA)(PSP_INF_INFORMATION, UINT, PSP_ALTPLATFORM_INFO, PSP_ORIGINAL_FILE_INFO_A);
+static BOOL (WINAPI *pSetupUninstallOEMInfA)(PCSTR, DWORD, PVOID);
static void create_inf_file(LPCSTR filename)
{
@@ -196,21 +197,23 @@ static void test_SetupCopyOEMInf(void)
/* try a relative SourceInfFileName */
SetLastError(0xdeadbeef);
res = pSetupCopyOEMInfA(tmpfile, NULL, 0, SP_COPY_NOOVERWRITE, NULL, 0, NULL, NULL);
- ok(res == FALSE, "Expected FALSE, got %d\n", res);
- if (GetLastError() == ERROR_WRONG_INF_TYPE)
+ ok(res == FALSE ||
+ broken(res == TRUE), /* Win98 */
+ "Expected FALSE, got %d\n", res);
+ if (GetLastError() == ERROR_WRONG_INF_TYPE || GetLastError() == ERROR_UNSUPPORTED_TYPE /* Win7 */)
{
/* FIXME:
* Vista needs a [Manufacturer] entry in the inf file. Doing this will give some
* popups during the installation though as it also needs a catalog file (signed?).
*/
- win_skip("Needs a different inf file on Vista/W2K8\n");
+ win_skip("Needs a different inf file on Vista+\n");
DeleteFile(tmpfile);
return;
}
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
- GetLastError() == ERROR_FILE_EXISTS, /* Win98 */
- "Expected ERROR_FILE_NOT_FOUND or ERROR_FILE_EXISTS, got %d\n", GetLastError());
+ broken(GetLastError() == ERROR_SUCCESS), /* Win98 */
+ "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
ok(file_exists(tmpfile), "Expected tmpfile to exist\n");
/* try SP_COPY_REPLACEONLY, dest does not exist */
@@ -306,6 +309,24 @@ static void test_SetupCopyOEMInf(void)
ok(res == TRUE, "Expected TRUE, got %d\n", res);
ok(GetLastError() == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", GetLastError());
ok(!file_exists(path), "Expected source inf to not exist\n");
+
+ if (pSetupUninstallOEMInfA)
+ {
+ char *destfile = strrchr(dest, '\\') + 1;
+
+ SetLastError(0xdeadbeef);
+ ok(pSetupUninstallOEMInfA(destfile, 0, NULL), "Failed to uninstall '%s' : %d\n", destfile, GetLastError());
+ }
+ else
+ {
+ /* Win9x/WinMe */
+ SetLastError(0xdeadbeef);
+ ok(DeleteFileA(dest), "Failed to delete file '%s' : %d\n", dest, GetLastError());
+
+ /* On WinMe we also need to remove the .pnf file */
+ *(strrchr(dest, '.') + 1) = 'p';
+ DeleteFileA(dest);
+ }
}
static void create_source_file(LPSTR filename, const BYTE *data, DWORD size)
@@ -581,6 +602,32 @@ static void test_SetupDecompressOrCopyFile(void)
DeleteFileA(source);
}
+static void test_SetupUninstallOEMInf(void)
+{
+ BOOL ret;
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupUninstallOEMInfA(NULL, 0, NULL);
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupUninstallOEMInfA("", 0, NULL);
+ todo_wine
+ {
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
+ }
+
+ SetLastError(0xdeadbeef);
+ ret = pSetupUninstallOEMInfA("nonexistent.inf", 0, NULL);
+ todo_wine
+ {
+ ok(!ret, "Expected failure\n");
+ ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
+ }
+}
+
START_TEST(misc)
{
HMODULE hsetupapi = GetModuleHandle("setupapi.dll");
@@ -588,6 +635,7 @@ START_TEST(misc)
pSetupGetFileCompressionInfoExA = (void*)GetProcAddress(hsetupapi, "SetupGetFileCompressionInfoExA");
pSetupCopyOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupCopyOEMInfA");
pSetupQueryInfOriginalFileInformationA = (void*)GetProcAddress(hsetupapi, "SetupQueryInfOriginalFileInformationA");
+ pSetupUninstallOEMInfA = (void*)GetProcAddress(hsetupapi, "SetupUninstallOEMInfA");
GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
@@ -604,4 +652,9 @@ START_TEST(misc)
win_skip("SetupGetFileCompressionInfoExA is not available\n");
test_SetupDecompressOrCopyFile();
+
+ if (pSetupUninstallOEMInfA)
+ test_SetupUninstallOEMInf();
+ else
+ win_skip("SetupUninstallOEMInfA is not available\n");
}
diff --git a/rostests/winetests/setupapi/parser.c b/rostests/winetests/setupapi/parser.c
index 06bffaf13bb..30ffea10831 100644
--- a/rostests/winetests/setupapi/parser.c
+++ b/rostests/winetests/setupapi/parser.c
@@ -32,14 +32,18 @@
/* function pointers */
static HMODULE hSetupAPI;
-static LPCWSTR (WINAPI *pSetupGetField)(PINFCONTEXT,DWORD);
+static LPCSTR (WINAPI *pSetupGetFieldA)(PINFCONTEXT,DWORD);
+static LPCWSTR (WINAPI *pSetupGetFieldW)(PINFCONTEXT,DWORD);
static BOOL (WINAPI *pSetupEnumInfSectionsA)( HINF hinf, UINT index, PSTR buffer, DWORD size, UINT *need );
static void init_function_pointers(void)
{
hSetupAPI = GetModuleHandleA("setupapi.dll");
- pSetupGetField = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
+ /* Nice, pSetupGetField is either A or W depending on the Windows version! The actual test
+ * takes care of this difference */
+ pSetupGetFieldA = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
+ pSetupGetFieldW = (void *)GetProcAddress(hSetupAPI, "pSetupGetField");
pSetupEnumInfSectionsA = (void *)GetProcAddress(hSetupAPI, "SetupEnumInfSectionsA" );
}
@@ -497,7 +501,14 @@ static const char *contents = "[Version]\n"
"[Strings]\n"
"RTMQFE_NAME = \"RTMQFE\"\n";
-static const WCHAR getfield_res[][20] =
+static const CHAR getfield_resA[][20] =
+{
+ "RTMQFE",
+ "%RTMGFE_NAME%",
+ "SP1RTM",
+};
+
+static const WCHAR getfield_resW[][20] =
{
{'R','T','M','Q','F','E',0},
{'%','R','T','M','G','F','E','_','N','A','M','E','%',0},
@@ -509,10 +520,20 @@ static void test_pSetupGetField(void)
UINT err;
BOOL ret;
HINF hinf;
- LPCWSTR field;
+ LPCSTR fieldA;
+ LPCWSTR fieldW;
INFCONTEXT context;
int i;
int len;
+ BOOL unicode = TRUE;
+
+ SetLastError(0xdeadbeef);
+ lstrcmpW(NULL, NULL);
+ if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ win_skip("Using A-functions instead of W\n");
+ unicode = FALSE;
+ }
hinf = test_file_contents( contents, &err );
ok( hinf != NULL, "Expected valid INF file\n" );
@@ -524,23 +545,47 @@ static void test_pSetupGetField(void)
for ( i = 0; i < 3; i++ )
{
- field = pSetupGetField( &context, i );
- ok( field != NULL, "Failed to get field %i\n", i );
- ok( !lstrcmpW( getfield_res[i], field ), "Wrong string returned\n" );
+ if (unicode)
+ {
+ fieldW = pSetupGetFieldW( &context, i );
+ ok( fieldW != NULL, "Failed to get field %i\n", i );
+ ok( !lstrcmpW( getfield_resW[i], fieldW ), "Wrong string returned\n" );
+ }
+ else
+ {
+ fieldA = pSetupGetFieldA( &context, i );
+ ok( fieldA != NULL, "Failed to get field %i\n", i );
+ ok( !lstrcmpA( getfield_resA[i], fieldA ), "Wrong string returned\n" );
+ }
}
- field = pSetupGetField( &context, 3 );
- ok( field != NULL, "Failed to get field 3\n" );
- len = lstrlenW( field );
- ok( len == 511 /* NT4, W2K, XP and W2K3 */ ||
- len == 4096 /* Vista */ ||
- len == 256 /* Win9x and WinME */,
- "Unexpected length, got %d\n", len );
+ if (unicode)
+ {
+ fieldW = pSetupGetFieldW( &context, 3 );
+ ok( fieldW != NULL, "Failed to get field 3\n" );
+ len = lstrlenW( fieldW );
+ ok( len == 511 || /* NT4, W2K, XP and W2K3 */
+ len == 4096, /* Vista */
+ "Unexpected length, got %d\n", len );
- field = pSetupGetField( &context, 4 );
- ok( field == NULL, "Expected NULL, got %p\n", field );
- ok( GetLastError() == ERROR_INVALID_PARAMETER,
- "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
+ fieldW = pSetupGetFieldW( &context, 4 );
+ ok( fieldW == NULL, "Expected NULL, got %p\n", fieldW );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
+ }
+ else
+ {
+ fieldA = pSetupGetFieldA( &context, 3 );
+ ok( fieldA != NULL, "Failed to get field 3\n" );
+ len = lstrlenA( fieldA );
+ ok( len == 511, /* Win9x, WinME */
+ "Unexpected length, got %d\n", len );
+
+ fieldA = pSetupGetFieldA( &context, 4 );
+ ok( fieldA == NULL, "Expected NULL, got %p\n", fieldA );
+ ok( GetLastError() == ERROR_INVALID_PARAMETER,
+ "Expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() );
+ }
SetupCloseInfFile( hinf );
}
@@ -557,14 +602,14 @@ static void test_SetupGetIntField(void)
} keys[] =
{
/* key fields index expected int errorcode */
- { "Key=", "48", 1, 48, ERROR_SUCCESS },
- { "Key=", "48", 0, -1, ERROR_INVALID_DATA },
- { "123=", "48", 0, 123, ERROR_SUCCESS },
- { "Key=", "0x4", 1, 4, ERROR_SUCCESS },
- { "Key=", "Field1", 1, -1, ERROR_INVALID_DATA },
- { "Key=", "Field1,34", 2, 34, ERROR_SUCCESS },
- { "Key=", "Field1,,Field3", 2, 0, ERROR_SUCCESS },
- { "Key=", "Field1,", 2, 0, ERROR_SUCCESS }
+ { "Key", "48", 1, 48, ERROR_SUCCESS },
+ { "Key", "48", 0, -1, ERROR_INVALID_DATA },
+ { "123", "48", 0, 123, ERROR_SUCCESS },
+ { "Key", "0x4", 1, 4, ERROR_SUCCESS },
+ { "Key", "Field1", 1, -1, ERROR_INVALID_DATA },
+ { "Key", "Field1,34", 2, 34, ERROR_SUCCESS },
+ { "Key", "Field1,,Field3", 2, 0, ERROR_SUCCESS },
+ { "Key", "Field1,", 2, 0, ERROR_SUCCESS }
};
unsigned int i;
@@ -579,11 +624,12 @@ static void test_SetupGetIntField(void)
strcpy( buffer, STD_HEADER "[TestSection]\n" );
strcat( buffer, keys[i].key );
+ strcat( buffer, "=" );
strcat( buffer, keys[i].fields );
hinf = test_file_contents( buffer, &err);
ok( hinf != NULL, "Expected valid INF file\n" );
- SetupFindFirstLineA( hinf, "TestSection", "Key", &context );
+ SetupFindFirstLineA( hinf, "TestSection", keys[i].key, &context );
SetLastError( 0xdeadbeef );
intfield = -1;
retb = SetupGetIntField( &context, keys[i].index, &intfield );
diff --git a/rostests/winetests/setupapi/query.c b/rostests/winetests/setupapi/query.c
index bbc2c659724..c77912d3d91 100644
--- a/rostests/winetests/setupapi/query.c
+++ b/rostests/winetests/setupapi/query.c
@@ -167,14 +167,15 @@ static void test_SetupGetInfInformation(void)
broken(GetLastError() == ERROR_FILE_NOT_FOUND) || /* win98 */
broken(GetLastError() == ERROR_PATH_NOT_FOUND) || /* NT4 */
broken(GetLastError() == ERROR_INVALID_NAME) || /* win2k */
- broken(GetLastError() == ERROR_GENERAL_SYNTAX), /* another win2k */
+ broken(GetLastError() == ERROR_GENERAL_SYNTAX), /* another win2k / winMe */
"Expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
ok(size == 0xdeadbeef, "Expected size to remain unchanged\n");
/* try an invalid inf filename */
- /* do not use NULL as absolute inf filename on win9x (crash) */
+ /* do not use NULL as absolute inf filename on win9x/winMe (crash) */
if ((GetLastError() != ERROR_BAD_PATHNAME) && /* win95 */
- (GetLastError() != ERROR_FILE_NOT_FOUND)) /* win98 */
+ (GetLastError() != ERROR_FILE_NOT_FOUND) && /* win98 */
+ (GetLastError() != ERROR_GENERAL_SYNTAX)) /* winMe */
{
size = 0xdeadbeef;
SetLastError(0xbeefcafe);
diff --git a/rostests/winetests/setupapi/stringtable.c b/rostests/winetests/setupapi/stringtable.c
index 59c3f17a327..93701ba5ae9 100644
--- a/rostests/winetests/setupapi/stringtable.c
+++ b/rostests/winetests/setupapi/stringtable.c
@@ -301,6 +301,7 @@ static void test_StringTableLookUpStringEx(void)
ok(!memcmp(buffer, &data, 4), "unexpected data\n");
pStringTableDestroy(table);
+ pStringTableDestroy(table2);
}
static void test_StringTableStringFromId(void)
diff --git a/rostests/winetests/shell32/progman_dde.c b/rostests/winetests/shell32/progman_dde.c
new file mode 100644
index 00000000000..0a7fdaa2102
--- /dev/null
+++ b/rostests/winetests/shell32/progman_dde.c
@@ -0,0 +1,722 @@
+/*
+ * Unit test of the Program Manager DDE Interfaces
+ *
+ * Copyright 2009 Mikey Alexander
+ *
+ * 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
+ */
+
+/* DDE Program Manager Tests
+ * - Covers basic CreateGroup, ShowGroup, DeleteGroup, AddItem, and DeleteItem
+ * functionality
+ * - Todo: Handle CommonGroupFlag
+ * Better AddItem Tests (Lots of parameters to test)
+ * Tests for Invalid Characters in Names / Invalid Parameters
+ */
+
+#include
+#include
+#include
+#include "dde.h"
+#include "ddeml.h"
+#include "winuser.h"
+#include "shlobj.h"
+
+/* Timeout on DdeClientTransaction Call */
+#define MS_TIMEOUT_VAL 1000
+/* # of times to poll for window creation */
+#define PDDE_POLL_NUM 150
+/* time to sleep between polls */
+#define PDDE_POLL_TIME 300
+
+/* Call Info */
+#define DDE_TEST_MISC 0x00010000
+#define DDE_TEST_CREATEGROUP 0x00020000
+#define DDE_TEST_DELETEGROUP 0x00030000
+#define DDE_TEST_SHOWGROUP 0x00040000
+#define DDE_TEST_ADDITEM 0x00050000
+#define DDE_TEST_DELETEITEM 0x00060000
+#define DDE_TEST_COMPOUND 0x00070000
+#define DDE_TEST_CALLMASK 0x00ff0000
+
+#define DDE_TEST_NUMMASK 0x0000ffff
+
+static HRESULT (WINAPI *pSHGetLocalizedName)(LPCWSTR, LPWSTR, UINT, int *);
+static BOOL (WINAPI *pSHGetSpecialFolderPathA)(HWND, LPSTR, int, BOOL);
+static BOOL (WINAPI *pReadCabinetState)(CABINETSTATE *, int);
+
+static void init_function_pointers(void)
+{
+ HMODULE hmod;
+
+ hmod = GetModuleHandleA("shell32.dll");
+ pSHGetLocalizedName = (void*)GetProcAddress(hmod, "SHGetLocalizedName");
+ pSHGetSpecialFolderPathA = (void*)GetProcAddress(hmod, "SHGetSpecialFolderPathA");
+ pReadCabinetState = (void*)GetProcAddress(hmod, "ReadCabinetState");
+ if (!pReadCabinetState)
+ pReadCabinetState = (void*)GetProcAddress(hmod, (LPSTR)651);
+}
+
+static BOOL use_common(void)
+{
+ HMODULE hmod;
+ static BOOL (WINAPI *pIsNTAdmin)(DWORD, LPDWORD);
+
+ /* IsNTAdmin() is available on all platforms. */
+ hmod = LoadLibraryA("advpack.dll");
+ pIsNTAdmin = (void*)GetProcAddress(hmod, "IsNTAdmin");
+
+ if (!pIsNTAdmin(0, NULL))
+ {
+ /* We are definitely not an administrator */
+ FreeLibrary(hmod);
+ return FALSE;
+ }
+ FreeLibrary(hmod);
+
+ /* If we end up here we are on NT4+ as Win9x and WinMe don't have the
+ * notion of administrators (as we need it).
+ */
+
+ /* As of Vista we should always use the users directory. Tests with the
+ * real Administrator account on Windows 7 proved this.
+ *
+ * FIXME: We need a better way of identifying Vista+ as currently this check
+ * also covers Wine and we don't know yet which behavior we want to follow.
+ */
+ if (pSHGetLocalizedName)
+ return FALSE;
+
+ return TRUE;
+}
+
+static char ProgramsDir[MAX_PATH];
+
+static char Group1Title[MAX_PATH] = "Group1";
+static char Group2Title[MAX_PATH] = "Group2";
+static char Group3Title[MAX_PATH] = "Group3";
+static char StartupTitle[MAX_PATH] = "Startup";
+
+static void init_strings(void)
+{
+ char startup[MAX_PATH];
+ char commonprograms[MAX_PATH];
+ char programs[MAX_PATH];
+
+ CABINETSTATE cs;
+
+ if (pSHGetSpecialFolderPathA)
+ {
+ pSHGetSpecialFolderPathA(NULL, programs, CSIDL_PROGRAMS, FALSE);
+ pSHGetSpecialFolderPathA(NULL, commonprograms, CSIDL_COMMON_PROGRAMS, FALSE);
+ pSHGetSpecialFolderPathA(NULL, startup, CSIDL_STARTUP, FALSE);
+ }
+ else
+ {
+ HKEY key;
+ DWORD size;
+ LONG res;
+
+ /* Older Win9x and NT4 */
+
+ RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &key);
+ size = sizeof(programs);
+ RegQueryValueExA(key, "Programs", NULL, NULL, (LPBYTE)&programs, &size);
+ size = sizeof(startup);
+ RegQueryValueExA(key, "Startup", NULL, NULL, (LPBYTE)&startup, &size);
+ RegCloseKey(key);
+
+ RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", &key);
+ size = sizeof(commonprograms);
+ res = RegQueryValueExA(key, "Common Programs", NULL, NULL, (LPBYTE)&commonprograms, &size);
+ RegCloseKey(key);
+ }
+
+ /* ProgramsDir on Vista+ is always the users one (CSIDL_PROGRAMS). Before Vista
+ * it depends on whether the user is an administrator (CSIDL_COMMON_PROGRAMS) or
+ * not (CSIDL_PROGRAMS).
+ */
+ if (use_common())
+ lstrcpyA(ProgramsDir, commonprograms);
+ else
+ lstrcpyA(ProgramsDir, programs);
+
+ memset(&cs, 0, sizeof(cs));
+ pReadCabinetState(&cs, sizeof(cs));
+ if (cs.fFullPathTitle == -1)
+ {
+ lstrcpyA(Group1Title, ProgramsDir);
+ lstrcatA(Group1Title, "\\Group1");
+ lstrcpyA(Group2Title, ProgramsDir);
+ lstrcatA(Group2Title, "\\Group2");
+ lstrcpyA(Group3Title, ProgramsDir);
+ lstrcatA(Group3Title, "\\Group3");
+
+ lstrcpyA(StartupTitle, startup);
+ }
+ else
+ {
+ /* Vista has the nice habit of displaying the full path in English
+ * and the short one localized. CSIDL_STARTUP on Vista gives us the
+ * English version so we have to 'translate' this one.
+ *
+ * MSDN claims it should be used for files not folders but this one
+ * suits our purposes just fine.
+ */
+ if (pSHGetLocalizedName)
+ {
+ WCHAR startupW[MAX_PATH];
+ WCHAR module[MAX_PATH];
+ WCHAR module_expanded[MAX_PATH];
+ WCHAR localized[MAX_PATH];
+ int id;
+
+ MultiByteToWideChar(CP_ACP, 0, startup, -1, startupW, sizeof(startupW)/sizeof(WCHAR));
+ pSHGetLocalizedName(startupW, module, MAX_PATH, &id);
+ ExpandEnvironmentStringsW(module, module_expanded, MAX_PATH);
+ LoadStringW(GetModuleHandleW(module_expanded), id, localized, MAX_PATH);
+
+ WideCharToMultiByte(CP_ACP, 0, localized, -1, StartupTitle, sizeof(StartupTitle), NULL, NULL);
+ }
+ else
+ {
+ lstrcpyA(StartupTitle, (strrchr(startup, '\\') + 1));
+ }
+ }
+}
+
+static HDDEDATA CALLBACK DdeCallback(UINT type, UINT format, HCONV hConv, HSZ hsz1, HSZ hsz2,
+ HDDEDATA hDDEData, ULONG_PTR data1, ULONG_PTR data2)
+{
+ trace("Callback: type=%i, format=%i\n", type, format);
+ return NULL;
+}
+
+/*
+ * Encoded String for Error Messages so that inner failures can determine
+ * what test is failing. Format is: [Code:TestNum]
+ */
+static const char * GetStringFromTestParams(int testParams)
+{
+ int testNum;
+ static char testParamString[64];
+ const char *callId;
+
+ testNum = testParams & DDE_TEST_NUMMASK;
+ switch (testParams & DDE_TEST_CALLMASK)
+ {
+ default:
+ case DDE_TEST_MISC:
+ callId = "MISC";
+ break;
+ case DDE_TEST_CREATEGROUP:
+ callId = "C_G";
+ break;
+ case DDE_TEST_DELETEGROUP:
+ callId = "D_G";
+ break;
+ case DDE_TEST_SHOWGROUP:
+ callId = "S_G";
+ break;
+ case DDE_TEST_ADDITEM:
+ callId = "A_I";
+ break;
+ case DDE_TEST_DELETEITEM:
+ callId = "D_I";
+ break;
+ case DDE_TEST_COMPOUND:
+ callId = "CPD";
+ break;
+ }
+
+ sprintf(testParamString, " [%s:%i]", callId, testNum);
+ return testParamString;
+}
+
+/* Transfer DMLERR's into text readable strings for Error Messages */
+#define DMLERR_TO_STR(x) case x: return#x;
+static const char * GetStringFromError(UINT err)
+{
+ switch (err)
+ {
+ DMLERR_TO_STR(DMLERR_NO_ERROR);
+ DMLERR_TO_STR(DMLERR_ADVACKTIMEOUT);
+ DMLERR_TO_STR(DMLERR_BUSY);
+ DMLERR_TO_STR(DMLERR_DATAACKTIMEOUT);
+ DMLERR_TO_STR(DMLERR_DLL_NOT_INITIALIZED);
+ DMLERR_TO_STR(DMLERR_DLL_USAGE);
+ DMLERR_TO_STR(DMLERR_EXECACKTIMEOUT);
+ DMLERR_TO_STR(DMLERR_INVALIDPARAMETER);
+ DMLERR_TO_STR(DMLERR_LOW_MEMORY);
+ DMLERR_TO_STR(DMLERR_MEMORY_ERROR);
+ DMLERR_TO_STR(DMLERR_NOTPROCESSED);
+ DMLERR_TO_STR(DMLERR_NO_CONV_ESTABLISHED);
+ DMLERR_TO_STR(DMLERR_POKEACKTIMEOUT);
+ DMLERR_TO_STR(DMLERR_POSTMSG_FAILED);
+ DMLERR_TO_STR(DMLERR_REENTRANCY);
+ DMLERR_TO_STR(DMLERR_SERVER_DIED);
+ DMLERR_TO_STR(DMLERR_SYS_ERROR);
+ DMLERR_TO_STR(DMLERR_UNADVACKTIMEOUT);
+ DMLERR_TO_STR(DMLERR_UNFOUND_QUEUE_ID);
+ default:
+ return "Unknown DML Error";
+ }
+}
+
+/* Helper Function to Transfer DdeGetLastError into a String */
+static const char * GetDdeLastErrorStr(DWORD instance)
+{
+ UINT err = DdeGetLastError(instance);
+
+ return GetStringFromError(err);
+}
+
+/* Execute a Dde Command and return the error & result */
+/* Note: Progman DDE always returns a pointer to 0x00000001 on a successful result */
+static void DdeExecuteCommand(DWORD instance, HCONV hConv, const char *strCmd, HDDEDATA *hData, UINT *err, int testParams)
+{
+ HDDEDATA command;
+
+ command = DdeCreateDataHandle(instance, (LPBYTE) strCmd, strlen(strCmd)+1, 0, 0L, 0, 0);
+ ok (command != NULL, "DdeCreateDataHandle Error %s.%s\n",
+ GetDdeLastErrorStr(instance), GetStringFromTestParams(testParams));
+ *hData = DdeClientTransaction((void *) command,
+ -1,
+ hConv,
+ 0,
+ 0,
+ XTYP_EXECUTE,
+ MS_TIMEOUT_VAL,
+ NULL);
+
+ /* hData is technically a pointer, but for Program Manager,
+ * it is NULL (error) or 1 (success)
+ * TODO: Check other versions of Windows to verify 1 is returned.
+ * While it is unlikely that anyone is actually testing that the result is 1
+ * if all versions of windows return 1, Wine should also.
+ */
+ if (*hData == NULL)
+ {
+ *err = DdeGetLastError(instance);
+ }
+ else
+ {
+ *err = DMLERR_NO_ERROR;
+ todo_wine
+ {
+ ok(*hData == (HDDEDATA) 1, "Expected HDDEDATA Handle == 1, actually %p.%s\n",
+ *hData, GetStringFromTestParams(testParams));
+ }
+ }
+ DdeFreeDataHandle(command);
+}
+
+/*
+ * Check if Window is onscreen with the appropriate name.
+ *
+ * Windows are not created synchronously. So we do not know
+ * when and if the window will be created/shown on screen.
+ * This function implements a polling mechanism to determine
+ * creation.
+ * A more complicated method would be to use SetWindowsHookEx.
+ * Since polling worked fine in my testing, no reason to implement
+ * the other. Comments about other methods of determining when
+ * window creation happened were not encouraging (not including
+ * SetWindowsHookEx).
+ */
+static void CheckWindowCreated(const char *winName, int closeWindow, int testParams)
+{
+ HWND window = NULL;
+ int i;
+
+ /* Poll for Window Creation */
+ for (i = 0; window == NULL && i < PDDE_POLL_NUM; i++)
+ {
+ Sleep(PDDE_POLL_TIME);
+ window = FindWindowA(NULL, winName);
+ }
+ ok (window != NULL, "Window \"%s\" was not created in %i seconds - assumed failure.%s\n",
+ winName, PDDE_POLL_NUM*PDDE_POLL_TIME/1000, GetStringFromTestParams(testParams));
+
+ /* Close Window as desired. */
+ if (window != NULL && closeWindow)
+ {
+ SendMessageA(window, WM_SYSCOMMAND, SC_CLOSE, 0);
+ }
+}
+
+/* Check for Existence (or non-existence) of a file or group
+ * When testing for existence of a group, groupName is not needed
+ */
+static void CheckFileExistsInProgramGroups(const char *nameToCheck, int shouldExist, int isGroup,
+ const char *groupName, int testParams)
+{
+ char path[MAX_PATH];
+ DWORD attributes;
+ int len;
+
+ lstrcpyA(path, ProgramsDir);
+
+ len = strlen(path) + strlen(nameToCheck)+1;
+ if (groupName != NULL)
+ {
+ len += strlen(groupName)+1;
+ }
+ ok (len <= MAX_PATH, "Path Too Long.%s\n", GetStringFromTestParams(testParams));
+ if (len <= MAX_PATH)
+ {
+ if (groupName != NULL)
+ {
+ strcat(path, "\\");
+ strcat(path, groupName);
+ }
+ strcat(path, "\\");
+ strcat(path, nameToCheck);
+ attributes = GetFileAttributes(path);
+ if (!shouldExist)
+ {
+ ok (attributes == INVALID_FILE_ATTRIBUTES , "File exists and shouldn't %s.%s\n",
+ path, GetStringFromTestParams(testParams));
+ } else {
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ {
+ ok (FALSE, "Created File %s doesn't exist.%s\n", path, GetStringFromTestParams(testParams));
+ } else if (isGroup) {
+ ok (attributes & FILE_ATTRIBUTE_DIRECTORY, "%s is not a folder (attr=%x).%s\n",
+ path, attributes, GetStringFromTestParams(testParams));
+ } else {
+ ok (attributes & FILE_ATTRIBUTE_ARCHIVE, "Created File %s has wrong attributes (%x).%s\n",
+ path, attributes, GetStringFromTestParams(testParams));
+ }
+ }
+ }
+}
+
+/* Create Group Test.
+ * command and expected_result.
+ * if expected_result is DMLERR_NO_ERROR, test
+ * 1. group was created
+ * 2. window is open
+ */
+static void CreateGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *groupName, const char *windowTitle, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ /* Execute Command & Check Result */
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+ todo_wine
+ {
+ ok (expected_result == error, "CreateGroup %s: Expected Error %s, received %s.%s\n",
+ groupName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+
+ /* No Error */
+ if (error == DMLERR_NO_ERROR)
+ {
+
+ /* Check if Group Now Exists */
+ CheckFileExistsInProgramGroups(groupName, TRUE, TRUE, NULL, testParams);
+ /* Check if Window is Open (polling) */
+ CheckWindowCreated(windowTitle, TRUE, testParams);
+ }
+}
+
+/* Show Group Test.
+ * DDE command, expected_result, and the group name to check for existence
+ * if expected_result is DMLERR_NO_ERROR, test
+ * 1. window is open
+ */
+static void ShowGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *groupName, const char *windowTitle, int closeAfterShowing, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+/* todo_wine... Is expected to fail, wine stubbed functions DO fail */
+/* TODO REMOVE THIS CODE!!! */
+ if (expected_result == DMLERR_NOTPROCESSED)
+ {
+ ok (expected_result == error, "ShowGroup %s: Expected Error %s, received %s.%s\n",
+ groupName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ } else {
+ todo_wine
+ {
+ ok (expected_result == error, "ShowGroup %s: Expected Error %s, received %s.%s\n",
+ groupName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+ }
+
+ if (error == DMLERR_NO_ERROR)
+ {
+ /* Check if Window is Open (polling) */
+ CheckWindowCreated(windowTitle, closeAfterShowing, testParams);
+ }
+}
+
+/* Delete Group Test.
+ * DDE command, expected_result, and the group name to check for existence
+ * if expected_result is DMLERR_NO_ERROR, test
+ * 1. group does not exist
+ */
+static void DeleteGroupTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *groupName, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+ todo_wine
+ {
+ ok (expected_result == error, "DeleteGroup %s: Expected Error %s, received %s.%s\n",
+ groupName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+
+ if (error == DMLERR_NO_ERROR)
+ {
+ /* Check that Group does not exist */
+ CheckFileExistsInProgramGroups(groupName, FALSE, TRUE, NULL, testParams);
+ }
+}
+
+/* Add Item Test
+ * DDE command, expected result, and group and file name where it should exist.
+ * checks to make sure error code matches expected error code
+ * checks to make sure item exists if successful
+ */
+static void AddItemTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *fileName, const char *groupName, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+ todo_wine
+ {
+ ok (expected_result == error, "AddItem %s: Expected Error %s, received %s.%s\n",
+ fileName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+
+ if (error == DMLERR_NO_ERROR)
+ {
+ /* Check that File exists */
+ CheckFileExistsInProgramGroups(fileName, TRUE, FALSE, groupName, testParams);
+ }
+}
+
+/* Delete Item Test.
+ * DDE command, expected result, and group and file name where it should exist.
+ * checks to make sure error code matches expected error code
+ * checks to make sure item does not exist if successful
+ */
+static void DeleteItemTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *fileName, const char *groupName, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+ todo_wine
+ {
+ ok (expected_result == error, "DeleteItem %s: Expected Error %s, received %s.%s\n",
+ fileName, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+
+ if (error == DMLERR_NO_ERROR)
+ {
+ /* Check that File does not exist */
+ CheckFileExistsInProgramGroups(fileName, FALSE, FALSE, groupName, testParams);
+ }
+}
+
+/* Compound Command Test.
+ * not really generic, assumes command of the form:
+ * [CreateGroup ...][AddItem ...][AddItem ...]
+ * All samples I've seen using Compound were of this form (CreateGroup,
+ * AddItems) so this covers minimum expected functionality.
+ */
+static void CompoundCommandTest(DWORD instance, HCONV hConv, const char *command, UINT expected_result,
+ const char *groupName, const char *windowTitle, const char *fileName1,
+ const char *fileName2, int testParams)
+{
+ HDDEDATA hData;
+ UINT error;
+
+ DdeExecuteCommand(instance, hConv, command, &hData, &error, testParams);
+ todo_wine
+ {
+ ok (expected_result == error, "Compound String %s: Expected Error %s, received %s.%s\n",
+ command, GetStringFromError(expected_result), GetStringFromError(error),
+ GetStringFromTestParams(testParams));
+ }
+
+ if (error == DMLERR_NO_ERROR)
+ {
+ /* Check that File exists */
+ CheckFileExistsInProgramGroups(groupName, TRUE, TRUE, NULL, testParams);
+ CheckWindowCreated(windowTitle, FALSE, testParams);
+ CheckFileExistsInProgramGroups(fileName1, TRUE, FALSE, groupName, testParams);
+ CheckFileExistsInProgramGroups(fileName2, TRUE, FALSE, groupName, testParams);
+ }
+}
+
+static void CreateAddItemText(char *itemtext, const char *cmdline, const char *name)
+{
+ lstrcpyA(itemtext, "[AddItem(");
+ lstrcatA(itemtext, cmdline);
+ lstrcatA(itemtext, ",");
+ lstrcatA(itemtext, name);
+ lstrcatA(itemtext, ")]");
+}
+
+/* 1st set of tests */
+static int DdeTestProgman(DWORD instance, HCONV hConv)
+{
+ HDDEDATA hData;
+ UINT error;
+ int testnum;
+ char temppath[MAX_PATH];
+ char f1g1[MAX_PATH], f2g1[MAX_PATH], f3g1[MAX_PATH], f1g3[MAX_PATH], f2g3[MAX_PATH];
+ char itemtext[MAX_PATH + 20];
+ char comptext[2 * (MAX_PATH + 20) + 21];
+
+ testnum = 1;
+ /* Invalid Command */
+ DdeExecuteCommand(instance, hConv, "[InvalidCommand()]", &hData, &error, DDE_TEST_MISC|testnum++);
+ ok (error == DMLERR_NOTPROCESSED, "InvalidCommand(), expected error %s, received %s.\n",
+ GetStringFromError(DMLERR_NOTPROCESSED), GetStringFromError(error));
+
+ /* On Vista+ the files have to exist when adding a link */
+ GetTempPathA(MAX_PATH, temppath);
+ GetTempFileNameA(temppath, "dde", 0, f1g1);
+ GetTempFileNameA(temppath, "dde", 0, f2g1);
+ GetTempFileNameA(temppath, "dde", 0, f3g1);
+ GetTempFileNameA(temppath, "dde", 0, f1g3);
+ GetTempFileNameA(temppath, "dde", 0, f2g3);
+
+ /* CreateGroup Tests (including AddItem, DeleteItem) */
+ CreateGroupTest(instance, hConv, "[CreateGroup(Group1)]", DMLERR_NO_ERROR, "Group1", Group1Title, DDE_TEST_CREATEGROUP|testnum++);
+ CreateAddItemText(itemtext, f1g1, "f1g1Name");
+ AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f1g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++);
+ CreateAddItemText(itemtext, f2g1, "f2g1Name");
+ AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f2g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++);
+ DeleteItemTest(instance, hConv, "[DeleteItem(f2g1Name)]", DMLERR_NO_ERROR, "f2g1Name.lnk", "Group1", DDE_TEST_DELETEITEM|testnum++);
+ CreateAddItemText(itemtext, f3g1, "f3g1Name");
+ AddItemTest(instance, hConv, itemtext, DMLERR_NO_ERROR, "f3g1Name.lnk", "Group1", DDE_TEST_ADDITEM|testnum++);
+ CreateGroupTest(instance, hConv, "[CreateGroup(Group2)]", DMLERR_NO_ERROR, "Group2", Group2Title, DDE_TEST_CREATEGROUP|testnum++);
+ /* Create Group that already exists - same instance */
+ CreateGroupTest(instance, hConv, "[CreateGroup(Group1)]", DMLERR_NO_ERROR, "Group1", Group1Title, DDE_TEST_CREATEGROUP|testnum++);
+
+ /* ShowGroup Tests */
+ ShowGroupTest(instance, hConv, "[ShowGroup(Group1)]", DMLERR_NOTPROCESSED, "Group1", Group1Title, TRUE, DDE_TEST_SHOWGROUP|testnum++);
+ DeleteItemTest(instance, hConv, "[DeleteItem(f3g1Name)]", DMLERR_NO_ERROR, "f3g1Name.lnk", "Group1", DDE_TEST_DELETEITEM|testnum++);
+ ShowGroupTest(instance, hConv, "[ShowGroup(Startup,0)]", DMLERR_NO_ERROR, "Startup", StartupTitle, TRUE, DDE_TEST_SHOWGROUP|testnum++);
+ ShowGroupTest(instance, hConv, "[ShowGroup(Group1,0)]", DMLERR_NO_ERROR, "Group1", Group1Title, FALSE, DDE_TEST_SHOWGROUP|testnum++);
+
+ /* DeleteGroup Test - Note that Window is Open for this test */
+ DeleteGroupTest(instance, hConv, "[DeleteGroup(Group1)]", DMLERR_NO_ERROR, "Group1", DDE_TEST_DELETEGROUP|testnum++);
+
+ /* Compound Execute String Command */
+ lstrcpyA(comptext, "[CreateGroup(Group3)]");
+ CreateAddItemText(itemtext, f1g3, "f1g3Name");
+ lstrcatA(comptext, itemtext);
+ CreateAddItemText(itemtext, f2g3, "f2g3Name");
+ lstrcatA(comptext, itemtext);
+ CompoundCommandTest(instance, hConv, comptext, DMLERR_NO_ERROR, "Group3", Group3Title, "f1g3Name.lnk", "f2g3Name.lnk", DDE_TEST_COMPOUND|testnum++);
+
+ DeleteGroupTest(instance, hConv, "[DeleteGroup(Group3)]", DMLERR_NO_ERROR, "Group3", DDE_TEST_DELETEGROUP|testnum++);
+
+ /* Full Parameters of Add Item */
+ /* AddItem(CmdLine[,Name[,IconPath[,IconIndex[,xPos,yPos[,DefDir[,HotKey[,fMinimize[fSeparateSpace]]]]]]]) */
+
+ DeleteFileA(f1g1);
+ DeleteFileA(f2g1);
+ DeleteFileA(f3g1);
+ DeleteFileA(f1g3);
+ DeleteFileA(f2g3);
+
+ return testnum;
+}
+
+/* 2nd set of tests - 2nd connection */
+static void DdeTestProgman2(DWORD instance, HCONV hConv, int testnum)
+{
+ /* Create Group that already exists on a separate connection */
+ CreateGroupTest(instance, hConv, "[CreateGroup(Group2)]", DMLERR_NO_ERROR, "Group2", Group2Title, DDE_TEST_CREATEGROUP|testnum++);
+ DeleteGroupTest(instance, hConv, "[DeleteGroup(Group2)]", DMLERR_NO_ERROR, "Group2", DDE_TEST_DELETEGROUP|testnum++);
+}
+
+START_TEST(progman_dde)
+{
+ DWORD instance = 0;
+ UINT err;
+ HSZ hszProgman;
+ HCONV hConv;
+ int testnum;
+
+ init_function_pointers();
+ init_strings();
+
+ /* Initialize DDE Instance */
+ err = DdeInitialize(&instance, DdeCallback, APPCMD_CLIENTONLY, 0);
+ ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err));
+
+ /* Create Connection */
+ hszProgman = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI);
+ ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance));
+ hConv = DdeConnect(instance, hszProgman, hszProgman, NULL);
+ ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n");
+ /* Seeing failures on early versions of Windows Connecting to progman, exit if connection fails */
+ if (hConv == NULL)
+ {
+ ok (DdeUninitialize(instance), "DdeUninitialize failed\n");
+ return;
+ }
+
+ /* Run Tests */
+ testnum = DdeTestProgman(instance, hConv);
+
+ /* Cleanup & Exit */
+ ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance));
+ ok (DdeUninitialize(instance), "DdeUninitialize failed\n");
+
+ /* 2nd Instance (Followup Tests) */
+ /* Initialize DDE Instance */
+ instance = 0;
+ err = DdeInitialize(&instance, DdeCallback, APPCMD_CLIENTONLY, 0);
+ ok (err == DMLERR_NO_ERROR, "DdeInitialize Error %s\n", GetStringFromError(err));
+
+ /* Create Connection */
+ hszProgman = DdeCreateStringHandle(instance, "PROGMAN", CP_WINANSI);
+ ok (hszProgman != NULL, "DdeCreateStringHandle Error %s\n", GetDdeLastErrorStr(instance));
+ hConv = DdeConnect(instance, hszProgman, hszProgman, NULL);
+ ok (hConv != NULL, "DdeConnect Error %s\n", GetDdeLastErrorStr(instance));
+ ok (DdeFreeStringHandle(instance, hszProgman), "DdeFreeStringHandle failure\n");
+
+ /* Run Tests */
+ DdeTestProgman2(instance, hConv, testnum);
+
+ /* Cleanup & Exit */
+ ok (DdeDisconnect(hConv), "DdeDisonnect Error %s\n", GetDdeLastErrorStr(instance));
+ ok (DdeUninitialize(instance), "DdeUninitialize failed\n");
+}
diff --git a/rostests/winetests/shell32/shell32.rbuild b/rostests/winetests/shell32/shell32.rbuild
index 5d7c99a5aa1..81f764b220e 100644
--- a/rostests/winetests/shell32/shell32.rbuild
+++ b/rostests/winetests/shell32/shell32.rbuild
@@ -18,6 +18,7 @@
appbar.c
autocomplete.c
generated.c
+ progman_dde.c
shelllink.c
shellpath.c
shlexec.c
diff --git a/rostests/winetests/shell32/shelllink.c b/rostests/winetests/shell32/shelllink.c
index 2f20200c67a..25354718601 100755
--- a/rostests/winetests/shell32/shelllink.c
+++ b/rostests/winetests/shell32/shelllink.c
@@ -275,6 +275,20 @@ static void test_get_set(void)
ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r);
ok(lstrcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
+ strcpy(buffer,"garbage");
+ r = IShellLinkA_SetArguments(sl, NULL);
+ ok(SUCCEEDED(r), "SetArguments failed (0x%08x)\n", r);
+ r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
+ ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r);
+ ok(!buffer[0] || lstrcmp(buffer,str)==0, "GetArguments returned '%s'\n", buffer);
+
+ strcpy(buffer,"garbage");
+ r = IShellLinkA_SetArguments(sl, "");
+ ok(SUCCEEDED(r), "SetArguments failed (0x%08x)\n", r);
+ r = IShellLinkA_GetArguments(sl, buffer, sizeof(buffer));
+ ok(SUCCEEDED(r), "GetArguments failed (0x%08x)\n", r);
+ ok(!buffer[0], "GetArguments returned '%s'\n", buffer);
+
/* Test Getting / Setting showcmd */
i=0xdeadbeef;
r = IShellLinkA_GetShowCmd(sl, &i);
diff --git a/rostests/winetests/shell32/shlexec.c b/rostests/winetests/shell32/shlexec.c
index fa5a2162027..fd712528bd8 100755
--- a/rostests/winetests/shell32/shlexec.c
+++ b/rostests/winetests/shell32/shlexec.c
@@ -1095,7 +1095,7 @@ static void test_find_executable(void)
* like '.mpeg', etc.
* Also it means we cannot do any other test.
*/
- trace("FindExecutable() is broken -> skipping 4+ character extension tests\n");
+ win_skip("FindExecutable() is broken -> not running 4+ character extension tests\n");
return;
}
diff --git a/rostests/winetests/shell32/shlfileop.c b/rostests/winetests/shell32/shlfileop.c
index c24a6f2bf0d..a035567b645 100644
--- a/rostests/winetests/shell32/shlfileop.c
+++ b/rostests/winetests/shell32/shlfileop.c
@@ -965,9 +965,10 @@ static void test_copy(void)
set_curr_dir_path(from, "test1.txt\0test2.txt\0");
set_curr_dir_path(to, "test3.txt\0");
retval = SHFileOperation(&shfo);
- if (retval == DE_FLDDESTISFILE)
+ if (retval == DE_FLDDESTISFILE || /* Vista and W2K8 */
+ retval == DE_INVALIDFILES) /* Win7 */
{
- /* Vista and W2K8 (broken or new behavior ?) */
+ /* Most likely new behavior */
ok(!shfo.fAnyOperationsAborted, "Didn't expect aborted operations\n");
}
else
diff --git a/rostests/winetests/shell32/shlfolder.c b/rostests/winetests/shell32/shlfolder.c
index 903c0894f9b..435942ba2bb 100644
--- a/rostests/winetests/shell32/shlfolder.c
+++ b/rostests/winetests/shell32/shlfolder.c
@@ -472,7 +472,8 @@ static void test_GetDisplayName(void)
/* WinXP and up store the filenames as both ANSI and UNICODE in the pidls */
if (pidlLast->mkid.cb >= 76) {
ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) ||
- (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)), /* Vista */
+ (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)) || /* Vista */
+ (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)), /* Win7 */
"Filename should be stored as wchar-string at this position!\n");
}
@@ -585,6 +586,7 @@ static void test_GetDisplayName(void)
ok (!lstrcmpiW(wszTestFile, wszTestFile2), "GetDisplayNameOf returns incorrect path!\n");
}
+ ILFree(pidlTestFile);
IShellFolder_Release(psfDesktop);
IShellFolder_Release(psfPersonal);
}
@@ -646,8 +648,12 @@ static void test_CallForAttributes(void)
* key. So the test will return at this point, if run on wine.
*/
lResult = RegOpenKeyExW(HKEY_CLASSES_ROOT, wszMyDocumentsKey, 0, KEY_WRITE|KEY_READ, &hKey);
- ok (lResult == ERROR_SUCCESS, "RegOpenKeyEx failed! result: %08x\n", lResult);
+ ok (lResult == ERROR_SUCCESS ||
+ lResult == ERROR_ACCESS_DENIED,
+ "RegOpenKeyEx failed! result: %08x\n", lResult);
if (lResult != ERROR_SUCCESS) {
+ if (lResult == ERROR_ACCESS_DENIED)
+ skip("Not enough rights to open the registry key\n");
IMalloc_Free(ppM, pidlMyDocuments);
IShellFolder_Release(psfDesktop);
return;
@@ -1524,18 +1530,38 @@ static void test_ITEMIDLIST_format(void) {
pFileStructA->uFileTime == pFileStructW->uTime,
"Last write time should match creation time!\n");
- ok (pFileStructA->uFileDate == pFileStructW->uDate2 &&
- pFileStructA->uFileTime == pFileStructW->uTime2,
- "Last write time should match last access time!\n");
+ /* On FAT filesystems the last access time is midnight
+ local time, so the values of uDate2 and uTime2 will
+ depend on the local timezone. If the times are exactly
+ equal then the dates should be identical for both FAT
+ and NTFS as no timezone is more than 1 day away from UTC.
+ */
+ if (pFileStructA->uFileTime == pFileStructW->uTime2)
+ {
+ ok (pFileStructA->uFileDate == pFileStructW->uDate2,
+ "Last write date and time should match last access date and time!\n");
+ }
+ else
+ {
+ /* Filesystem may be FAT. Check date within 1 day
+ and seconds are zero. */
+ trace ("Filesystem may be FAT. Performing less strict atime test.\n");
+ ok ((pFileStructW->uTime2 & 0x1F) == 0,
+ "Last access time on FAT filesystems should have zero seconds.\n");
+ /* TODO: Perform check for date being within one day.*/
+ }
ok (!lstrcmpW(wszFile[i], pFileStructW->wszName) ||
- !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 22)), /* Vista */
+ !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 22)) || /* Vista */
+ !lstrcmpW(wszFile[i], (WCHAR *)(pFileStructW->abFooBar2 + 26)), /* Win7 */
"The filename should be stored in unicode at this position!\n");
}
}
pILFree(pidlFile);
}
+
+ IShellFolder_Release(psfPersonal);
}
static void testSHGetFolderPathAndSubDirA(void)
diff --git a/rostests/winetests/shell32/testlist.c b/rostests/winetests/shell32/testlist.c
index 0c78417d4f6..72d9cef3e2f 100644
--- a/rostests/winetests/shell32/testlist.c
+++ b/rostests/winetests/shell32/testlist.c
@@ -9,6 +9,7 @@
extern void func_appbar(void);
extern void func_autocomplete(void);
extern void func_generated(void);
+extern void func_progman_dde(void);
extern void func_shelllink(void);
extern void func_shellpath(void);
extern void func_shfldr_netplaces(void);
@@ -24,6 +25,7 @@ const struct test winetest_testlist[] =
{ "appbar", func_appbar },
{ "autocomplete", func_autocomplete },
{ "generated", func_generated },
+ { "progman_dde", func_progman_dde },
{ "shelllink", func_shelllink },
{ "shellpath", func_shellpath },
{ "shfldr_netplaces", func_shfldr_netplaces },
diff --git a/rostests/winetests/usp10/usp10.c b/rostests/winetests/usp10/usp10.c
index 1eefee0509a..5795e909cd6 100644
--- a/rostests/winetests/usp10/usp10.c
+++ b/rostests/winetests/usp10/usp10.c
@@ -27,11 +27,7 @@
#include
#include
-#include
-#include
-#include
-#include
-#include
+#include
#include
static void test_ScriptShape(HDC hdc)
@@ -67,9 +63,10 @@ static void test_ScriptShape(HDC hdc)
ok(hr == E_PENDING, "ScriptShape should return E_PENDING not %08x\n", hr);
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, NULL, attrs, &nb);
- ok(!hr ||
- hr == E_INVALIDARG, /* Vista, W2K8 */
- "ScriptShape should return S_OK or E_INVALIDARG, not %08x\n", hr);
+ ok(broken(hr == S_OK) ||
+ hr == E_INVALIDARG || /* Vista, W2K8 */
+ hr == E_FAIL, /* WIN7 */
+ "ScriptShape should return E_FAIL or E_INVALIDARG, not %08x\n", hr);
ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n");
hr = ScriptShape(hdc, &sc, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb);
@@ -83,17 +80,19 @@ static void test_ScriptShape(HDC hdc)
ok(hr == E_INVALIDARG, "ScriptPlace should return E_INVALIDARG not %08x\n", hr);
hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, NULL);
- ok(hr == E_PENDING ||
- hr == E_INVALIDARG, /* Vista, W2K8 */
- "ScriptPlace should return E_PENDING or E_INVALIDARG, not %08x\n", hr);
+ ok(broken(hr == E_PENDING) ||
+ hr == E_INVALIDARG || /* Vista, W2K8 */
+ hr == E_FAIL, /* WIN7 */
+ "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr);
hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL);
ok(hr == E_PENDING, "ScriptPlace should return E_PENDING not %08x\n", hr);
hr = ScriptPlace(NULL, &sc, glyphs, 4, attrs, &items[0].a, widths, NULL, abc);
- ok(hr == E_PENDING ||
- hr == E_INVALIDARG, /* Vista, W2K8 */
- "ScriptPlace should return E_PENDING or E_INVALIDARG, not %08x\n", hr);
+ ok(broken(hr == E_PENDING) ||
+ hr == E_INVALIDARG || /* Vista, W2K8 */
+ hr == E_FAIL, /* WIN7 */
+ "ScriptPlace should return E_FAIL or E_INVALIDARG, not %08x\n", hr);
hr = ScriptPlace(hdc, &sc, glyphs, 4, attrs, &items[0].a, widths, offset, NULL);
ok(!hr, "ScriptPlace should return S_OK not %08x\n", hr);
@@ -339,14 +338,14 @@ static void test_ScriptGetCMap(HDC hdc, unsigned short pwOutGlyphs[256])
/* Set psc to NULL, to be able to check if a pointer is returned in psc */
psc = NULL;
- hr = ScriptGetCMap(NULL, &psc, NULL, 0, 0, NULL);
- ok( hr == E_PENDING, "(NULL,&psc,NULL,0,0NULL), expected E_PENDING, "
+ hr = ScriptGetCMap(NULL, &psc, TestItem1, cInChars, 0, pwOutGlyphs3);
+ ok( hr == E_PENDING, "(NULL,&psc,NULL,0,0,NULL), expected E_PENDING, "
"got %08x\n", hr);
ok( psc == NULL, "Expected psc to be NULL, got %p\n", psc);
/* Set psc to NULL but add hdc, to be able to check if a pointer is returned in psc */
psc = NULL;
- hr = ScriptGetCMap(hdc, &psc, NULL, 0, 0, NULL);
+ hr = ScriptGetCMap(hdc, &psc, TestItem1, cInChars, 0, pwOutGlyphs3);
ok( hr == S_OK, "ScriptGetCMap(NULL,&psc,NULL,0,0,NULL), expected S_OK, "
"got %08x\n", hr);
ok( psc != NULL, "ScritpGetCMap expected psc to be not NULL\n");
@@ -1058,6 +1057,11 @@ static void test_ScriptGetGlyphABCWidth(HDC hdc)
ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', NULL);
+ ok(broken(hr == E_PENDING) ||
+ hr == E_INVALIDARG, /* WIN7 */
+ "expected E_INVALIDARG, got 0x%08x\n", hr);
+
+ hr = ScriptGetGlyphABCWidth(NULL, &sc, 'a', &abc);
ok(hr == E_PENDING, "expected E_PENDING, got 0x%08x\n", hr);
if (0) { /* crashes on WinXP */
@@ -1169,7 +1173,7 @@ static void test_digit_substitution(void)
LGRPID_ARMENIAN
};
HMODULE hKernel32;
- static BOOL (WINAPI * pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROC,LGRPID,DWORD,LONG_PTR);
+ static BOOL (WINAPI * pEnumLanguageGroupLocalesA)(LANGGROUPLOCALE_ENUMPROCA,LGRPID,DWORD,LONG_PTR);
hKernel32 = GetModuleHandleA("kernel32.dll");
pEnumLanguageGroupLocalesA = (void*)GetProcAddress(hKernel32, "EnumLanguageGroupLocalesA");
diff --git a/rostests/winetests/winmm/mci.c b/rostests/winetests/winmm/mci.c
index 5f8698507a8..6607e17c99f 100644
--- a/rostests/winetests/winmm/mci.c
+++ b/rostests/winetests/winmm/mci.c
@@ -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 "wine/test.h"
-#include "winuser.h"
+#include
+#include "windows.h"
#include "mmsystem.h"
+#include "mmreg.h"
+#include "wine/test.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];
- HWND hwnd;
+ memset(buf, 0, sizeof(buf));
+ test_notification(hwnd, "-prior to any command-", 0);
- hwnd = CreateWindowExA(0, "static", "winmm test", WS_POPUP, 0,0,100,100,
- 0, 0, 0, NULL);
+ 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(command_open, NULL, 0, NULL);
- ok(!err,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_open, err);
+ 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,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_close_my, err);
+ 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);
- 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("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,"mciSendString(%s, NULL, 0 , NULL) returned error: %d\n", command_close_all, err);
+ 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,"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);
+ 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,"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);
+ 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);
- 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);
+ 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);
+ 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);
}
diff --git a/rostests/winetests/wldap32/parse.c b/rostests/winetests/wldap32/parse.c
index d4b5de2fadf..0f22d238674 100644
--- a/rostests/winetests/wldap32/parse.c
+++ b/rostests/winetests/wldap32/parse.c
@@ -57,8 +57,13 @@ static void test_ldap_parse_sort_control( LDAP *ld )
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 );