Hi.

I ask for comments before sending this as 2 or 3 patches.

- Correct 2 failing tests on win9x
- Add Documentation for GetPrinterDriverDirectoryW/A (c2man)


- Add Function "validate_envW" to validate the user-supplied
  Printing Environment (respect "Windows Version" - Setting)
- Change GetPrinterDriverDirectoryW to Report the correct NT-Path
  or the win9x-Path on top of "validate_envW"


- Fix 2 Bugs in GetPrinterDriverDirectoryA
  (invalid Result from "needed" and possible Read from 0x00000000)
- 2 Tests are now working in Wine




"validate_envW" will be used by more Functions later.
(WINSPOOL_OpenDriverReg as Example)


-- 
By By ...
      ... Detlef
Index: dlls/winspool/info.c
===================================================================
RCS file: /home/wine/wine/dlls/winspool/info.c,v
retrieving revision 1.130
diff -u -r1.130 info.c
--- dlls/winspool/info.c	24 Oct 2005 15:03:02 -0000	1.130
+++ dlls/winspool/info.c	22 Nov 2005 23:53:20 -0000
@@ -131,6 +131,14 @@
                                                'D','e','v','i','c','e','s',0};
 
 static const WCHAR DefaultEnvironmentW[] = {'W','i','n','e',0};
+static const WCHAR env_x86W[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0};
+static const WCHAR env_win40W[] = {'W','i','n','d','o','w','s',' ','4','.','0',0};
+static const WCHAR subdir_x86W[] = {'w','3','2','x','8','6',0};
+static const WCHAR subdir_win40W[] = {'w','i','n','4','0',0};
+static const WCHAR spooldriversW[] = {'\\','s','p','o','o','l','\\','D','R','I','V','E','R','S','\\',0};
+
+static const LPCWSTR env_namesW[] =  {NULL, env_win40W, env_x86W };
+static const LPCWSTR env_subdirW[] = {NULL, subdir_win40W, subdir_x86W };
 
 static const WCHAR Configuration_FileW[] = {'C','o','n','f','i','g','u','r','a','t',
 				      'i','o','n',' ','F','i','l','e',0};
@@ -605,6 +613,65 @@
 
 }
 
+/******************************************************************
+ *  validate the user-supplied printing-environment [internal]
+ *
+ * PARAMS
+ *  LPCWSTR env  [I] PTR to environment-String or NULL
+ *
+ * RETURNS
+ *  Failure:  0
+ *  Success:  > 0 (ENVIRONMENT_WIN40 or ENVIRONMENT_X86)
+ *
+ * NOTES
+ *  SetLastEror(ERROR_INVALID_ENVIRONMENT) is called on Failure
+ *  
+ */
+
+static DWORD validate_envW(LPCWSTR env)
+{
+    DWORD   rc = 0;
+
+    TRACE("testing %s\n", debugstr_w(env));
+
+    if (env) {
+        /* ENVIRONMENT_X86 is valid on NT only */
+        rc = ENVIRONMENT_X86;
+        while((rc > 0) && (lstrcmpiW(env, env_namesW[rc]) != 0)) {
+            rc--;
+        }
+        if (rc == 0) {
+            FIXME("unsupported Environment: %s\n", debugstr_w(env));
+        }
+        /* ENVIRONMENT_X86 is valid on NT only */
+        if ((rc > ENVIRONMENT_WIN40) && (GetVersion() & 0x80000000))  rc = 0;
+    }
+    else
+    {
+        OSVERSIONINFOW ver;
+        ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+
+        if(GetVersionExW(&ver)) {
+            switch (ver.dwPlatformId) {
+                 case VER_PLATFORM_WIN32s:
+                      ERR("win32 style printing used with 16 bits app, try specifying 'win95' Windows version\n");
+                      break;
+                 case VER_PLATFORM_WIN32_NT:
+                      rc = ENVIRONMENT_X86;
+                      break;
+                 default:
+                      rc = ENVIRONMENT_WIN40;
+                      break;
+            }
+        }
+    }
+
+    TRACE("using environment %ld: %s\n", rc, debugstr_w(env_namesW[rc]));
+    if (! rc)  SetLastError(ERROR_INVALID_ENVIRONMENT);
+    return rc;
+}
+
+
 
 /******************************************************************
  *  get_opened_printer_entry
@@ -3228,49 +3295,107 @@
 
 /*****************************************************************************
  *       GetPrinterDriverDirectoryW  [EMAIL PROTECTED]
+ *
+ * Return the PATH for the Printer-Drivers (UNICODE)
+ *
+ * PARAMS
+ *   pName            [I] Servername (NT only) or NULL (local Computer)
+ *   pEnvironment     [I] Printing-Environment (see below) or NULL
+ *   Level            [I] Structure-Level (must be 1)
+ *   pDriverDirectory [O] PTR to Buffer that receives the Result
+ *   cbBuf            [I] Size of Buffer at pDriverDirectory
+ *   pcbNeeded        [O] PTR to DWORD that receives the size in Bytes used / 
+ *                        required for pDriverDirectory
+ *
+ *
+ * RETURNS
+ *   Success: TRUE  and in pcbNeeded the Bytes used in pDriverDirectory
+ *   Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory,
+ *   if cbBuf is to small
+ *
+ * EXPECTED RESULTS
+ *   win9x:              "%winsysdir%"
+ *   NT(Windows 4.0):    "%winsysdir%\spool\DRIVERS\win40"
+ *   NT(Windows NT x86): "%winsysdir%\spool\DRIVERS\w32x86"
+ *
+ * FIXME
+ *   pName != NULL not supported
+ *   
+ * NOTES
+ *   Supported Printing-Environments: 
+ *   "Windows 4.0" (win9x) and "Windows NT x86"  (NT on i386 and above)
+ *
  */
 BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
 				       DWORD Level, LPBYTE pDriverDirectory,
 				       DWORD cbBuf, LPDWORD pcbNeeded)
 {
-    DWORD needed;
+    DWORD needed, env_index;
 
     TRACE("(%s, %s, %ld, %p, %ld, %p)\n", debugstr_w(pName), 
           debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded);
     if(pName != NULL) {
-        FIXME("pName = `%s' - unsupported\n", debugstr_w(pName));
-	SetLastError(ERROR_INVALID_PARAMETER);
-	return FALSE;
-    }
-    if(pEnvironment != NULL) {
-        FIXME("pEnvironment = `%s' - unsupported\n", debugstr_w(pEnvironment));
-	SetLastError(ERROR_INVALID_ENVIRONMENT);
-	return FALSE;
+        FIXME("pName unsupported: %s\n", debugstr_w(pName));
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
     }
-    if(Level != 1)  /* win95 ignores this so we just carry on */
+    env_index = validate_envW(pEnvironment);
+    if(!env_index) return FALSE;  /* pEnvironment invalid or unsupported */
+
+    if(Level != 1) {
+        /* this is a failure on NT, but ignored in win9x */
+        if(GetVersion() < 0x80000000) {
+            SetLastError(ERROR_INVALID_LEVEL);
+            return FALSE;
+        }
         WARN("Level = %ld - assuming 1\n", Level);
+    }
 
-    /* FIXME should read from registry */
-    needed = GetSystemDirectoryW( (LPWSTR)pDriverDirectory, cbBuf/sizeof(WCHAR));
-    /* GetSystemDirectoryW returns number of TCHAR without '\0' 
-     * adjust this now
-     */
-    needed++;
-    needed*=sizeof(WCHAR);
+    /* GetSystemDirectoryW returns number of WCHAR including the '\0' */
+    needed = GetSystemDirectoryW(NULL, 0);
+    /* add the Size for the Subdirectory on NT */
+    if(GetVersion() < 0x80000000) {
+        needed += lstrlenW(spooldriversW);
+        needed += lstrlenW(env_subdirW[env_index]);
+    }
+    needed*=sizeof(WCHAR);  /* return size in Bytes */
 
     if(pcbNeeded)
         *pcbNeeded = needed;
-    TRACE("required <%08lx>\n", *pcbNeeded);
+    TRACE("required: 0x%lx/%ld\n", needed, needed);
     if(needed > cbBuf) {
         SetLastError(ERROR_INSUFFICIENT_BUFFER);
-	return FALSE;
+        return FALSE;
+    }
+    if((pcbNeeded == NULL) && (GetVersion() < 0x80000000)) {
+        /* this is a failure on NT, but ignored in win9x */
+        SetLastError(RPC_X_NULL_REF_POINTER);
+        return FALSE;
+    }
+    if(pDriverDirectory == NULL) {
+        /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */
+        SetLastError((GetVersion() < 0x80000000) ? 
+                        ERROR_INVALID_USER_BUFFER : ERROR_INVALID_PARAMETER);
+        return FALSE;
     }
+    
+    GetSystemDirectoryW((LPWSTR) pDriverDirectory, cbBuf/sizeof(WCHAR));
+    /* add the Subdirectories on NT */
+    if(GetVersion() < 0x80000000) {
+        lstrcatW((LPWSTR) pDriverDirectory, spooldriversW);
+        lstrcatW((LPWSTR) pDriverDirectory, env_subdirW[env_index]);
+    }
+    TRACE(" => %s\n", debugstr_w((LPWSTR) pDriverDirectory));
     return TRUE;
 }
 
 
 /*****************************************************************************
  *       GetPrinterDriverDirectoryA  [EMAIL PROTECTED]
+ *
+ * Return the PATH for the Printer-Drivers (ANSI)
+ *
+ * See GetPrinterDriverDirectoryW.
  */
 BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment,
 				       DWORD Level, LPBYTE pDriverDirectory,
@@ -3293,7 +3418,7 @@
 				      (LPBYTE)driverDirectoryW, len, &pcbNeededW );
     if (ret) {
         DWORD needed;
-        needed = 1 + WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1, 
+        needed =  WideCharToMultiByte( CP_ACP, 0, driverDirectoryW, -1, 
                                    (LPSTR)pDriverDirectory, cbBuf, NULL, NULL);
         if(pcbNeeded)
             *pcbNeeded = needed;
@@ -3301,7 +3426,7 @@
     } else 
         if(pcbNeeded) *pcbNeeded = pcbNeededW * sizeof(CHAR)/sizeof(WCHAR);
 
-    TRACE("provided<%ld> required <%ld>\n", cbBuf, *pcbNeeded);
+    TRACE("required: %ld/0x%lx\n", pcbNeeded ? *pcbNeeded : -1, pcbNeeded ? *pcbNeeded : -1);
 
     HeapFree( GetProcessHeap(), 0, driverDirectoryW );
     RtlFreeUnicodeString(&environmentW);
Index: dlls/winspool/wspool.h
===================================================================
RCS file: /home/wine/wine/dlls/winspool/wspool.h,v
retrieving revision 1.1
diff -u -r1.1 wspool.h
--- dlls/winspool/wspool.h	12 Jul 2005 17:01:44 -0000	1.1
+++ dlls/winspool/wspool.h	22 Nov 2005 23:53:20 -0000
@@ -29,3 +29,8 @@
 
 #define FILENAME_DIALOG  100
 #define EDITBOX 201
+
+
+#define ENVIRONMENT_WIN40 1
+#define ENVIRONMENT_X86   2
+
Index: dlls/winspool/tests/info.c
===================================================================
RCS file: /home/wine/wine/dlls/winspool/tests/info.c,v
retrieving revision 1.11
diff -u -r1.11 info.c
--- dlls/winspool/tests/info.c	15 Nov 2005 16:51:45 -0000	1.11
+++ dlls/winspool/tests/info.c	22 Nov 2005 23:53:20 -0000
@@ -160,20 +160,20 @@
     ok( !res , "expected result == 0, got %d\n", res);
     ok( cbBuf == pcbNeeded, "pcbNeeded set to %ld instead of %ld\n",
                             pcbNeeded, cbBuf);
-    todo_wine {
+
     ok( ERROR_INSUFFICIENT_BUFFER == GetLastError(),
         "last error set to %ld instead of ERROR_INSUFFICIENT_BUFFER\n",
         GetLastError());
-    }
+
  
     SetLastError(0x00dead00);
     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, &pcbNeeded);
     ok( (!res && ERROR_INVALID_USER_BUFFER == GetLastError()) || 
+        ( res && ERROR_SUCCESS == GetLastError()) ||
         ( res && ERROR_INVALID_PARAMETER == GetLastError()) ,
-         "expected either result == 0 and "
-         "last error == ERROR_INVALID_USER_BUFFER "
-         "or result != 0 and last error == ERROR_INVALID_PARAMETER "
-         "got result %d and last error == %ld\n", res, GetLastError());
+         "returned %d with lasterror=%ld (expected "
+         "'0' with ERROR_INVALID_USER_BUFFER or '!= 0' with ERROR_SUCCESS or "
+         "'!= 0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
 
     SetLastError(0x00dead00);
     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, buffer, cbBuf, NULL);
@@ -185,11 +185,11 @@
     SetLastError(0x00dead00);
     res = GetPrinterDriverDirectoryA( NULL, NULL, 1, NULL, cbBuf, NULL);
     ok( (!res && RPC_X_NULL_REF_POINTER == GetLastError()) || 
+        ( res && ERROR_SUCCESS == GetLastError()) ||
         ( res && ERROR_INVALID_PARAMETER == GetLastError()) ,
-         "expected either result == 0 and "
-         "last error == RPC_X_NULL_REF_POINTER "
-         "or result != 0 and last error == ERROR_INVALID_PARAMETER "
-         "got result %d and last error == %ld\n", res, GetLastError());
+         "returned %d with lasterror=%ld (expected "
+         "'0' with RPC_X_NULL_REF_POINTER or '!= 0' with ERROR_SUCCESS or "
+         "'!= 0' with ERROR_INVALID_PARAMETER)\n", res, GetLastError());
 
     /* with a valid buffer, but level is to large */
     buffer[0] = '\0';
@@ -226,11 +226,11 @@
                                         buffer, cbBuf*2, &pcbNeeded);
     }
     
-    todo_wine{
+    
     ok(res && buffer[0], "returned %d with " \
-        "lasterror=%ld and len=%d (expected '0' with 'len > 0')\n", 
+        "lasterror=%ld and len=%d (expected '1' with 'len > 0')\n", 
         res, GetLastError(), lstrlenA((char *)buffer));
-    }
+
 
     buffer[0] = '\0';
     SetLastError(0x00dead00);


Reply via email to